Favivon - Correção

This commit is contained in:
2026-05-30 19:59:39 -03:00
parent 76ddaa815d
commit d7dfd221f0
32859 changed files with 5459654 additions and 404 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+376
View File
@@ -0,0 +1,376 @@
import { Vector3, Scene, PerspectiveCamera, OrthographicCamera } from 'three';
import { EventDispatcher } from './EventDispatcher';
import { StandardControlsEventMap } from './StandardControlsEventMap';
type Camera = OrthographicCamera | PerspectiveCamera;
/**
*
* @param {CamOrthographicCamera | PerspectiveCameraera} camera Virtual camera used in the scene
* @param {HTMLElement=null} domElement Renderer's dom element
* @param {Scene=null} scene The scene to be rendered
*/
declare class ArcballControls extends EventDispatcher<StandardControlsEventMap> {
private camera;
private domElement;
private scene;
private mouseActions;
private _mouseOp;
private _v2_1;
private _v3_1;
private _v3_2;
private _m4_1;
private _m4_2;
private _quat;
private _translationMatrix;
private _rotationMatrix;
private _scaleMatrix;
private _rotationAxis;
private _cameraMatrixState;
private _cameraProjectionState;
private _fovState;
private _upState;
private _zoomState;
private _nearPos;
private _farPos;
private _gizmoMatrixState;
private _up0;
private _zoom0;
private _fov0;
private _initialNear;
private _nearPos0;
private _initialFar;
private _farPos0;
private _cameraMatrixState0;
private _gizmoMatrixState0;
private _button;
private _touchStart;
private _touchCurrent;
private _input;
private _switchSensibility;
private _startFingerDistance;
private _currentFingerDistance;
private _startFingerRotation;
private _currentFingerRotation;
private _devPxRatio;
private _downValid;
private _nclicks;
private _downEvents;
private _clickStart;
private _maxDownTime;
private _maxInterval;
private _posThreshold;
private _movementThreshold;
private _currentCursorPosition;
private _startCursorPosition;
private _grid;
private _gridPosition;
private _gizmos;
private _curvePts;
private _timeStart;
private _animationId;
focusAnimationTime: number;
private _timePrev;
private _timeCurrent;
private _anglePrev;
private _angleCurrent;
private _cursorPosPrev;
private _cursorPosCurr;
private _wPrev;
private _wCurr;
adjustNearFar: boolean;
scaleFactor: number;
dampingFactor: number;
wMax: number;
enableAnimations: boolean;
enableGrid: boolean;
cursorZoom: boolean;
minFov: number;
maxFov: number;
enabled: boolean;
enablePan: boolean;
enableRotate: boolean;
enableZoom: boolean;
minDistance: number;
maxDistance: number;
minZoom: number;
maxZoom: number;
readonly target: Vector3;
private _currentTarget;
private _tbRadius;
private _state;
constructor(camera: Camera | null, domElement?: HTMLElement | null | undefined, scene?: Scene | null | undefined);
private onWindowResize;
private onContextMenu;
private onPointerCancel;
private onPointerDown;
private onPointerMove;
private onPointerUp;
private onWheel;
private onSinglePanStart;
private onSinglePanMove;
private onSinglePanEnd;
private onDoubleTap;
private onDoublePanStart;
private onDoublePanMove;
private onDoublePanEnd;
private onRotateStart;
private onRotateMove;
private onRotateEnd;
private onPinchStart;
private onPinchMove;
private onPinchEnd;
private onTriplePanStart;
private onTriplePanMove;
private onTriplePanEnd;
/**
* Set _center's x/y coordinates
* @param {Number} clientX
* @param {Number} clientY
*/
private setCenter;
/**
* Set default mouse actions
*/
private initializeMouseActions;
/**
* Set a new mouse action by specifying the operation to be performed and a mouse/key combination. In case of conflict, replaces the existing one
* @param {String} operation The operation to be performed ('PAN', 'ROTATE', 'ZOOM', 'FOV)
* @param {*} mouse A mouse button (0, 1, 2) or 'WHEEL' for wheel notches
* @param {*} key The keyboard modifier ('CTRL', 'SHIFT') or null if key is not needed
* @returns {Boolean} True if the mouse action has been successfully added, false otherwise
*/
private setMouseAction;
/**
* Return the operation associated to a mouse/keyboard combination
* @param {*} mouse A mouse button (0, 1, 2) or 'WHEEL' for wheel notches
* @param {*} key The keyboard modifier ('CTRL', 'SHIFT') or null if key is not needed
* @returns The operation if it has been found, null otherwise
*/
private getOpFromAction;
/**
* Get the operation associated to mouse and key combination and returns the corresponding FSA state
* @param {Number} mouse Mouse button
* @param {String} key Keyboard modifier
* @returns The FSA state obtained from the operation associated to mouse/keyboard combination
*/
private getOpStateFromAction;
/**
* Calculate the angle between two pointers
* @param {PointerEvent} p1
* @param {PointerEvent} p2
* @returns {Number} The angle between two pointers in degrees
*/
private getAngle;
/**
* Update a PointerEvent inside current pointerevents array
* @param {PointerEvent} event
*/
private updateTouchEvent;
/**
* Apply a transformation matrix, to the camera and gizmos
* @param {Object} transformation Object containing matrices to apply to camera and gizmos
*/
private applyTransformMatrix;
/**
* 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
*/
private calculateAngularSpeed;
/**
* Calculate the distance between two pointers
* @param {PointerEvent} p0 The first pointer
* @param {PointerEvent} p1 The second pointer
* @returns {number} The distance between the two pointers
*/
private calculatePointersDistance;
/**
* Calculate the rotation axis as the vector perpendicular between two vectors
* @param {Vector3} vec1 The first vector
* @param {Vector3} vec2 The second vector
* @returns {Vector3} The normalized rotation axis
*/
private calculateRotationAxis;
/**
* Calculate the trackball radius so that gizmo's diamater will be 2/3 of the minimum side of the camera frustum
* @param {Camera} camera
* @returns {Number} The trackball radius
*/
private calculateTbRadius;
/**
* Focus operation consist of positioning the point of interest in front of the camera and a slightly zoom in
* @param {Vector3} point The point of interest
* @param {Number} size Scale factor
* @param {Number} amount Amount of operation to be completed (used for focus animations, default is complete full operation)
*/
private focus;
/**
* Draw a grid and add it to the scene
*/
private drawGrid;
connect: (domElement: HTMLElement) => void;
/**
* Remove all listeners, stop animations and clean scene
*/
dispose: () => void;
/**
* remove the grid from the scene
*/
private disposeGrid;
/**
* Compute the easing out cubic function for ease out effect in animation
* @param {Number} t The absolute progress of the animation in the bound of 0 (beginning of the) and 1 (ending of animation)
* @returns {Number} Result of easing out cubic at time t
*/
private easeOutCubic;
/**
* Make rotation gizmos more or less visible
* @param {Boolean} isActive If true, make gizmos more visible
*/
private activateGizmos;
/**
* Calculate the cursor position in NDC
* @param {number} x Cursor horizontal coordinate within the canvas
* @param {number} y Cursor vertical coordinate within the canvas
* @param {HTMLElement} canvas The canvas where the renderer draws its output
* @returns {Vector2} Cursor normalized position inside the canvas
*/
private getCursorNDC;
/**
* Calculate the cursor position inside the canvas x/y coordinates with the origin being in the center of the canvas
* @param {Number} x Cursor horizontal coordinate within the canvas
* @param {Number} y Cursor vertical coordinate within the canvas
* @param {HTMLElement} canvas The canvas where the renderer draws its output
* @returns {Vector2} Cursor position inside the canvas
*/
private getCursorPosition;
/**
* Set the camera to be controlled
* @param {Camera} camera The virtual camera to be controlled
*/
private setCamera;
/**
* Set gizmos visibility
* @param {Boolean} value Value of gizmos visibility
*/
setGizmosVisible(value: boolean): void;
/**
* Creates the rotation gizmos matching trackball center and radius
* @param {Vector3} tbCenter The trackball center
* @param {number} tbRadius The trackball radius
*/
private makeGizmos;
/**
* Perform animation for focus operation
* @param {Number} time Instant in which this function is called as performance.now()
* @param {Vector3} point Point of interest for focus operation
* @param {Matrix4} cameraMatrix Camera matrix
* @param {Matrix4} gizmoMatrix Gizmos matrix
*/
private onFocusAnim;
/**
* Perform animation for rotation operation
* @param {Number} time Instant in which this function is called as performance.now()
* @param {Vector3} rotationAxis Rotation axis
* @param {number} w0 Initial angular velocity
*/
private onRotationAnim;
/**
* Perform pan operation moving camera between two points
* @param {Vector3} p0 Initial point
* @param {Vector3} p1 Ending point
* @param {Boolean} adjust If movement should be adjusted considering camera distance (Perspective only)
*/
private pan;
/**
* Reset trackball
*/
reset: () => void;
/**
* Rotate the camera around an axis passing by trackball's center
* @param {Vector3} axis Rotation axis
* @param {number} angle Angle in radians
* @returns {Object} Object with 'camera' field containing transformation matrix resulting from the operation to be applied to the camera
*/
private rotate;
copyState: () => void;
pasteState: () => void;
/**
* Save the current state of the control. This can later be recovered with .reset
*/
saveState: () => void;
/**
* Perform uniform scale operation around a given point
* @param {Number} size Scale factor
* @param {Vector3} point Point around which scale
* @param {Boolean} scaleGizmos If gizmos should be scaled (Perspective only)
* @returns {Object} Object with 'camera' and 'gizmo' fields containing transformation matrices resulting from the operation to be applied to the camera and gizmos
*/
private applyScale;
/**
* Set camera fov
* @param {Number} value fov to be setted
*/
private setFov;
/**
* Set the trackball's center point
* @param {Number} x X coordinate
* @param {Number} y Y coordinate
* @param {Number} z Z coordinate
*/
setTarget: (x: number, y: number, z: number) => void;
/**
* Set values in transformation object
* @param {Matrix4} camera Transformation to be applied to the camera
* @param {Matrix4} gizmos Transformation to be applied to gizmos
*/
private setTransformationMatrices;
/**
* 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
*/
private zRotate;
/**
* 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
*/
private unprojectOnObj;
/**
* Unproject the cursor on the trackball surface
* @param {Camera} camera The virtual camera
* @param {Number} cursorX Cursor horizontal coordinate on screen
* @param {Number} cursorY Cursor vertical coordinate on screen
* @param {HTMLElement} canvas The canvas where the renderer draws its output
* @param {number} tbRadius The trackball radius
* @returns {Vector3} The unprojected point on the trackball surface
*/
private unprojectOnTbSurface;
/**
* Unproject the cursor on the plane passing through the center of the trackball orthogonal to the camera
* @param {Camera} camera The virtual camera
* @param {Number} cursorX Cursor horizontal coordinate on screen
* @param {Number} cursorY Cursor vertical coordinate on screen
* @param {HTMLElement} canvas The canvas where the renderer draws its output
* @param {Boolean} initialDistance If initial distance between camera and gizmos should be used for calculations instead of current (Perspective only)
* @returns {Vector3} The unprojected point on the trackball plane
*/
private unprojectOnTbPlane;
/**
* Update camera and gizmos state
*/
private updateMatrixState;
/**
* Update the trackball FSA
* @param {STATE} newState New state of the FSA
* @param {Boolean} updateMatrices If matriices state should be updated
*/
private updateTbState;
update: () => void;
private setStateFromJSON;
}
export { ArcballControls };
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+87
View File
@@ -0,0 +1,87 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("./EventDispatcher.cjs");
class DeviceOrientationControls extends EventDispatcher.EventDispatcher {
// radians
constructor(object) {
super();
__publicField(this, "object");
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "EPS", 1e-6);
__publicField(this, "enabled", true);
__publicField(this, "deviceOrientation", { alpha: 0, beta: 0, gamma: 0 });
__publicField(this, "screenOrientation", 0);
__publicField(this, "alphaOffset", 0);
__publicField(this, "onDeviceOrientationChangeEvent", (event) => {
this.deviceOrientation = event;
});
__publicField(this, "onScreenOrientationChangeEvent", () => {
this.screenOrientation = window.orientation || 0;
});
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
__publicField(this, "zee", new THREE.Vector3(0, 0, 1));
__publicField(this, "euler", new THREE.Euler());
__publicField(this, "q0", new THREE.Quaternion());
__publicField(this, "q1", new THREE.Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)));
// - PI/2 around the x-axis
__publicField(this, "setObjectQuaternion", (quaternion, alpha, beta, gamma, orient) => {
this.euler.set(beta, alpha, -gamma, "YXZ");
quaternion.setFromEuler(this.euler);
quaternion.multiply(this.q1);
quaternion.multiply(this.q0.setFromAxisAngle(this.zee, -orient));
});
__publicField(this, "connect", () => {
this.onScreenOrientationChangeEvent();
if (window.DeviceOrientationEvent !== void 0 && // @ts-ignore
typeof window.DeviceOrientationEvent.requestPermission === "function") {
window.DeviceOrientationEvent.requestPermission().then((response) => {
if (response == "granted") {
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
}
}).catch((error) => {
console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:", error);
});
} else {
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
}
this.enabled = true;
});
__publicField(this, "disconnect", () => {
window.removeEventListener("orientationchange", this.onScreenOrientationChangeEvent);
window.removeEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
this.enabled = false;
});
__publicField(this, "lastQuaternion", new THREE.Quaternion());
__publicField(this, "update", () => {
if (this.enabled === false)
return;
const device = this.deviceOrientation;
if (device) {
const alpha = device.alpha ? THREE.MathUtils.degToRad(device.alpha) + this.alphaOffset : 0;
const beta = device.beta ? THREE.MathUtils.degToRad(device.beta) : 0;
const gamma = device.gamma ? THREE.MathUtils.degToRad(device.gamma) : 0;
const orient = this.screenOrientation ? THREE.MathUtils.degToRad(this.screenOrientation) : 0;
this.setObjectQuaternion(this.object.quaternion, alpha, beta, gamma, orient);
if (8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
this.lastQuaternion.copy(this.object.quaternion);
this.dispatchEvent(this.changeEvent);
}
}
});
__publicField(this, "dispose", () => this.disconnect());
this.object = object;
this.object.rotation.reorder("YXZ");
this.connect();
}
}
exports.DeviceOrientationControls = DeviceOrientationControls;
//# sourceMappingURL=DeviceOrientationControls.cjs.map
File diff suppressed because one or more lines are too long
+29
View File
@@ -0,0 +1,29 @@
import { Camera } from 'three';
import { EventDispatcher } from './EventDispatcher';
import { StandardControlsEventMap } from './StandardControlsEventMap';
/**
* W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html)
*/
declare class DeviceOrientationControls extends EventDispatcher<StandardControlsEventMap> {
object: Camera;
private changeEvent;
private EPS;
enabled: boolean;
deviceOrientation: Partial<DeviceOrientationEvent>;
screenOrientation: string | number;
alphaOffset: number;
constructor(object: Camera);
private onDeviceOrientationChangeEvent;
private onScreenOrientationChangeEvent;
private zee;
private euler;
private q0;
private q1;
private setObjectQuaternion;
connect: () => void;
disconnect: () => void;
private lastQuaternion;
update: () => void;
dispose: () => void;
}
export { DeviceOrientationControls };
+87
View File
@@ -0,0 +1,87 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { Vector3, Euler, Quaternion, MathUtils } from "three";
import { EventDispatcher } from "./EventDispatcher.js";
class DeviceOrientationControls extends EventDispatcher {
// radians
constructor(object) {
super();
__publicField(this, "object");
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "EPS", 1e-6);
__publicField(this, "enabled", true);
__publicField(this, "deviceOrientation", { alpha: 0, beta: 0, gamma: 0 });
__publicField(this, "screenOrientation", 0);
__publicField(this, "alphaOffset", 0);
__publicField(this, "onDeviceOrientationChangeEvent", (event) => {
this.deviceOrientation = event;
});
__publicField(this, "onScreenOrientationChangeEvent", () => {
this.screenOrientation = window.orientation || 0;
});
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
__publicField(this, "zee", new Vector3(0, 0, 1));
__publicField(this, "euler", new Euler());
__publicField(this, "q0", new Quaternion());
__publicField(this, "q1", new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)));
// - PI/2 around the x-axis
__publicField(this, "setObjectQuaternion", (quaternion, alpha, beta, gamma, orient) => {
this.euler.set(beta, alpha, -gamma, "YXZ");
quaternion.setFromEuler(this.euler);
quaternion.multiply(this.q1);
quaternion.multiply(this.q0.setFromAxisAngle(this.zee, -orient));
});
__publicField(this, "connect", () => {
this.onScreenOrientationChangeEvent();
if (window.DeviceOrientationEvent !== void 0 && // @ts-ignore
typeof window.DeviceOrientationEvent.requestPermission === "function") {
window.DeviceOrientationEvent.requestPermission().then((response) => {
if (response == "granted") {
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
}
}).catch((error) => {
console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:", error);
});
} else {
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
}
this.enabled = true;
});
__publicField(this, "disconnect", () => {
window.removeEventListener("orientationchange", this.onScreenOrientationChangeEvent);
window.removeEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
this.enabled = false;
});
__publicField(this, "lastQuaternion", new Quaternion());
__publicField(this, "update", () => {
if (this.enabled === false)
return;
const device = this.deviceOrientation;
if (device) {
const alpha = device.alpha ? MathUtils.degToRad(device.alpha) + this.alphaOffset : 0;
const beta = device.beta ? MathUtils.degToRad(device.beta) : 0;
const gamma = device.gamma ? MathUtils.degToRad(device.gamma) : 0;
const orient = this.screenOrientation ? MathUtils.degToRad(this.screenOrientation) : 0;
this.setObjectQuaternion(this.object.quaternion, alpha, beta, gamma, orient);
if (8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
this.lastQuaternion.copy(this.object.quaternion);
this.dispatchEvent(this.changeEvent);
}
}
});
__publicField(this, "dispose", () => this.disconnect());
this.object = object;
this.object.rotation.reorder("YXZ");
this.connect();
}
}
export {
DeviceOrientationControls
};
//# sourceMappingURL=DeviceOrientationControls.js.map
File diff suppressed because one or more lines are too long
+184
View File
@@ -0,0 +1,184 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("./EventDispatcher.cjs");
class DragControls extends EventDispatcher.EventDispatcher {
constructor(_objects, _camera, _domElement) {
super();
__publicField(this, "enabled", true);
__publicField(this, "transformGroup", false);
__publicField(this, "_objects");
__publicField(this, "_camera");
__publicField(this, "_domElement");
__publicField(this, "_plane", new THREE.Plane());
__publicField(this, "_raycaster", new THREE.Raycaster());
__publicField(this, "_mouse", new THREE.Vector2());
__publicField(this, "_offset", new THREE.Vector3());
__publicField(this, "_intersection", new THREE.Vector3());
__publicField(this, "_worldPosition", new THREE.Vector3());
__publicField(this, "_inverseMatrix", new THREE.Matrix4());
__publicField(this, "_intersections", []);
__publicField(this, "_selected", null);
__publicField(this, "_hovered", null);
__publicField(this, "activate", () => {
this._domElement.addEventListener("pointermove", this.onPointerMove);
this._domElement.addEventListener("pointerdown", this.onPointerDown);
this._domElement.addEventListener("pointerup", this.onPointerCancel);
this._domElement.addEventListener("pointerleave", this.onPointerCancel);
this._domElement.addEventListener("touchmove", this.onTouchMove);
this._domElement.addEventListener("touchstart", this.onTouchStart);
this._domElement.addEventListener("touchend", this.onTouchEnd);
});
__publicField(this, "deactivate", () => {
this._domElement.removeEventListener("pointermove", this.onPointerMove);
this._domElement.removeEventListener("pointerdown", this.onPointerDown);
this._domElement.removeEventListener("pointerup", this.onPointerCancel);
this._domElement.removeEventListener("pointerleave", this.onPointerCancel);
this._domElement.removeEventListener("touchmove", this.onTouchMove);
this._domElement.removeEventListener("touchstart", this.onTouchStart);
this._domElement.removeEventListener("touchend", this.onTouchEnd);
this._domElement.style.cursor = "";
});
// TODO: confirm if this can be removed?
__publicField(this, "dispose", () => this.deactivate());
__publicField(this, "getObjects", () => this._objects);
__publicField(this, "getRaycaster", () => this._raycaster);
__publicField(this, "onMouseMove", (event) => {
const rect = this._domElement.getBoundingClientRect();
this._mouse.x = (event.clientX - rect.left) / rect.width * 2 - 1;
this._mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
this._raycaster.setFromCamera(this._mouse, this._camera);
if (this._selected && this.enabled) {
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection)) {
this._selected.position.copy(this._intersection.sub(this._offset).applyMatrix4(this._inverseMatrix));
}
this.dispatchEvent({ type: "drag", object: this._selected });
return;
}
this._intersections.length = 0;
this._raycaster.setFromCamera(this._mouse, this._camera);
this._raycaster.intersectObjects(this._objects, true, this._intersections);
if (this._intersections.length > 0) {
const object = this._intersections[0].object;
this._plane.setFromNormalAndCoplanarPoint(
this._camera.getWorldDirection(this._plane.normal),
this._worldPosition.setFromMatrixPosition(object.matrixWorld)
);
if (this._hovered !== object) {
this.dispatchEvent({ type: "hoveron", object });
this._domElement.style.cursor = "pointer";
this._hovered = object;
}
} else {
if (this._hovered !== null) {
this.dispatchEvent({ type: "hoveroff", object: this._hovered });
this._domElement.style.cursor = "auto";
this._hovered = null;
}
}
});
__publicField(this, "onMouseDown", () => {
this._intersections.length = 0;
this._raycaster.setFromCamera(this._mouse, this._camera);
this._raycaster.intersectObjects(this._objects, true, this._intersections);
if (this._intersections.length > 0) {
this._selected = this.transformGroup === true ? this._objects[0] : this._intersections[0].object;
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection) && this._selected.parent) {
this._inverseMatrix.copy(this._selected.parent.matrixWorld).invert();
this._offset.copy(this._intersection).sub(this._worldPosition.setFromMatrixPosition(this._selected.matrixWorld));
}
this._domElement.style.cursor = "move";
this.dispatchEvent({ type: "dragstart", object: this._selected });
}
});
__publicField(this, "onMouseCancel", () => {
if (this._selected) {
this.dispatchEvent({ type: "dragend", object: this._selected });
this._selected = null;
}
this._domElement.style.cursor = this._hovered ? "pointer" : "auto";
});
__publicField(this, "onPointerMove", (event) => {
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseMove(event);
break;
}
});
__publicField(this, "onPointerDown", (event) => {
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseDown();
break;
}
});
__publicField(this, "onPointerCancel", (event) => {
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseCancel();
break;
}
});
__publicField(this, "onTouchMove", (event) => {
event.preventDefault();
const newEvent = event.changedTouches[0];
const rect = this._domElement.getBoundingClientRect();
this._mouse.x = (newEvent.clientX - rect.left) / rect.width * 2 - 1;
this._mouse.y = -((newEvent.clientY - rect.top) / rect.height) * 2 + 1;
this._raycaster.setFromCamera(this._mouse, this._camera);
if (this._selected && this.enabled) {
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection)) {
this._selected.position.copy(this._intersection.sub(this._offset).applyMatrix4(this._inverseMatrix));
}
this.dispatchEvent({ type: "drag", object: this._selected });
return;
}
});
__publicField(this, "onTouchStart", (event) => {
event.preventDefault();
const newEvent = event.changedTouches[0];
const rect = this._domElement.getBoundingClientRect();
this._mouse.x = (newEvent.clientX - rect.left) / rect.width * 2 - 1;
this._mouse.y = -((newEvent.clientY - rect.top) / rect.height) * 2 + 1;
this._intersections.length = 0;
this._raycaster.setFromCamera(this._mouse, this._camera);
this._raycaster.intersectObjects(this._objects, true, this._intersections);
if (this._intersections.length > 0) {
this._selected = this.transformGroup === true ? this._objects[0] : this._intersections[0].object;
this._plane.setFromNormalAndCoplanarPoint(
this._camera.getWorldDirection(this._plane.normal),
this._worldPosition.setFromMatrixPosition(this._selected.matrixWorld)
);
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection) && this._selected.parent) {
this._inverseMatrix.copy(this._selected.parent.matrixWorld).invert();
this._offset.copy(this._intersection).sub(this._worldPosition.setFromMatrixPosition(this._selected.matrixWorld));
}
this._domElement.style.cursor = "move";
this.dispatchEvent({ type: "dragstart", object: this._selected });
}
});
__publicField(this, "onTouchEnd", (event) => {
event.preventDefault();
if (this._selected) {
this.dispatchEvent({ type: "dragend", object: this._selected });
this._selected = null;
}
this._domElement.style.cursor = "auto";
});
this._objects = _objects;
this._camera = _camera;
this._domElement = _domElement;
this.activate();
}
}
exports.DragControls = DragControls;
//# sourceMappingURL=DragControls.cjs.map
File diff suppressed because one or more lines are too long
+67
View File
@@ -0,0 +1,67 @@
import { Camera, Object3D, Raycaster } from 'three';
import { EventDispatcher } from './EventDispatcher';
export interface DragControlsEventMap {
/**
* Fires when the pointer is moved onto a 3D object, or onto one of its children.
*/
hoveron: {
object: Object3D;
};
/**
* Fires when the pointer is moved out of a 3D object.
*/
hoveroff: {
object: Object3D;
};
/**
* Fires when the user starts to drag a 3D object.
*/
dragstart: {
object: Object3D;
};
/**
* Fires when the user drags a 3D object.
*/
drag: {
object: Object3D;
};
/**
* Fires when the user has finished dragging a 3D object.
*/
dragend: {
object: Object3D;
};
}
declare class DragControls extends EventDispatcher<DragControlsEventMap> {
enabled: boolean;
transformGroup: boolean;
private _objects;
private _camera;
private _domElement;
private _plane;
private _raycaster;
private _mouse;
private _offset;
private _intersection;
private _worldPosition;
private _inverseMatrix;
private _intersections;
private _selected;
private _hovered;
constructor(_objects: Object3D[], _camera: Camera, _domElement: HTMLElement);
activate: () => void;
deactivate: () => void;
dispose: () => void;
getObjects: () => Object3D[];
getRaycaster: () => Raycaster;
private onMouseMove;
private onMouseDown;
private onMouseCancel;
private onPointerMove;
private onPointerDown;
private onPointerCancel;
private onTouchMove;
private onTouchStart;
private onTouchEnd;
}
export { DragControls };
+184
View File
@@ -0,0 +1,184 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { Plane, Raycaster, Vector2, Vector3, Matrix4 } from "three";
import { EventDispatcher } from "./EventDispatcher.js";
class DragControls extends EventDispatcher {
constructor(_objects, _camera, _domElement) {
super();
__publicField(this, "enabled", true);
__publicField(this, "transformGroup", false);
__publicField(this, "_objects");
__publicField(this, "_camera");
__publicField(this, "_domElement");
__publicField(this, "_plane", new Plane());
__publicField(this, "_raycaster", new Raycaster());
__publicField(this, "_mouse", new Vector2());
__publicField(this, "_offset", new Vector3());
__publicField(this, "_intersection", new Vector3());
__publicField(this, "_worldPosition", new Vector3());
__publicField(this, "_inverseMatrix", new Matrix4());
__publicField(this, "_intersections", []);
__publicField(this, "_selected", null);
__publicField(this, "_hovered", null);
__publicField(this, "activate", () => {
this._domElement.addEventListener("pointermove", this.onPointerMove);
this._domElement.addEventListener("pointerdown", this.onPointerDown);
this._domElement.addEventListener("pointerup", this.onPointerCancel);
this._domElement.addEventListener("pointerleave", this.onPointerCancel);
this._domElement.addEventListener("touchmove", this.onTouchMove);
this._domElement.addEventListener("touchstart", this.onTouchStart);
this._domElement.addEventListener("touchend", this.onTouchEnd);
});
__publicField(this, "deactivate", () => {
this._domElement.removeEventListener("pointermove", this.onPointerMove);
this._domElement.removeEventListener("pointerdown", this.onPointerDown);
this._domElement.removeEventListener("pointerup", this.onPointerCancel);
this._domElement.removeEventListener("pointerleave", this.onPointerCancel);
this._domElement.removeEventListener("touchmove", this.onTouchMove);
this._domElement.removeEventListener("touchstart", this.onTouchStart);
this._domElement.removeEventListener("touchend", this.onTouchEnd);
this._domElement.style.cursor = "";
});
// TODO: confirm if this can be removed?
__publicField(this, "dispose", () => this.deactivate());
__publicField(this, "getObjects", () => this._objects);
__publicField(this, "getRaycaster", () => this._raycaster);
__publicField(this, "onMouseMove", (event) => {
const rect = this._domElement.getBoundingClientRect();
this._mouse.x = (event.clientX - rect.left) / rect.width * 2 - 1;
this._mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
this._raycaster.setFromCamera(this._mouse, this._camera);
if (this._selected && this.enabled) {
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection)) {
this._selected.position.copy(this._intersection.sub(this._offset).applyMatrix4(this._inverseMatrix));
}
this.dispatchEvent({ type: "drag", object: this._selected });
return;
}
this._intersections.length = 0;
this._raycaster.setFromCamera(this._mouse, this._camera);
this._raycaster.intersectObjects(this._objects, true, this._intersections);
if (this._intersections.length > 0) {
const object = this._intersections[0].object;
this._plane.setFromNormalAndCoplanarPoint(
this._camera.getWorldDirection(this._plane.normal),
this._worldPosition.setFromMatrixPosition(object.matrixWorld)
);
if (this._hovered !== object) {
this.dispatchEvent({ type: "hoveron", object });
this._domElement.style.cursor = "pointer";
this._hovered = object;
}
} else {
if (this._hovered !== null) {
this.dispatchEvent({ type: "hoveroff", object: this._hovered });
this._domElement.style.cursor = "auto";
this._hovered = null;
}
}
});
__publicField(this, "onMouseDown", () => {
this._intersections.length = 0;
this._raycaster.setFromCamera(this._mouse, this._camera);
this._raycaster.intersectObjects(this._objects, true, this._intersections);
if (this._intersections.length > 0) {
this._selected = this.transformGroup === true ? this._objects[0] : this._intersections[0].object;
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection) && this._selected.parent) {
this._inverseMatrix.copy(this._selected.parent.matrixWorld).invert();
this._offset.copy(this._intersection).sub(this._worldPosition.setFromMatrixPosition(this._selected.matrixWorld));
}
this._domElement.style.cursor = "move";
this.dispatchEvent({ type: "dragstart", object: this._selected });
}
});
__publicField(this, "onMouseCancel", () => {
if (this._selected) {
this.dispatchEvent({ type: "dragend", object: this._selected });
this._selected = null;
}
this._domElement.style.cursor = this._hovered ? "pointer" : "auto";
});
__publicField(this, "onPointerMove", (event) => {
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseMove(event);
break;
}
});
__publicField(this, "onPointerDown", (event) => {
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseDown();
break;
}
});
__publicField(this, "onPointerCancel", (event) => {
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseCancel();
break;
}
});
__publicField(this, "onTouchMove", (event) => {
event.preventDefault();
const newEvent = event.changedTouches[0];
const rect = this._domElement.getBoundingClientRect();
this._mouse.x = (newEvent.clientX - rect.left) / rect.width * 2 - 1;
this._mouse.y = -((newEvent.clientY - rect.top) / rect.height) * 2 + 1;
this._raycaster.setFromCamera(this._mouse, this._camera);
if (this._selected && this.enabled) {
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection)) {
this._selected.position.copy(this._intersection.sub(this._offset).applyMatrix4(this._inverseMatrix));
}
this.dispatchEvent({ type: "drag", object: this._selected });
return;
}
});
__publicField(this, "onTouchStart", (event) => {
event.preventDefault();
const newEvent = event.changedTouches[0];
const rect = this._domElement.getBoundingClientRect();
this._mouse.x = (newEvent.clientX - rect.left) / rect.width * 2 - 1;
this._mouse.y = -((newEvent.clientY - rect.top) / rect.height) * 2 + 1;
this._intersections.length = 0;
this._raycaster.setFromCamera(this._mouse, this._camera);
this._raycaster.intersectObjects(this._objects, true, this._intersections);
if (this._intersections.length > 0) {
this._selected = this.transformGroup === true ? this._objects[0] : this._intersections[0].object;
this._plane.setFromNormalAndCoplanarPoint(
this._camera.getWorldDirection(this._plane.normal),
this._worldPosition.setFromMatrixPosition(this._selected.matrixWorld)
);
if (this._raycaster.ray.intersectPlane(this._plane, this._intersection) && this._selected.parent) {
this._inverseMatrix.copy(this._selected.parent.matrixWorld).invert();
this._offset.copy(this._intersection).sub(this._worldPosition.setFromMatrixPosition(this._selected.matrixWorld));
}
this._domElement.style.cursor = "move";
this.dispatchEvent({ type: "dragstart", object: this._selected });
}
});
__publicField(this, "onTouchEnd", (event) => {
event.preventDefault();
if (this._selected) {
this.dispatchEvent({ type: "dragend", object: this._selected });
this._selected = null;
}
this._domElement.style.cursor = "auto";
});
this._objects = _objects;
this._camera = _camera;
this._domElement = _domElement;
this.activate();
}
}
export {
DragControls
};
//# sourceMappingURL=DragControls.js.map
File diff suppressed because one or more lines are too long
+78
View File
@@ -0,0 +1,78 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
class EventDispatcher {
constructor() {
// not defined in @types/three
__publicField(this, "_listeners");
}
/**
* Adds a listener to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
addEventListener(type, listener) {
if (this._listeners === void 0)
this._listeners = {};
const listeners = this._listeners;
if (listeners[type] === void 0) {
listeners[type] = [];
}
if (listeners[type].indexOf(listener) === -1) {
listeners[type].push(listener);
}
}
/**
* Checks if listener is added to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
hasEventListener(type, listener) {
if (this._listeners === void 0)
return false;
const listeners = this._listeners;
return listeners[type] !== void 0 && listeners[type].indexOf(listener) !== -1;
}
/**
* Removes a listener from an event type.
* @param type The type of the listener that gets removed.
* @param listener The listener function that gets removed.
*/
removeEventListener(type, listener) {
if (this._listeners === void 0)
return;
const listeners = this._listeners;
const listenerArray = listeners[type];
if (listenerArray !== void 0) {
const index = listenerArray.indexOf(listener);
if (index !== -1) {
listenerArray.splice(index, 1);
}
}
}
/**
* Fire an event type.
* @param event The event that gets fired.
*/
dispatchEvent(event) {
if (this._listeners === void 0)
return;
const listeners = this._listeners;
const listenerArray = listeners[event.type];
if (listenerArray !== void 0) {
event.target = this;
const array = listenerArray.slice(0);
for (let i = 0, l = array.length; i < l; i++) {
array[i].call(this, event);
}
event.target = null;
}
}
}
exports.EventDispatcher = EventDispatcher;
//# sourceMappingURL=EventDispatcher.cjs.map
File diff suppressed because one or more lines are too long
+41
View File
@@ -0,0 +1,41 @@
/**
* The minimal basic Event that can be dispatched by a {@link EventDispatcher<>}.
*/
export interface BaseEvent<TEventType extends string = string> {
readonly type: TEventType;
target: any;
}
/**
* The minimal expected contract of a fired Event that was dispatched by a {@link EventDispatcher<>}.
*/
export interface Event<TEventType extends string = string, TTarget = unknown> {
readonly type: TEventType;
readonly target: TTarget;
}
export type EventListener<TEventData, TEventType extends string, TTarget> = (event: TEventData & Event<TEventType, TTarget>) => void;
export declare class EventDispatcher<TEventMap extends {} = {}> {
private _listeners;
/**
* Adds a listener to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
addEventListener<T extends Extract<keyof TEventMap, string>>(type: T, listener: EventListener<TEventMap[T], T, this>): void;
/**
* Checks if listener is added to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
hasEventListener<T extends Extract<keyof TEventMap, string>>(type: T, listener: EventListener<TEventMap[T], T, this>): boolean;
/**
* Removes a listener from an event type.
* @param type The type of the listener that gets removed.
* @param listener The listener function that gets removed.
*/
removeEventListener<T extends Extract<keyof TEventMap, string>>(type: T, listener: EventListener<TEventMap[T], T, this>): void;
/**
* Fire an event type.
* @param event The event that gets fired.
*/
dispatchEvent<T extends Extract<keyof TEventMap, string>>(event: BaseEvent<T> & TEventMap[T]): void;
}
+78
View File
@@ -0,0 +1,78 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
class EventDispatcher {
constructor() {
// not defined in @types/three
__publicField(this, "_listeners");
}
/**
* Adds a listener to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
addEventListener(type, listener) {
if (this._listeners === void 0)
this._listeners = {};
const listeners = this._listeners;
if (listeners[type] === void 0) {
listeners[type] = [];
}
if (listeners[type].indexOf(listener) === -1) {
listeners[type].push(listener);
}
}
/**
* Checks if listener is added to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
hasEventListener(type, listener) {
if (this._listeners === void 0)
return false;
const listeners = this._listeners;
return listeners[type] !== void 0 && listeners[type].indexOf(listener) !== -1;
}
/**
* Removes a listener from an event type.
* @param type The type of the listener that gets removed.
* @param listener The listener function that gets removed.
*/
removeEventListener(type, listener) {
if (this._listeners === void 0)
return;
const listeners = this._listeners;
const listenerArray = listeners[type];
if (listenerArray !== void 0) {
const index = listenerArray.indexOf(listener);
if (index !== -1) {
listenerArray.splice(index, 1);
}
}
}
/**
* Fire an event type.
* @param event The event that gets fired.
*/
dispatchEvent(event) {
if (this._listeners === void 0)
return;
const listeners = this._listeners;
const listenerArray = listeners[event.type];
if (listenerArray !== void 0) {
event.target = this;
const array = listenerArray.slice(0);
for (let i = 0, l = array.length; i < l; i++) {
array[i].call(this, event);
}
event.target = null;
}
}
}
export {
EventDispatcher
};
//# sourceMappingURL=EventDispatcher.js.map
File diff suppressed because one or more lines are too long
+231
View File
@@ -0,0 +1,231 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("./EventDispatcher.cjs");
const targetPosition = /* @__PURE__ */ new THREE.Vector3();
class FirstPersonControls extends EventDispatcher.EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement");
__publicField(this, "enabled", true);
__publicField(this, "movementSpeed", 1);
__publicField(this, "lookSpeed", 5e-3);
__publicField(this, "lookVertical", true);
__publicField(this, "autoForward", false);
__publicField(this, "activeLook", true);
__publicField(this, "heightSpeed", false);
__publicField(this, "heightCoef", 1);
__publicField(this, "heightMin", 0);
__publicField(this, "heightMax", 1);
__publicField(this, "constrainVertical", false);
__publicField(this, "verticalMin", 0);
__publicField(this, "verticalMax", Math.PI);
__publicField(this, "mouseDragOn", false);
// internals
__publicField(this, "autoSpeedFactor", 0);
__publicField(this, "mouseX", 0);
__publicField(this, "mouseY", 0);
__publicField(this, "moveForward", false);
__publicField(this, "moveBackward", false);
__publicField(this, "moveLeft", false);
__publicField(this, "moveRight", false);
__publicField(this, "moveUp", false);
__publicField(this, "moveDown", false);
__publicField(this, "viewHalfX", 0);
__publicField(this, "viewHalfY", 0);
__publicField(this, "lat", 0);
__publicField(this, "lon", 0);
__publicField(this, "lookDirection", new THREE.Vector3());
__publicField(this, "spherical", new THREE.Spherical());
__publicField(this, "target", new THREE.Vector3());
__publicField(this, "connect", (domElement) => {
domElement.setAttribute("tabindex", "-1");
domElement.style.touchAction = "none";
domElement.addEventListener("contextmenu", this.contextmenu);
domElement.addEventListener("mousemove", this.onMouseMove);
domElement.addEventListener("mousedown", this.onMouseDown);
domElement.addEventListener("mouseup", this.onMouseUp);
this.domElement = domElement;
window.addEventListener("keydown", this.onKeyDown);
window.addEventListener("keyup", this.onKeyUp);
this.handleResize();
});
__publicField(this, "dispose", () => {
var _a, _b, _c, _d;
(_a = this.domElement) == null ? void 0 : _a.removeEventListener("contextmenu", this.contextmenu);
(_b = this.domElement) == null ? void 0 : _b.removeEventListener("mousedown", this.onMouseDown);
(_c = this.domElement) == null ? void 0 : _c.removeEventListener("mousemove", this.onMouseMove);
(_d = this.domElement) == null ? void 0 : _d.removeEventListener("mouseup", this.onMouseUp);
window.removeEventListener("keydown", this.onKeyDown);
window.removeEventListener("keyup", this.onKeyUp);
});
__publicField(this, "handleResize", () => {
if (this.domElement) {
this.viewHalfX = this.domElement.offsetWidth / 2;
this.viewHalfY = this.domElement.offsetHeight / 2;
}
});
__publicField(this, "onMouseDown", (event) => {
var _a;
(_a = this.domElement) == null ? void 0 : _a.focus();
if (this.activeLook) {
switch (event.button) {
case 0:
this.moveForward = true;
break;
case 2:
this.moveBackward = true;
break;
}
}
this.mouseDragOn = true;
});
__publicField(this, "onMouseUp", (event) => {
if (this.activeLook) {
switch (event.button) {
case 0:
this.moveForward = false;
break;
case 2:
this.moveBackward = false;
break;
}
}
this.mouseDragOn = false;
});
__publicField(this, "onMouseMove", (event) => {
if (this.domElement) {
this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
}
});
__publicField(this, "onKeyDown", (event) => {
switch (event.code) {
case "ArrowUp":
case "KeyW":
this.moveForward = true;
break;
case "ArrowLeft":
case "KeyA":
this.moveLeft = true;
break;
case "ArrowDown":
case "KeyS":
this.moveBackward = true;
break;
case "ArrowRight":
case "KeyD":
this.moveRight = true;
break;
case "KeyR":
this.moveUp = true;
break;
case "KeyF":
this.moveDown = true;
break;
}
});
__publicField(this, "onKeyUp", (event) => {
switch (event.code) {
case "ArrowUp":
case "KeyW":
this.moveForward = false;
break;
case "ArrowLeft":
case "KeyA":
this.moveLeft = false;
break;
case "ArrowDown":
case "KeyS":
this.moveBackward = false;
break;
case "ArrowRight":
case "KeyD":
this.moveRight = false;
break;
case "KeyR":
this.moveUp = false;
break;
case "KeyF":
this.moveDown = false;
break;
}
});
__publicField(this, "lookAt", (x, y, z) => {
if (x instanceof THREE.Vector3) {
this.target.copy(x);
} else if (y && z) {
this.target.set(x, y, z);
}
this.object.lookAt(this.target);
this.setOrientation();
return this;
});
__publicField(this, "update", (delta) => {
if (!this.enabled)
return;
if (this.heightSpeed) {
const y = THREE.MathUtils.clamp(this.object.position.y, this.heightMin, this.heightMax);
const heightDelta = y - this.heightMin;
this.autoSpeedFactor = delta * (heightDelta * this.heightCoef);
} else {
this.autoSpeedFactor = 0;
}
const actualMoveSpeed = delta * this.movementSpeed;
if (this.moveForward || this.autoForward && !this.moveBackward) {
this.object.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
}
if (this.moveBackward)
this.object.translateZ(actualMoveSpeed);
if (this.moveLeft)
this.object.translateX(-actualMoveSpeed);
if (this.moveRight)
this.object.translateX(actualMoveSpeed);
if (this.moveUp)
this.object.translateY(actualMoveSpeed);
if (this.moveDown)
this.object.translateY(-actualMoveSpeed);
let actualLookSpeed = delta * this.lookSpeed;
if (!this.activeLook) {
actualLookSpeed = 0;
}
let verticalLookRatio = 1;
if (this.constrainVertical) {
verticalLookRatio = Math.PI / (this.verticalMax - this.verticalMin);
}
this.lon -= this.mouseX * actualLookSpeed;
if (this.lookVertical)
this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
this.lat = Math.max(-85, Math.min(85, this.lat));
let phi = THREE.MathUtils.degToRad(90 - this.lat);
const theta = THREE.MathUtils.degToRad(this.lon);
if (this.constrainVertical) {
phi = THREE.MathUtils.mapLinear(phi, 0, Math.PI, this.verticalMin, this.verticalMax);
}
const position = this.object.position;
targetPosition.setFromSphericalCoords(1, phi, theta).add(position);
this.object.lookAt(targetPosition);
});
__publicField(this, "contextmenu", (event) => event.preventDefault());
__publicField(this, "setOrientation", () => {
this.lookDirection.set(0, 0, -1).applyQuaternion(this.object.quaternion);
this.spherical.setFromVector3(this.lookDirection);
this.lat = 90 - THREE.MathUtils.radToDeg(this.spherical.phi);
this.lon = THREE.MathUtils.radToDeg(this.spherical.theta);
});
this.object = object;
this.domElement = domElement;
this.setOrientation();
if (domElement)
this.connect(domElement);
}
}
exports.FirstPersonControls = FirstPersonControls;
//# sourceMappingURL=FirstPersonControls.cjs.map
File diff suppressed because one or more lines are too long
+49
View File
@@ -0,0 +1,49 @@
import { Vector3, Camera } from 'three';
import { EventDispatcher } from './EventDispatcher';
export declare class FirstPersonControls extends EventDispatcher<{}> {
object: Camera;
domElement?: HTMLElement | null;
enabled: boolean;
movementSpeed: number;
lookSpeed: number;
lookVertical: boolean;
autoForward: boolean;
activeLook: boolean;
heightSpeed: boolean;
heightCoef: number;
heightMin: number;
heightMax: number;
constrainVertical: boolean;
verticalMin: number;
verticalMax: number;
mouseDragOn: boolean;
private autoSpeedFactor;
private mouseX;
private mouseY;
private moveForward;
private moveBackward;
private moveLeft;
private moveRight;
private moveUp;
private moveDown;
private viewHalfX;
private viewHalfY;
private lat;
private lon;
private lookDirection;
private spherical;
readonly target: Vector3;
constructor(object: Camera, domElement?: HTMLElement | null);
connect: (domElement: HTMLElement) => void;
dispose: () => void;
handleResize: () => void;
private onMouseDown;
private onMouseUp;
private onMouseMove;
private onKeyDown;
private onKeyUp;
lookAt: (x: Vector3 | number, y?: number, z?: number) => this;
update: (delta: number) => void;
private contextmenu;
private setOrientation;
}
+231
View File
@@ -0,0 +1,231 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { Vector3, Spherical, MathUtils } from "three";
import { EventDispatcher } from "./EventDispatcher.js";
const targetPosition = /* @__PURE__ */ new Vector3();
class FirstPersonControls extends EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement");
__publicField(this, "enabled", true);
__publicField(this, "movementSpeed", 1);
__publicField(this, "lookSpeed", 5e-3);
__publicField(this, "lookVertical", true);
__publicField(this, "autoForward", false);
__publicField(this, "activeLook", true);
__publicField(this, "heightSpeed", false);
__publicField(this, "heightCoef", 1);
__publicField(this, "heightMin", 0);
__publicField(this, "heightMax", 1);
__publicField(this, "constrainVertical", false);
__publicField(this, "verticalMin", 0);
__publicField(this, "verticalMax", Math.PI);
__publicField(this, "mouseDragOn", false);
// internals
__publicField(this, "autoSpeedFactor", 0);
__publicField(this, "mouseX", 0);
__publicField(this, "mouseY", 0);
__publicField(this, "moveForward", false);
__publicField(this, "moveBackward", false);
__publicField(this, "moveLeft", false);
__publicField(this, "moveRight", false);
__publicField(this, "moveUp", false);
__publicField(this, "moveDown", false);
__publicField(this, "viewHalfX", 0);
__publicField(this, "viewHalfY", 0);
__publicField(this, "lat", 0);
__publicField(this, "lon", 0);
__publicField(this, "lookDirection", new Vector3());
__publicField(this, "spherical", new Spherical());
__publicField(this, "target", new Vector3());
__publicField(this, "connect", (domElement) => {
domElement.setAttribute("tabindex", "-1");
domElement.style.touchAction = "none";
domElement.addEventListener("contextmenu", this.contextmenu);
domElement.addEventListener("mousemove", this.onMouseMove);
domElement.addEventListener("mousedown", this.onMouseDown);
domElement.addEventListener("mouseup", this.onMouseUp);
this.domElement = domElement;
window.addEventListener("keydown", this.onKeyDown);
window.addEventListener("keyup", this.onKeyUp);
this.handleResize();
});
__publicField(this, "dispose", () => {
var _a, _b, _c, _d;
(_a = this.domElement) == null ? void 0 : _a.removeEventListener("contextmenu", this.contextmenu);
(_b = this.domElement) == null ? void 0 : _b.removeEventListener("mousedown", this.onMouseDown);
(_c = this.domElement) == null ? void 0 : _c.removeEventListener("mousemove", this.onMouseMove);
(_d = this.domElement) == null ? void 0 : _d.removeEventListener("mouseup", this.onMouseUp);
window.removeEventListener("keydown", this.onKeyDown);
window.removeEventListener("keyup", this.onKeyUp);
});
__publicField(this, "handleResize", () => {
if (this.domElement) {
this.viewHalfX = this.domElement.offsetWidth / 2;
this.viewHalfY = this.domElement.offsetHeight / 2;
}
});
__publicField(this, "onMouseDown", (event) => {
var _a;
(_a = this.domElement) == null ? void 0 : _a.focus();
if (this.activeLook) {
switch (event.button) {
case 0:
this.moveForward = true;
break;
case 2:
this.moveBackward = true;
break;
}
}
this.mouseDragOn = true;
});
__publicField(this, "onMouseUp", (event) => {
if (this.activeLook) {
switch (event.button) {
case 0:
this.moveForward = false;
break;
case 2:
this.moveBackward = false;
break;
}
}
this.mouseDragOn = false;
});
__publicField(this, "onMouseMove", (event) => {
if (this.domElement) {
this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
}
});
__publicField(this, "onKeyDown", (event) => {
switch (event.code) {
case "ArrowUp":
case "KeyW":
this.moveForward = true;
break;
case "ArrowLeft":
case "KeyA":
this.moveLeft = true;
break;
case "ArrowDown":
case "KeyS":
this.moveBackward = true;
break;
case "ArrowRight":
case "KeyD":
this.moveRight = true;
break;
case "KeyR":
this.moveUp = true;
break;
case "KeyF":
this.moveDown = true;
break;
}
});
__publicField(this, "onKeyUp", (event) => {
switch (event.code) {
case "ArrowUp":
case "KeyW":
this.moveForward = false;
break;
case "ArrowLeft":
case "KeyA":
this.moveLeft = false;
break;
case "ArrowDown":
case "KeyS":
this.moveBackward = false;
break;
case "ArrowRight":
case "KeyD":
this.moveRight = false;
break;
case "KeyR":
this.moveUp = false;
break;
case "KeyF":
this.moveDown = false;
break;
}
});
__publicField(this, "lookAt", (x, y, z) => {
if (x instanceof Vector3) {
this.target.copy(x);
} else if (y && z) {
this.target.set(x, y, z);
}
this.object.lookAt(this.target);
this.setOrientation();
return this;
});
__publicField(this, "update", (delta) => {
if (!this.enabled)
return;
if (this.heightSpeed) {
const y = MathUtils.clamp(this.object.position.y, this.heightMin, this.heightMax);
const heightDelta = y - this.heightMin;
this.autoSpeedFactor = delta * (heightDelta * this.heightCoef);
} else {
this.autoSpeedFactor = 0;
}
const actualMoveSpeed = delta * this.movementSpeed;
if (this.moveForward || this.autoForward && !this.moveBackward) {
this.object.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
}
if (this.moveBackward)
this.object.translateZ(actualMoveSpeed);
if (this.moveLeft)
this.object.translateX(-actualMoveSpeed);
if (this.moveRight)
this.object.translateX(actualMoveSpeed);
if (this.moveUp)
this.object.translateY(actualMoveSpeed);
if (this.moveDown)
this.object.translateY(-actualMoveSpeed);
let actualLookSpeed = delta * this.lookSpeed;
if (!this.activeLook) {
actualLookSpeed = 0;
}
let verticalLookRatio = 1;
if (this.constrainVertical) {
verticalLookRatio = Math.PI / (this.verticalMax - this.verticalMin);
}
this.lon -= this.mouseX * actualLookSpeed;
if (this.lookVertical)
this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
this.lat = Math.max(-85, Math.min(85, this.lat));
let phi = MathUtils.degToRad(90 - this.lat);
const theta = MathUtils.degToRad(this.lon);
if (this.constrainVertical) {
phi = MathUtils.mapLinear(phi, 0, Math.PI, this.verticalMin, this.verticalMax);
}
const position = this.object.position;
targetPosition.setFromSphericalCoords(1, phi, theta).add(position);
this.object.lookAt(targetPosition);
});
__publicField(this, "contextmenu", (event) => event.preventDefault());
__publicField(this, "setOrientation", () => {
this.lookDirection.set(0, 0, -1).applyQuaternion(this.object.quaternion);
this.spherical.setFromVector3(this.lookDirection);
this.lat = 90 - MathUtils.radToDeg(this.spherical.phi);
this.lon = MathUtils.radToDeg(this.spherical.theta);
});
this.object = object;
this.domElement = domElement;
this.setOrientation();
if (domElement)
this.connect(domElement);
}
}
export {
FirstPersonControls
};
//# sourceMappingURL=FirstPersonControls.js.map
File diff suppressed because one or more lines are too long
+250
View File
@@ -0,0 +1,250 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("./EventDispatcher.cjs");
function contextmenu(event) {
event.preventDefault();
}
class FlyControls extends EventDispatcher.EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement", null);
__publicField(this, "movementSpeed", 1);
__publicField(this, "rollSpeed", 5e-3);
__publicField(this, "dragToLook", false);
__publicField(this, "autoForward", false);
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "EPS", 1e-6);
__publicField(this, "tmpQuaternion", new THREE.Quaternion());
__publicField(this, "mouseStatus", 0);
__publicField(this, "movementSpeedMultiplier", 1);
__publicField(this, "moveState", {
up: 0,
down: 0,
left: 0,
right: 0,
forward: 0,
back: 0,
pitchUp: 0,
pitchDown: 0,
yawLeft: 0,
yawRight: 0,
rollLeft: 0,
rollRight: 0
});
__publicField(this, "moveVector", new THREE.Vector3(0, 0, 0));
__publicField(this, "rotationVector", new THREE.Vector3(0, 0, 0));
__publicField(this, "keydown", (event) => {
if (event.altKey) {
return;
}
switch (event.code) {
case "ShiftLeft":
case "ShiftRight":
this.movementSpeedMultiplier = 0.1;
break;
case "KeyW":
this.moveState.forward = 1;
break;
case "KeyS":
this.moveState.back = 1;
break;
case "KeyA":
this.moveState.left = 1;
break;
case "KeyD":
this.moveState.right = 1;
break;
case "KeyR":
this.moveState.up = 1;
break;
case "KeyF":
this.moveState.down = 1;
break;
case "ArrowUp":
this.moveState.pitchUp = 1;
break;
case "ArrowDown":
this.moveState.pitchDown = 1;
break;
case "ArrowLeft":
this.moveState.yawLeft = 1;
break;
case "ArrowRight":
this.moveState.yawRight = 1;
break;
case "KeyQ":
this.moveState.rollLeft = 1;
break;
case "KeyE":
this.moveState.rollRight = 1;
break;
}
this.updateMovementVector();
this.updateRotationVector();
});
__publicField(this, "keyup", (event) => {
switch (event.code) {
case "ShiftLeft":
case "ShiftRight":
this.movementSpeedMultiplier = 1;
break;
case "KeyW":
this.moveState.forward = 0;
break;
case "KeyS":
this.moveState.back = 0;
break;
case "KeyA":
this.moveState.left = 0;
break;
case "KeyD":
this.moveState.right = 0;
break;
case "KeyR":
this.moveState.up = 0;
break;
case "KeyF":
this.moveState.down = 0;
break;
case "ArrowUp":
this.moveState.pitchUp = 0;
break;
case "ArrowDown":
this.moveState.pitchDown = 0;
break;
case "ArrowLeft":
this.moveState.yawLeft = 0;
break;
case "ArrowRight":
this.moveState.yawRight = 0;
break;
case "KeyQ":
this.moveState.rollLeft = 0;
break;
case "KeyE":
this.moveState.rollRight = 0;
break;
}
this.updateMovementVector();
this.updateRotationVector();
});
__publicField(this, "pointerdown", (event) => {
if (this.dragToLook) {
this.mouseStatus++;
} else {
switch (event.button) {
case 0:
this.moveState.forward = 1;
break;
case 2:
this.moveState.back = 1;
break;
}
this.updateMovementVector();
}
});
__publicField(this, "pointermove", (event) => {
if (!this.dragToLook || this.mouseStatus > 0) {
const container = this.getContainerDimensions();
const halfWidth = container.size[0] / 2;
const halfHeight = container.size[1] / 2;
this.moveState.yawLeft = -(event.pageX - container.offset[0] - halfWidth) / halfWidth;
this.moveState.pitchDown = (event.pageY - container.offset[1] - halfHeight) / halfHeight;
this.updateRotationVector();
}
});
__publicField(this, "pointerup", (event) => {
if (this.dragToLook) {
this.mouseStatus--;
this.moveState.yawLeft = this.moveState.pitchDown = 0;
} else {
switch (event.button) {
case 0:
this.moveState.forward = 0;
break;
case 2:
this.moveState.back = 0;
break;
}
this.updateMovementVector();
}
this.updateRotationVector();
});
__publicField(this, "lastQuaternion", new THREE.Quaternion());
__publicField(this, "lastPosition", new THREE.Vector3());
__publicField(this, "update", (delta) => {
const moveMult = delta * this.movementSpeed;
const rotMult = delta * this.rollSpeed;
this.object.translateX(this.moveVector.x * moveMult);
this.object.translateY(this.moveVector.y * moveMult);
this.object.translateZ(this.moveVector.z * moveMult);
this.tmpQuaternion.set(this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1).normalize();
this.object.quaternion.multiply(this.tmpQuaternion);
if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS || 8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
this.dispatchEvent(this.changeEvent);
this.lastQuaternion.copy(this.object.quaternion);
this.lastPosition.copy(this.object.position);
}
});
__publicField(this, "updateMovementVector", () => {
const forward = this.moveState.forward || this.autoForward && !this.moveState.back ? 1 : 0;
this.moveVector.x = -this.moveState.left + this.moveState.right;
this.moveVector.y = -this.moveState.down + this.moveState.up;
this.moveVector.z = -forward + this.moveState.back;
});
__publicField(this, "updateRotationVector", () => {
this.rotationVector.x = -this.moveState.pitchDown + this.moveState.pitchUp;
this.rotationVector.y = -this.moveState.yawRight + this.moveState.yawLeft;
this.rotationVector.z = -this.moveState.rollRight + this.moveState.rollLeft;
});
__publicField(this, "getContainerDimensions", () => {
if (this.domElement != document && !(this.domElement instanceof Document)) {
return {
size: [this.domElement.offsetWidth, this.domElement.offsetHeight],
offset: [this.domElement.offsetLeft, this.domElement.offsetTop]
};
} else {
return {
size: [window.innerWidth, window.innerHeight],
offset: [0, 0]
};
}
});
// https://github.com/mrdoob/three.js/issues/20575
__publicField(this, "connect", (domElement) => {
this.domElement = domElement;
if (!(domElement instanceof Document)) {
domElement.setAttribute("tabindex", -1);
}
this.domElement.addEventListener("contextmenu", contextmenu);
this.domElement.addEventListener("pointermove", this.pointermove);
this.domElement.addEventListener("pointerdown", this.pointerdown);
this.domElement.addEventListener("pointerup", this.pointerup);
window.addEventListener("keydown", this.keydown);
window.addEventListener("keyup", this.keyup);
});
__publicField(this, "dispose", () => {
this.domElement.removeEventListener("contextmenu", contextmenu);
this.domElement.removeEventListener("pointermove", this.pointermove);
this.domElement.removeEventListener("pointerdown", this.pointerdown);
this.domElement.removeEventListener("pointerup", this.pointerup);
window.removeEventListener("keydown", this.keydown);
window.removeEventListener("keyup", this.keyup);
});
this.object = object;
if (domElement !== void 0)
this.connect(domElement);
this.updateMovementVector();
this.updateRotationVector();
}
}
exports.FlyControls = FlyControls;
//# sourceMappingURL=FlyControls.cjs.map
File diff suppressed because one or more lines are too long
+39
View File
@@ -0,0 +1,39 @@
import { Camera } from 'three';
import { EventDispatcher } from './EventDispatcher';
export interface FlyControlsEventMap {
/**
* Fires when the camera has been transformed by the controls.
*/
change: {};
}
declare class FlyControls extends EventDispatcher<FlyControlsEventMap> {
object: Camera;
domElement: HTMLElement | Document;
movementSpeed: number;
rollSpeed: number;
dragToLook: boolean;
autoForward: boolean;
private changeEvent;
private EPS;
private tmpQuaternion;
private mouseStatus;
private movementSpeedMultiplier;
private moveState;
private moveVector;
private rotationVector;
constructor(object: Camera, domElement?: HTMLElement | Document);
private keydown;
private keyup;
private pointerdown;
private pointermove;
private pointerup;
private lastQuaternion;
private lastPosition;
update: (delta: number) => void;
private updateMovementVector;
private updateRotationVector;
private getContainerDimensions;
connect: (domElement: HTMLElement | Document) => void;
dispose: () => void;
}
export { FlyControls };
+250
View File
@@ -0,0 +1,250 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { Quaternion, Vector3 } from "three";
import { EventDispatcher } from "./EventDispatcher.js";
function contextmenu(event) {
event.preventDefault();
}
class FlyControls extends EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement", null);
__publicField(this, "movementSpeed", 1);
__publicField(this, "rollSpeed", 5e-3);
__publicField(this, "dragToLook", false);
__publicField(this, "autoForward", false);
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "EPS", 1e-6);
__publicField(this, "tmpQuaternion", new Quaternion());
__publicField(this, "mouseStatus", 0);
__publicField(this, "movementSpeedMultiplier", 1);
__publicField(this, "moveState", {
up: 0,
down: 0,
left: 0,
right: 0,
forward: 0,
back: 0,
pitchUp: 0,
pitchDown: 0,
yawLeft: 0,
yawRight: 0,
rollLeft: 0,
rollRight: 0
});
__publicField(this, "moveVector", new Vector3(0, 0, 0));
__publicField(this, "rotationVector", new Vector3(0, 0, 0));
__publicField(this, "keydown", (event) => {
if (event.altKey) {
return;
}
switch (event.code) {
case "ShiftLeft":
case "ShiftRight":
this.movementSpeedMultiplier = 0.1;
break;
case "KeyW":
this.moveState.forward = 1;
break;
case "KeyS":
this.moveState.back = 1;
break;
case "KeyA":
this.moveState.left = 1;
break;
case "KeyD":
this.moveState.right = 1;
break;
case "KeyR":
this.moveState.up = 1;
break;
case "KeyF":
this.moveState.down = 1;
break;
case "ArrowUp":
this.moveState.pitchUp = 1;
break;
case "ArrowDown":
this.moveState.pitchDown = 1;
break;
case "ArrowLeft":
this.moveState.yawLeft = 1;
break;
case "ArrowRight":
this.moveState.yawRight = 1;
break;
case "KeyQ":
this.moveState.rollLeft = 1;
break;
case "KeyE":
this.moveState.rollRight = 1;
break;
}
this.updateMovementVector();
this.updateRotationVector();
});
__publicField(this, "keyup", (event) => {
switch (event.code) {
case "ShiftLeft":
case "ShiftRight":
this.movementSpeedMultiplier = 1;
break;
case "KeyW":
this.moveState.forward = 0;
break;
case "KeyS":
this.moveState.back = 0;
break;
case "KeyA":
this.moveState.left = 0;
break;
case "KeyD":
this.moveState.right = 0;
break;
case "KeyR":
this.moveState.up = 0;
break;
case "KeyF":
this.moveState.down = 0;
break;
case "ArrowUp":
this.moveState.pitchUp = 0;
break;
case "ArrowDown":
this.moveState.pitchDown = 0;
break;
case "ArrowLeft":
this.moveState.yawLeft = 0;
break;
case "ArrowRight":
this.moveState.yawRight = 0;
break;
case "KeyQ":
this.moveState.rollLeft = 0;
break;
case "KeyE":
this.moveState.rollRight = 0;
break;
}
this.updateMovementVector();
this.updateRotationVector();
});
__publicField(this, "pointerdown", (event) => {
if (this.dragToLook) {
this.mouseStatus++;
} else {
switch (event.button) {
case 0:
this.moveState.forward = 1;
break;
case 2:
this.moveState.back = 1;
break;
}
this.updateMovementVector();
}
});
__publicField(this, "pointermove", (event) => {
if (!this.dragToLook || this.mouseStatus > 0) {
const container = this.getContainerDimensions();
const halfWidth = container.size[0] / 2;
const halfHeight = container.size[1] / 2;
this.moveState.yawLeft = -(event.pageX - container.offset[0] - halfWidth) / halfWidth;
this.moveState.pitchDown = (event.pageY - container.offset[1] - halfHeight) / halfHeight;
this.updateRotationVector();
}
});
__publicField(this, "pointerup", (event) => {
if (this.dragToLook) {
this.mouseStatus--;
this.moveState.yawLeft = this.moveState.pitchDown = 0;
} else {
switch (event.button) {
case 0:
this.moveState.forward = 0;
break;
case 2:
this.moveState.back = 0;
break;
}
this.updateMovementVector();
}
this.updateRotationVector();
});
__publicField(this, "lastQuaternion", new Quaternion());
__publicField(this, "lastPosition", new Vector3());
__publicField(this, "update", (delta) => {
const moveMult = delta * this.movementSpeed;
const rotMult = delta * this.rollSpeed;
this.object.translateX(this.moveVector.x * moveMult);
this.object.translateY(this.moveVector.y * moveMult);
this.object.translateZ(this.moveVector.z * moveMult);
this.tmpQuaternion.set(this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1).normalize();
this.object.quaternion.multiply(this.tmpQuaternion);
if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS || 8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
this.dispatchEvent(this.changeEvent);
this.lastQuaternion.copy(this.object.quaternion);
this.lastPosition.copy(this.object.position);
}
});
__publicField(this, "updateMovementVector", () => {
const forward = this.moveState.forward || this.autoForward && !this.moveState.back ? 1 : 0;
this.moveVector.x = -this.moveState.left + this.moveState.right;
this.moveVector.y = -this.moveState.down + this.moveState.up;
this.moveVector.z = -forward + this.moveState.back;
});
__publicField(this, "updateRotationVector", () => {
this.rotationVector.x = -this.moveState.pitchDown + this.moveState.pitchUp;
this.rotationVector.y = -this.moveState.yawRight + this.moveState.yawLeft;
this.rotationVector.z = -this.moveState.rollRight + this.moveState.rollLeft;
});
__publicField(this, "getContainerDimensions", () => {
if (this.domElement != document && !(this.domElement instanceof Document)) {
return {
size: [this.domElement.offsetWidth, this.domElement.offsetHeight],
offset: [this.domElement.offsetLeft, this.domElement.offsetTop]
};
} else {
return {
size: [window.innerWidth, window.innerHeight],
offset: [0, 0]
};
}
});
// https://github.com/mrdoob/three.js/issues/20575
__publicField(this, "connect", (domElement) => {
this.domElement = domElement;
if (!(domElement instanceof Document)) {
domElement.setAttribute("tabindex", -1);
}
this.domElement.addEventListener("contextmenu", contextmenu);
this.domElement.addEventListener("pointermove", this.pointermove);
this.domElement.addEventListener("pointerdown", this.pointerdown);
this.domElement.addEventListener("pointerup", this.pointerup);
window.addEventListener("keydown", this.keydown);
window.addEventListener("keyup", this.keyup);
});
__publicField(this, "dispose", () => {
this.domElement.removeEventListener("contextmenu", contextmenu);
this.domElement.removeEventListener("pointermove", this.pointermove);
this.domElement.removeEventListener("pointerdown", this.pointerdown);
this.domElement.removeEventListener("pointerup", this.pointerup);
window.removeEventListener("keydown", this.keydown);
window.removeEventListener("keyup", this.keyup);
});
this.object = object;
if (domElement !== void 0)
this.connect(domElement);
this.updateMovementVector();
this.updateRotationVector();
}
}
export {
FlyControls
};
//# sourceMappingURL=FlyControls.js.map
File diff suppressed because one or more lines are too long
+882
View File
@@ -0,0 +1,882 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("./EventDispatcher.cjs");
const _ray = /* @__PURE__ */ new THREE.Ray();
const _plane = /* @__PURE__ */ new THREE.Plane();
const TILT_LIMIT = Math.cos(70 * (Math.PI / 180));
const moduloWrapAround = (offset, capacity) => (offset % capacity + capacity) % capacity;
class OrbitControls extends EventDispatcher.EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement");
// Set to false to disable this control
__publicField(this, "enabled", true);
// "target" sets the location of focus, where the object orbits around
__publicField(this, "target", new THREE.Vector3());
// How far you can dolly in and out ( PerspectiveCamera only )
__publicField(this, "minDistance", 0);
__publicField(this, "maxDistance", Infinity);
// How far you can zoom in and out ( OrthographicCamera only )
__publicField(this, "minZoom", 0);
__publicField(this, "maxZoom", Infinity);
// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
__publicField(this, "minPolarAngle", 0);
// radians
__publicField(this, "maxPolarAngle", Math.PI);
// radians
// How far you can orbit horizontally, upper and lower limits.
// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
__publicField(this, "minAzimuthAngle", -Infinity);
// radians
__publicField(this, "maxAzimuthAngle", Infinity);
// radians
// Set to true to enable damping (inertia)
// If damping is enabled, you must call controls.update() in your animation loop
__publicField(this, "enableDamping", false);
__publicField(this, "dampingFactor", 0.05);
// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
// Set to false to disable zooming
__publicField(this, "enableZoom", true);
__publicField(this, "zoomSpeed", 1);
// Set to false to disable rotating
__publicField(this, "enableRotate", true);
__publicField(this, "rotateSpeed", 1);
// Set to false to disable panning
__publicField(this, "enablePan", true);
__publicField(this, "panSpeed", 1);
__publicField(this, "screenSpacePanning", true);
// if false, pan orthogonal to world-space direction camera.up
__publicField(this, "keyPanSpeed", 7);
// pixels moved per arrow key push
__publicField(this, "zoomToCursor", false);
// Set to true to automatically rotate around the target
// If auto-rotate is enabled, you must call controls.update() in your animation loop
__publicField(this, "autoRotate", false);
__publicField(this, "autoRotateSpeed", 2);
// 30 seconds per orbit when fps is 60
__publicField(this, "reverseOrbit", false);
// true if you want to reverse the orbit to mouse drag from left to right = orbits left
__publicField(this, "reverseHorizontalOrbit", false);
// true if you want to reverse the horizontal orbit direction
__publicField(this, "reverseVerticalOrbit", false);
// true if you want to reverse the vertical orbit direction
// The four arrow keys
__publicField(this, "keys", { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" });
// Mouse buttons
__publicField(this, "mouseButtons", {
LEFT: THREE.MOUSE.ROTATE,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.PAN
});
// Touch fingers
__publicField(this, "touches", { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN });
__publicField(this, "target0");
__publicField(this, "position0");
__publicField(this, "zoom0");
// the target DOM element for key events
__publicField(this, "_domElementKeyEvents", null);
__publicField(this, "getPolarAngle");
__publicField(this, "getAzimuthalAngle");
__publicField(this, "setPolarAngle");
__publicField(this, "setAzimuthalAngle");
__publicField(this, "getDistance");
// Not used in most scenarios, however they can be useful for specific use cases
__publicField(this, "getZoomScale");
__publicField(this, "listenToKeyEvents");
__publicField(this, "stopListenToKeyEvents");
__publicField(this, "saveState");
__publicField(this, "reset");
__publicField(this, "update");
__publicField(this, "connect");
__publicField(this, "dispose");
// Dolly in programmatically
__publicField(this, "dollyIn");
// Dolly out programmatically
__publicField(this, "dollyOut");
// Get the current scale
__publicField(this, "getScale");
// Set the current scale (these are not used in most scenarios, however they can be useful for specific use cases)
__publicField(this, "setScale");
this.object = object;
this.domElement = domElement;
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.zoom0 = this.object.zoom;
this.getPolarAngle = () => spherical.phi;
this.getAzimuthalAngle = () => spherical.theta;
this.setPolarAngle = (value) => {
let phi = moduloWrapAround(value, 2 * Math.PI);
let currentPhi = spherical.phi;
if (currentPhi < 0)
currentPhi += 2 * Math.PI;
if (phi < 0)
phi += 2 * Math.PI;
let phiDist = Math.abs(phi - currentPhi);
if (2 * Math.PI - phiDist < phiDist) {
if (phi < currentPhi) {
phi += 2 * Math.PI;
} else {
currentPhi += 2 * Math.PI;
}
}
sphericalDelta.phi = phi - currentPhi;
scope.update();
};
this.setAzimuthalAngle = (value) => {
let theta = moduloWrapAround(value, 2 * Math.PI);
let currentTheta = spherical.theta;
if (currentTheta < 0)
currentTheta += 2 * Math.PI;
if (theta < 0)
theta += 2 * Math.PI;
let thetaDist = Math.abs(theta - currentTheta);
if (2 * Math.PI - thetaDist < thetaDist) {
if (theta < currentTheta) {
theta += 2 * Math.PI;
} else {
currentTheta += 2 * Math.PI;
}
}
sphericalDelta.theta = theta - currentTheta;
scope.update();
};
this.getDistance = () => scope.object.position.distanceTo(scope.target);
this.listenToKeyEvents = (domElement2) => {
domElement2.addEventListener("keydown", onKeyDown);
this._domElementKeyEvents = domElement2;
};
this.stopListenToKeyEvents = () => {
this._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
this._domElementKeyEvents = null;
};
this.saveState = () => {
scope.target0.copy(scope.target);
scope.position0.copy(scope.object.position);
scope.zoom0 = scope.object.zoom;
};
this.reset = () => {
scope.target.copy(scope.target0);
scope.object.position.copy(scope.position0);
scope.object.zoom = scope.zoom0;
scope.object.updateProjectionMatrix();
scope.dispatchEvent(changeEvent);
scope.update();
state = STATE.NONE;
};
this.update = (() => {
const offset = new THREE.Vector3();
const up = new THREE.Vector3(0, 1, 0);
const quat = new THREE.Quaternion().setFromUnitVectors(object.up, up);
const quatInverse = quat.clone().invert();
const lastPosition = new THREE.Vector3();
const lastQuaternion = new THREE.Quaternion();
const twoPI = 2 * Math.PI;
return function update() {
const position = scope.object.position;
quat.setFromUnitVectors(object.up, up);
quatInverse.copy(quat).invert();
offset.copy(position).sub(scope.target);
offset.applyQuaternion(quat);
spherical.setFromVector3(offset);
if (scope.autoRotate && state === STATE.NONE) {
rotateLeft(getAutoRotationAngle());
}
if (scope.enableDamping) {
spherical.theta += sphericalDelta.theta * scope.dampingFactor;
spherical.phi += sphericalDelta.phi * scope.dampingFactor;
} else {
spherical.theta += sphericalDelta.theta;
spherical.phi += sphericalDelta.phi;
}
let min = scope.minAzimuthAngle;
let max = scope.maxAzimuthAngle;
if (isFinite(min) && isFinite(max)) {
if (min < -Math.PI)
min += twoPI;
else if (min > Math.PI)
min -= twoPI;
if (max < -Math.PI)
max += twoPI;
else if (max > Math.PI)
max -= twoPI;
if (min <= max) {
spherical.theta = Math.max(min, Math.min(max, spherical.theta));
} else {
spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
}
}
spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
spherical.makeSafe();
if (scope.enableDamping === true) {
scope.target.addScaledVector(panOffset, scope.dampingFactor);
} else {
scope.target.add(panOffset);
}
if (scope.zoomToCursor && performCursorZoom || scope.object.isOrthographicCamera) {
spherical.radius = clampDistance(spherical.radius);
} else {
spherical.radius = clampDistance(spherical.radius * scale);
}
offset.setFromSpherical(spherical);
offset.applyQuaternion(quatInverse);
position.copy(scope.target).add(offset);
if (!scope.object.matrixAutoUpdate)
scope.object.updateMatrix();
scope.object.lookAt(scope.target);
if (scope.enableDamping === true) {
sphericalDelta.theta *= 1 - scope.dampingFactor;
sphericalDelta.phi *= 1 - scope.dampingFactor;
panOffset.multiplyScalar(1 - scope.dampingFactor);
} else {
sphericalDelta.set(0, 0, 0);
panOffset.set(0, 0, 0);
}
let zoomChanged = false;
if (scope.zoomToCursor && performCursorZoom) {
let newRadius = null;
if (scope.object instanceof THREE.PerspectiveCamera && scope.object.isPerspectiveCamera) {
const prevRadius = offset.length();
newRadius = clampDistance(prevRadius * scale);
const radiusDelta = prevRadius - newRadius;
scope.object.position.addScaledVector(dollyDirection, radiusDelta);
scope.object.updateMatrixWorld();
} else if (scope.object.isOrthographicCamera) {
const mouseBefore = new THREE.Vector3(mouse.x, mouse.y, 0);
mouseBefore.unproject(scope.object);
scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / scale));
scope.object.updateProjectionMatrix();
zoomChanged = true;
const mouseAfter = new THREE.Vector3(mouse.x, mouse.y, 0);
mouseAfter.unproject(scope.object);
scope.object.position.sub(mouseAfter).add(mouseBefore);
scope.object.updateMatrixWorld();
newRadius = offset.length();
} else {
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.");
scope.zoomToCursor = false;
}
if (newRadius !== null) {
if (scope.screenSpacePanning) {
scope.target.set(0, 0, -1).transformDirection(scope.object.matrix).multiplyScalar(newRadius).add(scope.object.position);
} else {
_ray.origin.copy(scope.object.position);
_ray.direction.set(0, 0, -1).transformDirection(scope.object.matrix);
if (Math.abs(scope.object.up.dot(_ray.direction)) < TILT_LIMIT) {
object.lookAt(scope.target);
} else {
_plane.setFromNormalAndCoplanarPoint(scope.object.up, scope.target);
_ray.intersectPlane(_plane, scope.target);
}
}
}
} else if (scope.object instanceof THREE.OrthographicCamera && scope.object.isOrthographicCamera) {
zoomChanged = scale !== 1;
if (zoomChanged) {
scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / scale));
scope.object.updateProjectionMatrix();
}
}
scale = 1;
performCursorZoom = false;
if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
scope.dispatchEvent(changeEvent);
lastPosition.copy(scope.object.position);
lastQuaternion.copy(scope.object.quaternion);
zoomChanged = false;
return true;
}
return false;
};
})();
this.connect = (domElement2) => {
scope.domElement = domElement2;
scope.domElement.style.touchAction = "none";
scope.domElement.addEventListener("contextmenu", onContextMenu);
scope.domElement.addEventListener("pointerdown", onPointerDown);
scope.domElement.addEventListener("pointercancel", onPointerUp);
scope.domElement.addEventListener("wheel", onMouseWheel);
};
this.dispose = () => {
var _a, _b, _c, _d, _e, _f;
if (scope.domElement) {
scope.domElement.style.touchAction = "auto";
}
(_a = scope.domElement) == null ? void 0 : _a.removeEventListener("contextmenu", onContextMenu);
(_b = scope.domElement) == null ? void 0 : _b.removeEventListener("pointerdown", onPointerDown);
(_c = scope.domElement) == null ? void 0 : _c.removeEventListener("pointercancel", onPointerUp);
(_d = scope.domElement) == null ? void 0 : _d.removeEventListener("wheel", onMouseWheel);
(_e = scope.domElement) == null ? void 0 : _e.ownerDocument.removeEventListener("pointermove", onPointerMove);
(_f = scope.domElement) == null ? void 0 : _f.ownerDocument.removeEventListener("pointerup", onPointerUp);
if (scope._domElementKeyEvents !== null) {
scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
}
};
const scope = this;
const changeEvent = { type: "change" };
const startEvent = { type: "start" };
const endEvent = { type: "end" };
const STATE = {
NONE: -1,
ROTATE: 0,
DOLLY: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_PAN: 4,
TOUCH_DOLLY_PAN: 5,
TOUCH_DOLLY_ROTATE: 6
};
let state = STATE.NONE;
const EPS = 1e-6;
const spherical = new THREE.Spherical();
const sphericalDelta = new THREE.Spherical();
let scale = 1;
const panOffset = new THREE.Vector3();
const rotateStart = new THREE.Vector2();
const rotateEnd = new THREE.Vector2();
const rotateDelta = new THREE.Vector2();
const panStart = new THREE.Vector2();
const panEnd = new THREE.Vector2();
const panDelta = new THREE.Vector2();
const dollyStart = new THREE.Vector2();
const dollyEnd = new THREE.Vector2();
const dollyDelta = new THREE.Vector2();
const dollyDirection = new THREE.Vector3();
const mouse = new THREE.Vector2();
let performCursorZoom = false;
const pointers = [];
const pointerPositions = {};
function getAutoRotationAngle() {
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
}
function getZoomScale() {
return Math.pow(0.95, scope.zoomSpeed);
}
function rotateLeft(angle) {
if (scope.reverseOrbit || scope.reverseHorizontalOrbit) {
sphericalDelta.theta += angle;
} else {
sphericalDelta.theta -= angle;
}
}
function rotateUp(angle) {
if (scope.reverseOrbit || scope.reverseVerticalOrbit) {
sphericalDelta.phi += angle;
} else {
sphericalDelta.phi -= angle;
}
}
const panLeft = (() => {
const v = new THREE.Vector3();
return function panLeft2(distance, objectMatrix) {
v.setFromMatrixColumn(objectMatrix, 0);
v.multiplyScalar(-distance);
panOffset.add(v);
};
})();
const panUp = (() => {
const v = new THREE.Vector3();
return function panUp2(distance, objectMatrix) {
if (scope.screenSpacePanning === true) {
v.setFromMatrixColumn(objectMatrix, 1);
} else {
v.setFromMatrixColumn(objectMatrix, 0);
v.crossVectors(scope.object.up, v);
}
v.multiplyScalar(distance);
panOffset.add(v);
};
})();
const pan = (() => {
const offset = new THREE.Vector3();
return function pan2(deltaX, deltaY) {
const element = scope.domElement;
if (element && scope.object instanceof THREE.PerspectiveCamera && scope.object.isPerspectiveCamera) {
const position = scope.object.position;
offset.copy(position).sub(scope.target);
let targetDistance = offset.length();
targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
} else if (element && scope.object instanceof THREE.OrthographicCamera && scope.object.isOrthographicCamera) {
panLeft(
deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth,
scope.object.matrix
);
panUp(
deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight,
scope.object.matrix
);
} else {
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
scope.enablePan = false;
}
};
})();
function setScale(newScale) {
if (scope.object instanceof THREE.PerspectiveCamera && scope.object.isPerspectiveCamera || scope.object instanceof THREE.OrthographicCamera && scope.object.isOrthographicCamera) {
scale = newScale;
} else {
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
scope.enableZoom = false;
}
}
function dollyOut(dollyScale) {
setScale(scale / dollyScale);
}
function dollyIn(dollyScale) {
setScale(scale * dollyScale);
}
function updateMouseParameters(event) {
if (!scope.zoomToCursor || !scope.domElement) {
return;
}
performCursorZoom = true;
const rect = scope.domElement.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const w = rect.width;
const h = rect.height;
mouse.x = x / w * 2 - 1;
mouse.y = -(y / h) * 2 + 1;
dollyDirection.set(mouse.x, mouse.y, 1).unproject(scope.object).sub(scope.object.position).normalize();
}
function clampDistance(dist) {
return Math.max(scope.minDistance, Math.min(scope.maxDistance, dist));
}
function handleMouseDownRotate(event) {
rotateStart.set(event.clientX, event.clientY);
}
function handleMouseDownDolly(event) {
updateMouseParameters(event);
dollyStart.set(event.clientX, event.clientY);
}
function handleMouseDownPan(event) {
panStart.set(event.clientX, event.clientY);
}
function handleMouseMoveRotate(event) {
rotateEnd.set(event.clientX, event.clientY);
rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
const element = scope.domElement;
if (element) {
rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
}
rotateStart.copy(rotateEnd);
scope.update();
}
function handleMouseMoveDolly(event) {
dollyEnd.set(event.clientX, event.clientY);
dollyDelta.subVectors(dollyEnd, dollyStart);
if (dollyDelta.y > 0) {
dollyOut(getZoomScale());
} else if (dollyDelta.y < 0) {
dollyIn(getZoomScale());
}
dollyStart.copy(dollyEnd);
scope.update();
}
function handleMouseMovePan(event) {
panEnd.set(event.clientX, event.clientY);
panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
pan(panDelta.x, panDelta.y);
panStart.copy(panEnd);
scope.update();
}
function handleMouseWheel(event) {
updateMouseParameters(event);
if (event.deltaY < 0) {
dollyIn(getZoomScale());
} else if (event.deltaY > 0) {
dollyOut(getZoomScale());
}
scope.update();
}
function handleKeyDown(event) {
let needsUpdate = false;
switch (event.code) {
case scope.keys.UP:
pan(0, scope.keyPanSpeed);
needsUpdate = true;
break;
case scope.keys.BOTTOM:
pan(0, -scope.keyPanSpeed);
needsUpdate = true;
break;
case scope.keys.LEFT:
pan(scope.keyPanSpeed, 0);
needsUpdate = true;
break;
case scope.keys.RIGHT:
pan(-scope.keyPanSpeed, 0);
needsUpdate = true;
break;
}
if (needsUpdate) {
event.preventDefault();
scope.update();
}
}
function handleTouchStartRotate() {
if (pointers.length == 1) {
rotateStart.set(pointers[0].pageX, pointers[0].pageY);
} else {
const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
rotateStart.set(x, y);
}
}
function handleTouchStartPan() {
if (pointers.length == 1) {
panStart.set(pointers[0].pageX, pointers[0].pageY);
} else {
const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
panStart.set(x, y);
}
}
function handleTouchStartDolly() {
const dx = pointers[0].pageX - pointers[1].pageX;
const dy = pointers[0].pageY - pointers[1].pageY;
const distance = Math.sqrt(dx * dx + dy * dy);
dollyStart.set(0, distance);
}
function handleTouchStartDollyPan() {
if (scope.enableZoom)
handleTouchStartDolly();
if (scope.enablePan)
handleTouchStartPan();
}
function handleTouchStartDollyRotate() {
if (scope.enableZoom)
handleTouchStartDolly();
if (scope.enableRotate)
handleTouchStartRotate();
}
function handleTouchMoveRotate(event) {
if (pointers.length == 1) {
rotateEnd.set(event.pageX, event.pageY);
} else {
const position = getSecondPointerPosition(event);
const x = 0.5 * (event.pageX + position.x);
const y = 0.5 * (event.pageY + position.y);
rotateEnd.set(x, y);
}
rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
const element = scope.domElement;
if (element) {
rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
}
rotateStart.copy(rotateEnd);
}
function handleTouchMovePan(event) {
if (pointers.length == 1) {
panEnd.set(event.pageX, event.pageY);
} else {
const position = getSecondPointerPosition(event);
const x = 0.5 * (event.pageX + position.x);
const y = 0.5 * (event.pageY + position.y);
panEnd.set(x, y);
}
panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
pan(panDelta.x, panDelta.y);
panStart.copy(panEnd);
}
function handleTouchMoveDolly(event) {
const position = getSecondPointerPosition(event);
const dx = event.pageX - position.x;
const dy = event.pageY - position.y;
const distance = Math.sqrt(dx * dx + dy * dy);
dollyEnd.set(0, distance);
dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
dollyOut(dollyDelta.y);
dollyStart.copy(dollyEnd);
}
function handleTouchMoveDollyPan(event) {
if (scope.enableZoom)
handleTouchMoveDolly(event);
if (scope.enablePan)
handleTouchMovePan(event);
}
function handleTouchMoveDollyRotate(event) {
if (scope.enableZoom)
handleTouchMoveDolly(event);
if (scope.enableRotate)
handleTouchMoveRotate(event);
}
function onPointerDown(event) {
var _a, _b;
if (scope.enabled === false)
return;
if (pointers.length === 0) {
(_a = scope.domElement) == null ? void 0 : _a.ownerDocument.addEventListener("pointermove", onPointerMove);
(_b = scope.domElement) == null ? void 0 : _b.ownerDocument.addEventListener("pointerup", onPointerUp);
}
addPointer(event);
if (event.pointerType === "touch") {
onTouchStart(event);
} else {
onMouseDown(event);
}
}
function onPointerMove(event) {
if (scope.enabled === false)
return;
if (event.pointerType === "touch") {
onTouchMove(event);
} else {
onMouseMove(event);
}
}
function onPointerUp(event) {
var _a, _b, _c;
removePointer(event);
if (pointers.length === 0) {
(_a = scope.domElement) == null ? void 0 : _a.releasePointerCapture(event.pointerId);
(_b = scope.domElement) == null ? void 0 : _b.ownerDocument.removeEventListener("pointermove", onPointerMove);
(_c = scope.domElement) == null ? void 0 : _c.ownerDocument.removeEventListener("pointerup", onPointerUp);
}
scope.dispatchEvent(endEvent);
state = STATE.NONE;
}
function onMouseDown(event) {
let mouseAction;
switch (event.button) {
case 0:
mouseAction = scope.mouseButtons.LEFT;
break;
case 1:
mouseAction = scope.mouseButtons.MIDDLE;
break;
case 2:
mouseAction = scope.mouseButtons.RIGHT;
break;
default:
mouseAction = -1;
}
switch (mouseAction) {
case THREE.MOUSE.DOLLY:
if (scope.enableZoom === false)
return;
handleMouseDownDolly(event);
state = STATE.DOLLY;
break;
case THREE.MOUSE.ROTATE:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (scope.enablePan === false)
return;
handleMouseDownPan(event);
state = STATE.PAN;
} else {
if (scope.enableRotate === false)
return;
handleMouseDownRotate(event);
state = STATE.ROTATE;
}
break;
case THREE.MOUSE.PAN:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (scope.enableRotate === false)
return;
handleMouseDownRotate(event);
state = STATE.ROTATE;
} else {
if (scope.enablePan === false)
return;
handleMouseDownPan(event);
state = STATE.PAN;
}
break;
default:
state = STATE.NONE;
}
if (state !== STATE.NONE) {
scope.dispatchEvent(startEvent);
}
}
function onMouseMove(event) {
if (scope.enabled === false)
return;
switch (state) {
case STATE.ROTATE:
if (scope.enableRotate === false)
return;
handleMouseMoveRotate(event);
break;
case STATE.DOLLY:
if (scope.enableZoom === false)
return;
handleMouseMoveDolly(event);
break;
case STATE.PAN:
if (scope.enablePan === false)
return;
handleMouseMovePan(event);
break;
}
}
function onMouseWheel(event) {
if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE) {
return;
}
event.preventDefault();
scope.dispatchEvent(startEvent);
handleMouseWheel(event);
scope.dispatchEvent(endEvent);
}
function onKeyDown(event) {
if (scope.enabled === false || scope.enablePan === false)
return;
handleKeyDown(event);
}
function onTouchStart(event) {
trackPointer(event);
switch (pointers.length) {
case 1:
switch (scope.touches.ONE) {
case THREE.TOUCH.ROTATE:
if (scope.enableRotate === false)
return;
handleTouchStartRotate();
state = STATE.TOUCH_ROTATE;
break;
case THREE.TOUCH.PAN:
if (scope.enablePan === false)
return;
handleTouchStartPan();
state = STATE.TOUCH_PAN;
break;
default:
state = STATE.NONE;
}
break;
case 2:
switch (scope.touches.TWO) {
case THREE.TOUCH.DOLLY_PAN:
if (scope.enableZoom === false && scope.enablePan === false)
return;
handleTouchStartDollyPan();
state = STATE.TOUCH_DOLLY_PAN;
break;
case THREE.TOUCH.DOLLY_ROTATE:
if (scope.enableZoom === false && scope.enableRotate === false)
return;
handleTouchStartDollyRotate();
state = STATE.TOUCH_DOLLY_ROTATE;
break;
default:
state = STATE.NONE;
}
break;
default:
state = STATE.NONE;
}
if (state !== STATE.NONE) {
scope.dispatchEvent(startEvent);
}
}
function onTouchMove(event) {
trackPointer(event);
switch (state) {
case STATE.TOUCH_ROTATE:
if (scope.enableRotate === false)
return;
handleTouchMoveRotate(event);
scope.update();
break;
case STATE.TOUCH_PAN:
if (scope.enablePan === false)
return;
handleTouchMovePan(event);
scope.update();
break;
case STATE.TOUCH_DOLLY_PAN:
if (scope.enableZoom === false && scope.enablePan === false)
return;
handleTouchMoveDollyPan(event);
scope.update();
break;
case STATE.TOUCH_DOLLY_ROTATE:
if (scope.enableZoom === false && scope.enableRotate === false)
return;
handleTouchMoveDollyRotate(event);
scope.update();
break;
default:
state = STATE.NONE;
}
}
function onContextMenu(event) {
if (scope.enabled === false)
return;
event.preventDefault();
}
function addPointer(event) {
pointers.push(event);
}
function removePointer(event) {
delete pointerPositions[event.pointerId];
for (let i = 0; i < pointers.length; i++) {
if (pointers[i].pointerId == event.pointerId) {
pointers.splice(i, 1);
return;
}
}
}
function trackPointer(event) {
let position = pointerPositions[event.pointerId];
if (position === void 0) {
position = new THREE.Vector2();
pointerPositions[event.pointerId] = position;
}
position.set(event.pageX, event.pageY);
}
function getSecondPointerPosition(event) {
const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0];
return pointerPositions[pointer.pointerId];
}
this.dollyIn = (dollyScale = getZoomScale()) => {
dollyIn(dollyScale);
scope.update();
};
this.dollyOut = (dollyScale = getZoomScale()) => {
dollyOut(dollyScale);
scope.update();
};
this.getScale = () => {
return scale;
};
this.setScale = (newScale) => {
setScale(newScale);
scope.update();
};
this.getZoomScale = () => {
return getZoomScale();
};
if (domElement !== void 0)
this.connect(domElement);
this.update();
}
}
class MapControls extends OrbitControls {
constructor(object, domElement) {
super(object, domElement);
this.screenSpacePanning = false;
this.mouseButtons.LEFT = THREE.MOUSE.PAN;
this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE;
this.touches.ONE = THREE.TOUCH.PAN;
this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE;
}
}
exports.MapControls = MapControls;
exports.OrbitControls = OrbitControls;
//# sourceMappingURL=OrbitControls.cjs.map
File diff suppressed because one or more lines are too long
+74
View File
@@ -0,0 +1,74 @@
import { MOUSE, OrthographicCamera, PerspectiveCamera, TOUCH, Vector3 } from 'three';
import { EventDispatcher } from './EventDispatcher';
import { StandardControlsEventMap } from './StandardControlsEventMap';
declare class OrbitControls extends EventDispatcher<StandardControlsEventMap> {
object: PerspectiveCamera | OrthographicCamera;
domElement: HTMLElement | undefined;
enabled: boolean;
target: Vector3;
minDistance: number;
maxDistance: number;
minZoom: number;
maxZoom: number;
minPolarAngle: number;
maxPolarAngle: number;
minAzimuthAngle: number;
maxAzimuthAngle: number;
enableDamping: boolean;
dampingFactor: number;
enableZoom: boolean;
zoomSpeed: number;
enableRotate: boolean;
rotateSpeed: number;
enablePan: boolean;
panSpeed: number;
screenSpacePanning: boolean;
keyPanSpeed: number;
zoomToCursor: boolean;
autoRotate: boolean;
autoRotateSpeed: number;
reverseOrbit: boolean;
reverseHorizontalOrbit: boolean;
reverseVerticalOrbit: boolean;
keys: {
LEFT: string;
UP: string;
RIGHT: string;
BOTTOM: string;
};
mouseButtons: Partial<{
LEFT: MOUSE;
MIDDLE: MOUSE;
RIGHT: MOUSE;
}>;
touches: Partial<{
ONE: TOUCH;
TWO: TOUCH;
}>;
target0: Vector3;
position0: Vector3;
zoom0: number;
_domElementKeyEvents: any;
getPolarAngle: () => number;
getAzimuthalAngle: () => number;
setPolarAngle: (x: number) => void;
setAzimuthalAngle: (x: number) => void;
getDistance: () => number;
getZoomScale: () => number;
listenToKeyEvents: (domElement: HTMLElement) => void;
stopListenToKeyEvents: () => void;
saveState: () => void;
reset: () => void;
update: () => void;
connect: (domElement: HTMLElement) => void;
dispose: () => void;
dollyIn: (dollyScale?: number) => void;
dollyOut: (dollyScale?: number) => void;
getScale: () => number;
setScale: (newScale: number) => void;
constructor(object: PerspectiveCamera | OrthographicCamera, domElement?: HTMLElement);
}
declare class MapControls extends OrbitControls {
constructor(object: PerspectiveCamera | OrthographicCamera, domElement?: HTMLElement);
}
export { OrbitControls, MapControls };
+882
View File
@@ -0,0 +1,882 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { Vector3, MOUSE, TOUCH, Quaternion, PerspectiveCamera, OrthographicCamera, Spherical, Vector2, Ray, Plane } from "three";
import { EventDispatcher } from "./EventDispatcher.js";
const _ray = /* @__PURE__ */ new Ray();
const _plane = /* @__PURE__ */ new Plane();
const TILT_LIMIT = Math.cos(70 * (Math.PI / 180));
const moduloWrapAround = (offset, capacity) => (offset % capacity + capacity) % capacity;
class OrbitControls extends EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement");
// Set to false to disable this control
__publicField(this, "enabled", true);
// "target" sets the location of focus, where the object orbits around
__publicField(this, "target", new Vector3());
// How far you can dolly in and out ( PerspectiveCamera only )
__publicField(this, "minDistance", 0);
__publicField(this, "maxDistance", Infinity);
// How far you can zoom in and out ( OrthographicCamera only )
__publicField(this, "minZoom", 0);
__publicField(this, "maxZoom", Infinity);
// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
__publicField(this, "minPolarAngle", 0);
// radians
__publicField(this, "maxPolarAngle", Math.PI);
// radians
// How far you can orbit horizontally, upper and lower limits.
// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
__publicField(this, "minAzimuthAngle", -Infinity);
// radians
__publicField(this, "maxAzimuthAngle", Infinity);
// radians
// Set to true to enable damping (inertia)
// If damping is enabled, you must call controls.update() in your animation loop
__publicField(this, "enableDamping", false);
__publicField(this, "dampingFactor", 0.05);
// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
// Set to false to disable zooming
__publicField(this, "enableZoom", true);
__publicField(this, "zoomSpeed", 1);
// Set to false to disable rotating
__publicField(this, "enableRotate", true);
__publicField(this, "rotateSpeed", 1);
// Set to false to disable panning
__publicField(this, "enablePan", true);
__publicField(this, "panSpeed", 1);
__publicField(this, "screenSpacePanning", true);
// if false, pan orthogonal to world-space direction camera.up
__publicField(this, "keyPanSpeed", 7);
// pixels moved per arrow key push
__publicField(this, "zoomToCursor", false);
// Set to true to automatically rotate around the target
// If auto-rotate is enabled, you must call controls.update() in your animation loop
__publicField(this, "autoRotate", false);
__publicField(this, "autoRotateSpeed", 2);
// 30 seconds per orbit when fps is 60
__publicField(this, "reverseOrbit", false);
// true if you want to reverse the orbit to mouse drag from left to right = orbits left
__publicField(this, "reverseHorizontalOrbit", false);
// true if you want to reverse the horizontal orbit direction
__publicField(this, "reverseVerticalOrbit", false);
// true if you want to reverse the vertical orbit direction
// The four arrow keys
__publicField(this, "keys", { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" });
// Mouse buttons
__publicField(this, "mouseButtons", {
LEFT: MOUSE.ROTATE,
MIDDLE: MOUSE.DOLLY,
RIGHT: MOUSE.PAN
});
// Touch fingers
__publicField(this, "touches", { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN });
__publicField(this, "target0");
__publicField(this, "position0");
__publicField(this, "zoom0");
// the target DOM element for key events
__publicField(this, "_domElementKeyEvents", null);
__publicField(this, "getPolarAngle");
__publicField(this, "getAzimuthalAngle");
__publicField(this, "setPolarAngle");
__publicField(this, "setAzimuthalAngle");
__publicField(this, "getDistance");
// Not used in most scenarios, however they can be useful for specific use cases
__publicField(this, "getZoomScale");
__publicField(this, "listenToKeyEvents");
__publicField(this, "stopListenToKeyEvents");
__publicField(this, "saveState");
__publicField(this, "reset");
__publicField(this, "update");
__publicField(this, "connect");
__publicField(this, "dispose");
// Dolly in programmatically
__publicField(this, "dollyIn");
// Dolly out programmatically
__publicField(this, "dollyOut");
// Get the current scale
__publicField(this, "getScale");
// Set the current scale (these are not used in most scenarios, however they can be useful for specific use cases)
__publicField(this, "setScale");
this.object = object;
this.domElement = domElement;
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.zoom0 = this.object.zoom;
this.getPolarAngle = () => spherical.phi;
this.getAzimuthalAngle = () => spherical.theta;
this.setPolarAngle = (value) => {
let phi = moduloWrapAround(value, 2 * Math.PI);
let currentPhi = spherical.phi;
if (currentPhi < 0)
currentPhi += 2 * Math.PI;
if (phi < 0)
phi += 2 * Math.PI;
let phiDist = Math.abs(phi - currentPhi);
if (2 * Math.PI - phiDist < phiDist) {
if (phi < currentPhi) {
phi += 2 * Math.PI;
} else {
currentPhi += 2 * Math.PI;
}
}
sphericalDelta.phi = phi - currentPhi;
scope.update();
};
this.setAzimuthalAngle = (value) => {
let theta = moduloWrapAround(value, 2 * Math.PI);
let currentTheta = spherical.theta;
if (currentTheta < 0)
currentTheta += 2 * Math.PI;
if (theta < 0)
theta += 2 * Math.PI;
let thetaDist = Math.abs(theta - currentTheta);
if (2 * Math.PI - thetaDist < thetaDist) {
if (theta < currentTheta) {
theta += 2 * Math.PI;
} else {
currentTheta += 2 * Math.PI;
}
}
sphericalDelta.theta = theta - currentTheta;
scope.update();
};
this.getDistance = () => scope.object.position.distanceTo(scope.target);
this.listenToKeyEvents = (domElement2) => {
domElement2.addEventListener("keydown", onKeyDown);
this._domElementKeyEvents = domElement2;
};
this.stopListenToKeyEvents = () => {
this._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
this._domElementKeyEvents = null;
};
this.saveState = () => {
scope.target0.copy(scope.target);
scope.position0.copy(scope.object.position);
scope.zoom0 = scope.object.zoom;
};
this.reset = () => {
scope.target.copy(scope.target0);
scope.object.position.copy(scope.position0);
scope.object.zoom = scope.zoom0;
scope.object.updateProjectionMatrix();
scope.dispatchEvent(changeEvent);
scope.update();
state = STATE.NONE;
};
this.update = (() => {
const offset = new Vector3();
const up = new Vector3(0, 1, 0);
const quat = new Quaternion().setFromUnitVectors(object.up, up);
const quatInverse = quat.clone().invert();
const lastPosition = new Vector3();
const lastQuaternion = new Quaternion();
const twoPI = 2 * Math.PI;
return function update() {
const position = scope.object.position;
quat.setFromUnitVectors(object.up, up);
quatInverse.copy(quat).invert();
offset.copy(position).sub(scope.target);
offset.applyQuaternion(quat);
spherical.setFromVector3(offset);
if (scope.autoRotate && state === STATE.NONE) {
rotateLeft(getAutoRotationAngle());
}
if (scope.enableDamping) {
spherical.theta += sphericalDelta.theta * scope.dampingFactor;
spherical.phi += sphericalDelta.phi * scope.dampingFactor;
} else {
spherical.theta += sphericalDelta.theta;
spherical.phi += sphericalDelta.phi;
}
let min = scope.minAzimuthAngle;
let max = scope.maxAzimuthAngle;
if (isFinite(min) && isFinite(max)) {
if (min < -Math.PI)
min += twoPI;
else if (min > Math.PI)
min -= twoPI;
if (max < -Math.PI)
max += twoPI;
else if (max > Math.PI)
max -= twoPI;
if (min <= max) {
spherical.theta = Math.max(min, Math.min(max, spherical.theta));
} else {
spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
}
}
spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
spherical.makeSafe();
if (scope.enableDamping === true) {
scope.target.addScaledVector(panOffset, scope.dampingFactor);
} else {
scope.target.add(panOffset);
}
if (scope.zoomToCursor && performCursorZoom || scope.object.isOrthographicCamera) {
spherical.radius = clampDistance(spherical.radius);
} else {
spherical.radius = clampDistance(spherical.radius * scale);
}
offset.setFromSpherical(spherical);
offset.applyQuaternion(quatInverse);
position.copy(scope.target).add(offset);
if (!scope.object.matrixAutoUpdate)
scope.object.updateMatrix();
scope.object.lookAt(scope.target);
if (scope.enableDamping === true) {
sphericalDelta.theta *= 1 - scope.dampingFactor;
sphericalDelta.phi *= 1 - scope.dampingFactor;
panOffset.multiplyScalar(1 - scope.dampingFactor);
} else {
sphericalDelta.set(0, 0, 0);
panOffset.set(0, 0, 0);
}
let zoomChanged = false;
if (scope.zoomToCursor && performCursorZoom) {
let newRadius = null;
if (scope.object instanceof PerspectiveCamera && scope.object.isPerspectiveCamera) {
const prevRadius = offset.length();
newRadius = clampDistance(prevRadius * scale);
const radiusDelta = prevRadius - newRadius;
scope.object.position.addScaledVector(dollyDirection, radiusDelta);
scope.object.updateMatrixWorld();
} else if (scope.object.isOrthographicCamera) {
const mouseBefore = new Vector3(mouse.x, mouse.y, 0);
mouseBefore.unproject(scope.object);
scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / scale));
scope.object.updateProjectionMatrix();
zoomChanged = true;
const mouseAfter = new Vector3(mouse.x, mouse.y, 0);
mouseAfter.unproject(scope.object);
scope.object.position.sub(mouseAfter).add(mouseBefore);
scope.object.updateMatrixWorld();
newRadius = offset.length();
} else {
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.");
scope.zoomToCursor = false;
}
if (newRadius !== null) {
if (scope.screenSpacePanning) {
scope.target.set(0, 0, -1).transformDirection(scope.object.matrix).multiplyScalar(newRadius).add(scope.object.position);
} else {
_ray.origin.copy(scope.object.position);
_ray.direction.set(0, 0, -1).transformDirection(scope.object.matrix);
if (Math.abs(scope.object.up.dot(_ray.direction)) < TILT_LIMIT) {
object.lookAt(scope.target);
} else {
_plane.setFromNormalAndCoplanarPoint(scope.object.up, scope.target);
_ray.intersectPlane(_plane, scope.target);
}
}
}
} else if (scope.object instanceof OrthographicCamera && scope.object.isOrthographicCamera) {
zoomChanged = scale !== 1;
if (zoomChanged) {
scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / scale));
scope.object.updateProjectionMatrix();
}
}
scale = 1;
performCursorZoom = false;
if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
scope.dispatchEvent(changeEvent);
lastPosition.copy(scope.object.position);
lastQuaternion.copy(scope.object.quaternion);
zoomChanged = false;
return true;
}
return false;
};
})();
this.connect = (domElement2) => {
scope.domElement = domElement2;
scope.domElement.style.touchAction = "none";
scope.domElement.addEventListener("contextmenu", onContextMenu);
scope.domElement.addEventListener("pointerdown", onPointerDown);
scope.domElement.addEventListener("pointercancel", onPointerUp);
scope.domElement.addEventListener("wheel", onMouseWheel);
};
this.dispose = () => {
var _a, _b, _c, _d, _e, _f;
if (scope.domElement) {
scope.domElement.style.touchAction = "auto";
}
(_a = scope.domElement) == null ? void 0 : _a.removeEventListener("contextmenu", onContextMenu);
(_b = scope.domElement) == null ? void 0 : _b.removeEventListener("pointerdown", onPointerDown);
(_c = scope.domElement) == null ? void 0 : _c.removeEventListener("pointercancel", onPointerUp);
(_d = scope.domElement) == null ? void 0 : _d.removeEventListener("wheel", onMouseWheel);
(_e = scope.domElement) == null ? void 0 : _e.ownerDocument.removeEventListener("pointermove", onPointerMove);
(_f = scope.domElement) == null ? void 0 : _f.ownerDocument.removeEventListener("pointerup", onPointerUp);
if (scope._domElementKeyEvents !== null) {
scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
}
};
const scope = this;
const changeEvent = { type: "change" };
const startEvent = { type: "start" };
const endEvent = { type: "end" };
const STATE = {
NONE: -1,
ROTATE: 0,
DOLLY: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_PAN: 4,
TOUCH_DOLLY_PAN: 5,
TOUCH_DOLLY_ROTATE: 6
};
let state = STATE.NONE;
const EPS = 1e-6;
const spherical = new Spherical();
const sphericalDelta = new Spherical();
let scale = 1;
const panOffset = new Vector3();
const rotateStart = new Vector2();
const rotateEnd = new Vector2();
const rotateDelta = new Vector2();
const panStart = new Vector2();
const panEnd = new Vector2();
const panDelta = new Vector2();
const dollyStart = new Vector2();
const dollyEnd = new Vector2();
const dollyDelta = new Vector2();
const dollyDirection = new Vector3();
const mouse = new Vector2();
let performCursorZoom = false;
const pointers = [];
const pointerPositions = {};
function getAutoRotationAngle() {
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
}
function getZoomScale() {
return Math.pow(0.95, scope.zoomSpeed);
}
function rotateLeft(angle) {
if (scope.reverseOrbit || scope.reverseHorizontalOrbit) {
sphericalDelta.theta += angle;
} else {
sphericalDelta.theta -= angle;
}
}
function rotateUp(angle) {
if (scope.reverseOrbit || scope.reverseVerticalOrbit) {
sphericalDelta.phi += angle;
} else {
sphericalDelta.phi -= angle;
}
}
const panLeft = (() => {
const v = new Vector3();
return function panLeft2(distance, objectMatrix) {
v.setFromMatrixColumn(objectMatrix, 0);
v.multiplyScalar(-distance);
panOffset.add(v);
};
})();
const panUp = (() => {
const v = new Vector3();
return function panUp2(distance, objectMatrix) {
if (scope.screenSpacePanning === true) {
v.setFromMatrixColumn(objectMatrix, 1);
} else {
v.setFromMatrixColumn(objectMatrix, 0);
v.crossVectors(scope.object.up, v);
}
v.multiplyScalar(distance);
panOffset.add(v);
};
})();
const pan = (() => {
const offset = new Vector3();
return function pan2(deltaX, deltaY) {
const element = scope.domElement;
if (element && scope.object instanceof PerspectiveCamera && scope.object.isPerspectiveCamera) {
const position = scope.object.position;
offset.copy(position).sub(scope.target);
let targetDistance = offset.length();
targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
} else if (element && scope.object instanceof OrthographicCamera && scope.object.isOrthographicCamera) {
panLeft(
deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth,
scope.object.matrix
);
panUp(
deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight,
scope.object.matrix
);
} else {
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
scope.enablePan = false;
}
};
})();
function setScale(newScale) {
if (scope.object instanceof PerspectiveCamera && scope.object.isPerspectiveCamera || scope.object instanceof OrthographicCamera && scope.object.isOrthographicCamera) {
scale = newScale;
} else {
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
scope.enableZoom = false;
}
}
function dollyOut(dollyScale) {
setScale(scale / dollyScale);
}
function dollyIn(dollyScale) {
setScale(scale * dollyScale);
}
function updateMouseParameters(event) {
if (!scope.zoomToCursor || !scope.domElement) {
return;
}
performCursorZoom = true;
const rect = scope.domElement.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const w = rect.width;
const h = rect.height;
mouse.x = x / w * 2 - 1;
mouse.y = -(y / h) * 2 + 1;
dollyDirection.set(mouse.x, mouse.y, 1).unproject(scope.object).sub(scope.object.position).normalize();
}
function clampDistance(dist) {
return Math.max(scope.minDistance, Math.min(scope.maxDistance, dist));
}
function handleMouseDownRotate(event) {
rotateStart.set(event.clientX, event.clientY);
}
function handleMouseDownDolly(event) {
updateMouseParameters(event);
dollyStart.set(event.clientX, event.clientY);
}
function handleMouseDownPan(event) {
panStart.set(event.clientX, event.clientY);
}
function handleMouseMoveRotate(event) {
rotateEnd.set(event.clientX, event.clientY);
rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
const element = scope.domElement;
if (element) {
rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
}
rotateStart.copy(rotateEnd);
scope.update();
}
function handleMouseMoveDolly(event) {
dollyEnd.set(event.clientX, event.clientY);
dollyDelta.subVectors(dollyEnd, dollyStart);
if (dollyDelta.y > 0) {
dollyOut(getZoomScale());
} else if (dollyDelta.y < 0) {
dollyIn(getZoomScale());
}
dollyStart.copy(dollyEnd);
scope.update();
}
function handleMouseMovePan(event) {
panEnd.set(event.clientX, event.clientY);
panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
pan(panDelta.x, panDelta.y);
panStart.copy(panEnd);
scope.update();
}
function handleMouseWheel(event) {
updateMouseParameters(event);
if (event.deltaY < 0) {
dollyIn(getZoomScale());
} else if (event.deltaY > 0) {
dollyOut(getZoomScale());
}
scope.update();
}
function handleKeyDown(event) {
let needsUpdate = false;
switch (event.code) {
case scope.keys.UP:
pan(0, scope.keyPanSpeed);
needsUpdate = true;
break;
case scope.keys.BOTTOM:
pan(0, -scope.keyPanSpeed);
needsUpdate = true;
break;
case scope.keys.LEFT:
pan(scope.keyPanSpeed, 0);
needsUpdate = true;
break;
case scope.keys.RIGHT:
pan(-scope.keyPanSpeed, 0);
needsUpdate = true;
break;
}
if (needsUpdate) {
event.preventDefault();
scope.update();
}
}
function handleTouchStartRotate() {
if (pointers.length == 1) {
rotateStart.set(pointers[0].pageX, pointers[0].pageY);
} else {
const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
rotateStart.set(x, y);
}
}
function handleTouchStartPan() {
if (pointers.length == 1) {
panStart.set(pointers[0].pageX, pointers[0].pageY);
} else {
const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
panStart.set(x, y);
}
}
function handleTouchStartDolly() {
const dx = pointers[0].pageX - pointers[1].pageX;
const dy = pointers[0].pageY - pointers[1].pageY;
const distance = Math.sqrt(dx * dx + dy * dy);
dollyStart.set(0, distance);
}
function handleTouchStartDollyPan() {
if (scope.enableZoom)
handleTouchStartDolly();
if (scope.enablePan)
handleTouchStartPan();
}
function handleTouchStartDollyRotate() {
if (scope.enableZoom)
handleTouchStartDolly();
if (scope.enableRotate)
handleTouchStartRotate();
}
function handleTouchMoveRotate(event) {
if (pointers.length == 1) {
rotateEnd.set(event.pageX, event.pageY);
} else {
const position = getSecondPointerPosition(event);
const x = 0.5 * (event.pageX + position.x);
const y = 0.5 * (event.pageY + position.y);
rotateEnd.set(x, y);
}
rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
const element = scope.domElement;
if (element) {
rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
}
rotateStart.copy(rotateEnd);
}
function handleTouchMovePan(event) {
if (pointers.length == 1) {
panEnd.set(event.pageX, event.pageY);
} else {
const position = getSecondPointerPosition(event);
const x = 0.5 * (event.pageX + position.x);
const y = 0.5 * (event.pageY + position.y);
panEnd.set(x, y);
}
panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
pan(panDelta.x, panDelta.y);
panStart.copy(panEnd);
}
function handleTouchMoveDolly(event) {
const position = getSecondPointerPosition(event);
const dx = event.pageX - position.x;
const dy = event.pageY - position.y;
const distance = Math.sqrt(dx * dx + dy * dy);
dollyEnd.set(0, distance);
dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
dollyOut(dollyDelta.y);
dollyStart.copy(dollyEnd);
}
function handleTouchMoveDollyPan(event) {
if (scope.enableZoom)
handleTouchMoveDolly(event);
if (scope.enablePan)
handleTouchMovePan(event);
}
function handleTouchMoveDollyRotate(event) {
if (scope.enableZoom)
handleTouchMoveDolly(event);
if (scope.enableRotate)
handleTouchMoveRotate(event);
}
function onPointerDown(event) {
var _a, _b;
if (scope.enabled === false)
return;
if (pointers.length === 0) {
(_a = scope.domElement) == null ? void 0 : _a.ownerDocument.addEventListener("pointermove", onPointerMove);
(_b = scope.domElement) == null ? void 0 : _b.ownerDocument.addEventListener("pointerup", onPointerUp);
}
addPointer(event);
if (event.pointerType === "touch") {
onTouchStart(event);
} else {
onMouseDown(event);
}
}
function onPointerMove(event) {
if (scope.enabled === false)
return;
if (event.pointerType === "touch") {
onTouchMove(event);
} else {
onMouseMove(event);
}
}
function onPointerUp(event) {
var _a, _b, _c;
removePointer(event);
if (pointers.length === 0) {
(_a = scope.domElement) == null ? void 0 : _a.releasePointerCapture(event.pointerId);
(_b = scope.domElement) == null ? void 0 : _b.ownerDocument.removeEventListener("pointermove", onPointerMove);
(_c = scope.domElement) == null ? void 0 : _c.ownerDocument.removeEventListener("pointerup", onPointerUp);
}
scope.dispatchEvent(endEvent);
state = STATE.NONE;
}
function onMouseDown(event) {
let mouseAction;
switch (event.button) {
case 0:
mouseAction = scope.mouseButtons.LEFT;
break;
case 1:
mouseAction = scope.mouseButtons.MIDDLE;
break;
case 2:
mouseAction = scope.mouseButtons.RIGHT;
break;
default:
mouseAction = -1;
}
switch (mouseAction) {
case MOUSE.DOLLY:
if (scope.enableZoom === false)
return;
handleMouseDownDolly(event);
state = STATE.DOLLY;
break;
case MOUSE.ROTATE:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (scope.enablePan === false)
return;
handleMouseDownPan(event);
state = STATE.PAN;
} else {
if (scope.enableRotate === false)
return;
handleMouseDownRotate(event);
state = STATE.ROTATE;
}
break;
case MOUSE.PAN:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (scope.enableRotate === false)
return;
handleMouseDownRotate(event);
state = STATE.ROTATE;
} else {
if (scope.enablePan === false)
return;
handleMouseDownPan(event);
state = STATE.PAN;
}
break;
default:
state = STATE.NONE;
}
if (state !== STATE.NONE) {
scope.dispatchEvent(startEvent);
}
}
function onMouseMove(event) {
if (scope.enabled === false)
return;
switch (state) {
case STATE.ROTATE:
if (scope.enableRotate === false)
return;
handleMouseMoveRotate(event);
break;
case STATE.DOLLY:
if (scope.enableZoom === false)
return;
handleMouseMoveDolly(event);
break;
case STATE.PAN:
if (scope.enablePan === false)
return;
handleMouseMovePan(event);
break;
}
}
function onMouseWheel(event) {
if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE) {
return;
}
event.preventDefault();
scope.dispatchEvent(startEvent);
handleMouseWheel(event);
scope.dispatchEvent(endEvent);
}
function onKeyDown(event) {
if (scope.enabled === false || scope.enablePan === false)
return;
handleKeyDown(event);
}
function onTouchStart(event) {
trackPointer(event);
switch (pointers.length) {
case 1:
switch (scope.touches.ONE) {
case TOUCH.ROTATE:
if (scope.enableRotate === false)
return;
handleTouchStartRotate();
state = STATE.TOUCH_ROTATE;
break;
case TOUCH.PAN:
if (scope.enablePan === false)
return;
handleTouchStartPan();
state = STATE.TOUCH_PAN;
break;
default:
state = STATE.NONE;
}
break;
case 2:
switch (scope.touches.TWO) {
case TOUCH.DOLLY_PAN:
if (scope.enableZoom === false && scope.enablePan === false)
return;
handleTouchStartDollyPan();
state = STATE.TOUCH_DOLLY_PAN;
break;
case TOUCH.DOLLY_ROTATE:
if (scope.enableZoom === false && scope.enableRotate === false)
return;
handleTouchStartDollyRotate();
state = STATE.TOUCH_DOLLY_ROTATE;
break;
default:
state = STATE.NONE;
}
break;
default:
state = STATE.NONE;
}
if (state !== STATE.NONE) {
scope.dispatchEvent(startEvent);
}
}
function onTouchMove(event) {
trackPointer(event);
switch (state) {
case STATE.TOUCH_ROTATE:
if (scope.enableRotate === false)
return;
handleTouchMoveRotate(event);
scope.update();
break;
case STATE.TOUCH_PAN:
if (scope.enablePan === false)
return;
handleTouchMovePan(event);
scope.update();
break;
case STATE.TOUCH_DOLLY_PAN:
if (scope.enableZoom === false && scope.enablePan === false)
return;
handleTouchMoveDollyPan(event);
scope.update();
break;
case STATE.TOUCH_DOLLY_ROTATE:
if (scope.enableZoom === false && scope.enableRotate === false)
return;
handleTouchMoveDollyRotate(event);
scope.update();
break;
default:
state = STATE.NONE;
}
}
function onContextMenu(event) {
if (scope.enabled === false)
return;
event.preventDefault();
}
function addPointer(event) {
pointers.push(event);
}
function removePointer(event) {
delete pointerPositions[event.pointerId];
for (let i = 0; i < pointers.length; i++) {
if (pointers[i].pointerId == event.pointerId) {
pointers.splice(i, 1);
return;
}
}
}
function trackPointer(event) {
let position = pointerPositions[event.pointerId];
if (position === void 0) {
position = new Vector2();
pointerPositions[event.pointerId] = position;
}
position.set(event.pageX, event.pageY);
}
function getSecondPointerPosition(event) {
const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0];
return pointerPositions[pointer.pointerId];
}
this.dollyIn = (dollyScale = getZoomScale()) => {
dollyIn(dollyScale);
scope.update();
};
this.dollyOut = (dollyScale = getZoomScale()) => {
dollyOut(dollyScale);
scope.update();
};
this.getScale = () => {
return scale;
};
this.setScale = (newScale) => {
setScale(newScale);
scope.update();
};
this.getZoomScale = () => {
return getZoomScale();
};
if (domElement !== void 0)
this.connect(domElement);
this.update();
}
}
class MapControls extends OrbitControls {
constructor(object, domElement) {
super(object, domElement);
this.screenSpacePanning = false;
this.mouseButtons.LEFT = MOUSE.PAN;
this.mouseButtons.RIGHT = MOUSE.ROTATE;
this.touches.ONE = TOUCH.PAN;
this.touches.TWO = TOUCH.DOLLY_ROTATE;
}
}
export {
MapControls,
OrbitControls
};
//# sourceMappingURL=OrbitControls.js.map
File diff suppressed because one or more lines are too long
+104
View File
@@ -0,0 +1,104 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("./EventDispatcher.cjs");
const _euler = /* @__PURE__ */ new THREE.Euler(0, 0, 0, "YXZ");
const _vector = /* @__PURE__ */ new THREE.Vector3();
const _changeEvent = { type: "change" };
const _lockEvent = { type: "lock" };
const _unlockEvent = { type: "unlock" };
const _MOUSE_SENSITIVITY = 2e-3;
const _PI_2 = Math.PI / 2;
class PointerLockControls extends EventDispatcher.EventDispatcher {
constructor(camera, domElement) {
super();
__publicField(this, "camera");
__publicField(this, "domElement");
__publicField(this, "isLocked");
__publicField(this, "minPolarAngle");
__publicField(this, "maxPolarAngle");
__publicField(this, "pointerSpeed");
__publicField(this, "onMouseMove", (event) => {
if (!this.domElement || this.isLocked === false)
return;
_euler.setFromQuaternion(this.camera.quaternion);
_euler.y -= event.movementX * _MOUSE_SENSITIVITY * this.pointerSpeed;
_euler.x -= event.movementY * _MOUSE_SENSITIVITY * this.pointerSpeed;
_euler.x = Math.max(_PI_2 - this.maxPolarAngle, Math.min(_PI_2 - this.minPolarAngle, _euler.x));
this.camera.quaternion.setFromEuler(_euler);
this.dispatchEvent(_changeEvent);
});
__publicField(this, "onPointerlockChange", () => {
if (!this.domElement)
return;
if (this.domElement.ownerDocument.pointerLockElement === this.domElement) {
this.dispatchEvent(_lockEvent);
this.isLocked = true;
} else {
this.dispatchEvent(_unlockEvent);
this.isLocked = false;
}
});
__publicField(this, "onPointerlockError", () => {
console.error("THREE.PointerLockControls: Unable to use Pointer Lock API");
});
__publicField(this, "connect", (domElement) => {
this.domElement = domElement || this.domElement;
if (!this.domElement)
return;
this.domElement.ownerDocument.addEventListener("mousemove", this.onMouseMove);
this.domElement.ownerDocument.addEventListener("pointerlockchange", this.onPointerlockChange);
this.domElement.ownerDocument.addEventListener("pointerlockerror", this.onPointerlockError);
});
__publicField(this, "disconnect", () => {
if (!this.domElement)
return;
this.domElement.ownerDocument.removeEventListener("mousemove", this.onMouseMove);
this.domElement.ownerDocument.removeEventListener("pointerlockchange", this.onPointerlockChange);
this.domElement.ownerDocument.removeEventListener("pointerlockerror", this.onPointerlockError);
});
__publicField(this, "dispose", () => {
this.disconnect();
});
__publicField(this, "getObject", () => {
return this.camera;
});
__publicField(this, "direction", new THREE.Vector3(0, 0, -1));
__publicField(this, "getDirection", (v) => {
return v.copy(this.direction).applyQuaternion(this.camera.quaternion);
});
__publicField(this, "moveForward", (distance) => {
_vector.setFromMatrixColumn(this.camera.matrix, 0);
_vector.crossVectors(this.camera.up, _vector);
this.camera.position.addScaledVector(_vector, distance);
});
__publicField(this, "moveRight", (distance) => {
_vector.setFromMatrixColumn(this.camera.matrix, 0);
this.camera.position.addScaledVector(_vector, distance);
});
__publicField(this, "lock", () => {
if (this.domElement)
this.domElement.requestPointerLock();
});
__publicField(this, "unlock", () => {
if (this.domElement)
this.domElement.ownerDocument.exitPointerLock();
});
this.camera = camera;
this.domElement = domElement;
this.isLocked = false;
this.minPolarAngle = 0;
this.maxPolarAngle = Math.PI;
this.pointerSpeed = 1;
if (domElement)
this.connect(domElement);
}
}
exports.PointerLockControls = PointerLockControls;
//# sourceMappingURL=PointerLockControls.cjs.map
File diff suppressed because one or more lines are too long
+39
View File
@@ -0,0 +1,39 @@
import { Camera, Vector3 } from 'three';
import { EventDispatcher } from './EventDispatcher';
export interface PointerLockControlsEventMap {
/**
* Fires when the user moves the mouse.
*/
change: {};
/**
* Fires when the pointer lock status is "locked" (in other words: the mouse is captured).
*/
lock: {};
/**
* Fires when the pointer lock status is "unlocked" (in other words: the mouse is not captured anymore).
*/
unlock: {};
}
declare class PointerLockControls extends EventDispatcher<PointerLockControlsEventMap> {
camera: Camera;
domElement?: HTMLElement;
isLocked: boolean;
minPolarAngle: number;
maxPolarAngle: number;
pointerSpeed: number;
constructor(camera: Camera, domElement?: HTMLElement);
private onMouseMove;
private onPointerlockChange;
private onPointerlockError;
connect: (domElement: HTMLElement) => void;
disconnect: () => void;
dispose: () => void;
getObject: () => Camera;
private direction;
getDirection: (v: Vector3) => Vector3;
moveForward: (distance: number) => void;
moveRight: (distance: number) => void;
lock: () => void;
unlock: () => void;
}
export { PointerLockControls };
+104
View File
@@ -0,0 +1,104 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { Vector3, Euler } from "three";
import { EventDispatcher } from "./EventDispatcher.js";
const _euler = /* @__PURE__ */ new Euler(0, 0, 0, "YXZ");
const _vector = /* @__PURE__ */ new Vector3();
const _changeEvent = { type: "change" };
const _lockEvent = { type: "lock" };
const _unlockEvent = { type: "unlock" };
const _MOUSE_SENSITIVITY = 2e-3;
const _PI_2 = Math.PI / 2;
class PointerLockControls extends EventDispatcher {
constructor(camera, domElement) {
super();
__publicField(this, "camera");
__publicField(this, "domElement");
__publicField(this, "isLocked");
__publicField(this, "minPolarAngle");
__publicField(this, "maxPolarAngle");
__publicField(this, "pointerSpeed");
__publicField(this, "onMouseMove", (event) => {
if (!this.domElement || this.isLocked === false)
return;
_euler.setFromQuaternion(this.camera.quaternion);
_euler.y -= event.movementX * _MOUSE_SENSITIVITY * this.pointerSpeed;
_euler.x -= event.movementY * _MOUSE_SENSITIVITY * this.pointerSpeed;
_euler.x = Math.max(_PI_2 - this.maxPolarAngle, Math.min(_PI_2 - this.minPolarAngle, _euler.x));
this.camera.quaternion.setFromEuler(_euler);
this.dispatchEvent(_changeEvent);
});
__publicField(this, "onPointerlockChange", () => {
if (!this.domElement)
return;
if (this.domElement.ownerDocument.pointerLockElement === this.domElement) {
this.dispatchEvent(_lockEvent);
this.isLocked = true;
} else {
this.dispatchEvent(_unlockEvent);
this.isLocked = false;
}
});
__publicField(this, "onPointerlockError", () => {
console.error("THREE.PointerLockControls: Unable to use Pointer Lock API");
});
__publicField(this, "connect", (domElement) => {
this.domElement = domElement || this.domElement;
if (!this.domElement)
return;
this.domElement.ownerDocument.addEventListener("mousemove", this.onMouseMove);
this.domElement.ownerDocument.addEventListener("pointerlockchange", this.onPointerlockChange);
this.domElement.ownerDocument.addEventListener("pointerlockerror", this.onPointerlockError);
});
__publicField(this, "disconnect", () => {
if (!this.domElement)
return;
this.domElement.ownerDocument.removeEventListener("mousemove", this.onMouseMove);
this.domElement.ownerDocument.removeEventListener("pointerlockchange", this.onPointerlockChange);
this.domElement.ownerDocument.removeEventListener("pointerlockerror", this.onPointerlockError);
});
__publicField(this, "dispose", () => {
this.disconnect();
});
__publicField(this, "getObject", () => {
return this.camera;
});
__publicField(this, "direction", new Vector3(0, 0, -1));
__publicField(this, "getDirection", (v) => {
return v.copy(this.direction).applyQuaternion(this.camera.quaternion);
});
__publicField(this, "moveForward", (distance) => {
_vector.setFromMatrixColumn(this.camera.matrix, 0);
_vector.crossVectors(this.camera.up, _vector);
this.camera.position.addScaledVector(_vector, distance);
});
__publicField(this, "moveRight", (distance) => {
_vector.setFromMatrixColumn(this.camera.matrix, 0);
this.camera.position.addScaledVector(_vector, distance);
});
__publicField(this, "lock", () => {
if (this.domElement)
this.domElement.requestPointerLock();
});
__publicField(this, "unlock", () => {
if (this.domElement)
this.domElement.ownerDocument.exitPointerLock();
});
this.camera = camera;
this.domElement = domElement;
this.isLocked = false;
this.minPolarAngle = 0;
this.maxPolarAngle = Math.PI;
this.pointerSpeed = 1;
if (domElement)
this.connect(domElement);
}
}
export {
PointerLockControls
};
//# sourceMappingURL=PointerLockControls.js.map
File diff suppressed because one or more lines are too long
+14
View File
@@ -0,0 +1,14 @@
export interface StandardControlsEventMap {
/**
* Fires when the camera has been transformed by the controls.
*/
change: {};
/**
* Fires when an interaction was initiated.
*/
start: {};
/**
* Fires when an interaction has finished.
*/
end: {};
}
+502
View File
@@ -0,0 +1,502 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("./EventDispatcher.cjs");
class TrackballControls extends EventDispatcher.EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "enabled", true);
__publicField(this, "screen", { left: 0, top: 0, width: 0, height: 0 });
__publicField(this, "rotateSpeed", 1);
__publicField(this, "zoomSpeed", 1.2);
__publicField(this, "panSpeed", 0.3);
__publicField(this, "noRotate", false);
__publicField(this, "noZoom", false);
__publicField(this, "noPan", false);
__publicField(this, "staticMoving", false);
__publicField(this, "dynamicDampingFactor", 0.2);
__publicField(this, "minDistance", 0);
__publicField(this, "maxDistance", Infinity);
__publicField(this, "keys", [
"KeyA",
"KeyS",
"KeyD"
/*D*/
]);
__publicField(this, "mouseButtons", {
LEFT: THREE.MOUSE.ROTATE,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.PAN
});
__publicField(this, "object");
__publicField(this, "domElement");
__publicField(this, "cursorZoom", false);
__publicField(this, "target", new THREE.Vector3());
__publicField(this, "mousePosition", new THREE.Vector2());
// internals
__publicField(this, "STATE", {
NONE: -1,
ROTATE: 0,
ZOOM: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_ZOOM_PAN: 4
});
__publicField(this, "EPS", 1e-6);
__publicField(this, "lastZoom", 1);
__publicField(this, "lastPosition", new THREE.Vector3());
__publicField(this, "cursorVector", new THREE.Vector3());
__publicField(this, "targetVector", new THREE.Vector3());
__publicField(this, "_state", this.STATE.NONE);
__publicField(this, "_keyState", this.STATE.NONE);
__publicField(this, "_eye", new THREE.Vector3());
__publicField(this, "_movePrev", new THREE.Vector2());
__publicField(this, "_moveCurr", new THREE.Vector2());
__publicField(this, "_lastAxis", new THREE.Vector3());
__publicField(this, "_lastAngle", 0);
__publicField(this, "_zoomStart", new THREE.Vector2());
__publicField(this, "_zoomEnd", new THREE.Vector2());
__publicField(this, "_touchZoomDistanceStart", 0);
__publicField(this, "_touchZoomDistanceEnd", 0);
__publicField(this, "_panStart", new THREE.Vector2());
__publicField(this, "_panEnd", new THREE.Vector2());
__publicField(this, "target0");
__publicField(this, "position0");
__publicField(this, "up0");
__publicField(this, "zoom0");
// events
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "startEvent", { type: "start" });
__publicField(this, "endEvent", { type: "end" });
__publicField(this, "onScreenVector", new THREE.Vector2());
__publicField(this, "getMouseOnScreen", (pageX, pageY) => {
this.onScreenVector.set(
(pageX - this.screen.left) / this.screen.width,
(pageY - this.screen.top) / this.screen.height
);
return this.onScreenVector;
});
__publicField(this, "onCircleVector", new THREE.Vector2());
__publicField(this, "getMouseOnCircle", (pageX, pageY) => {
this.onCircleVector.set(
(pageX - this.screen.width * 0.5 - this.screen.left) / (this.screen.width * 0.5),
(this.screen.height + 2 * (this.screen.top - pageY)) / this.screen.width
// screen.width intentional
);
return this.onCircleVector;
});
__publicField(this, "axis", new THREE.Vector3());
__publicField(this, "quaternion", new THREE.Quaternion());
__publicField(this, "eyeDirection", new THREE.Vector3());
__publicField(this, "objectUpDirection", new THREE.Vector3());
__publicField(this, "objectSidewaysDirection", new THREE.Vector3());
__publicField(this, "moveDirection", new THREE.Vector3());
__publicField(this, "angle", 0);
__publicField(this, "rotateCamera", () => {
this.moveDirection.set(this._moveCurr.x - this._movePrev.x, this._moveCurr.y - this._movePrev.y, 0);
this.angle = this.moveDirection.length();
if (this.angle) {
this._eye.copy(this.object.position).sub(this.target);
this.eyeDirection.copy(this._eye).normalize();
this.objectUpDirection.copy(this.object.up).normalize();
this.objectSidewaysDirection.crossVectors(this.objectUpDirection, this.eyeDirection).normalize();
this.objectUpDirection.setLength(this._moveCurr.y - this._movePrev.y);
this.objectSidewaysDirection.setLength(this._moveCurr.x - this._movePrev.x);
this.moveDirection.copy(this.objectUpDirection.add(this.objectSidewaysDirection));
this.axis.crossVectors(this.moveDirection, this._eye).normalize();
this.angle *= this.rotateSpeed;
this.quaternion.setFromAxisAngle(this.axis, this.angle);
this._eye.applyQuaternion(this.quaternion);
this.object.up.applyQuaternion(this.quaternion);
this._lastAxis.copy(this.axis);
this._lastAngle = this.angle;
} else if (!this.staticMoving && this._lastAngle) {
this._lastAngle *= Math.sqrt(1 - this.dynamicDampingFactor);
this._eye.copy(this.object.position).sub(this.target);
this.quaternion.setFromAxisAngle(this._lastAxis, this._lastAngle);
this._eye.applyQuaternion(this.quaternion);
this.object.up.applyQuaternion(this.quaternion);
}
this._movePrev.copy(this._moveCurr);
});
__publicField(this, "zoomCamera", () => {
let factor;
if (this._state === this.STATE.TOUCH_ZOOM_PAN) {
factor = this._touchZoomDistanceStart / this._touchZoomDistanceEnd;
this._touchZoomDistanceStart = this._touchZoomDistanceEnd;
if (this.object.isPerspectiveCamera) {
this._eye.multiplyScalar(factor);
} else if (this.object.isOrthographicCamera) {
this.object.zoom /= factor;
this.object.updateProjectionMatrix();
} else {
console.warn("THREE.TrackballControls: Unsupported camera type");
}
} else {
factor = 1 + (this._zoomEnd.y - this._zoomStart.y) * this.zoomSpeed;
if (Math.abs(factor - 1) > this.EPS && factor > 0) {
if (this.object.isPerspectiveCamera) {
if (factor > 1 && this._eye.length() >= this.maxDistance - this.EPS) {
factor = 1;
}
this._eye.multiplyScalar(factor);
} else if (this.object.isOrthographicCamera) {
if (factor > 1 && this.object.zoom < this.maxDistance * this.maxDistance) {
factor = 1;
}
this.object.zoom /= factor;
} else {
console.warn("THREE.TrackballControls: Unsupported camera type");
}
}
if (this.staticMoving) {
this._zoomStart.copy(this._zoomEnd);
} else {
this._zoomStart.y += (this._zoomEnd.y - this._zoomStart.y) * this.dynamicDampingFactor;
}
if (this.cursorZoom) {
this.targetVector.copy(this.target).project(this.object);
let worldPos = this.cursorVector.set(this.mousePosition.x, this.mousePosition.y, this.targetVector.z).unproject(this.object);
this.target.lerpVectors(worldPos, this.target, factor);
}
if (this.object.isOrthographicCamera) {
this.object.updateProjectionMatrix();
}
}
});
__publicField(this, "mouseChange", new THREE.Vector2());
__publicField(this, "objectUp", new THREE.Vector3());
__publicField(this, "pan", new THREE.Vector3());
__publicField(this, "panCamera", () => {
if (!this.domElement)
return;
this.mouseChange.copy(this._panEnd).sub(this._panStart);
if (this.mouseChange.lengthSq() > this.EPS) {
if (this.object.isOrthographicCamera) {
const orthoObject = this.object;
const scale_x = (orthoObject.right - orthoObject.left) / this.object.zoom;
const scale_y = (orthoObject.top - orthoObject.bottom) / this.object.zoom;
this.mouseChange.x *= scale_x;
this.mouseChange.y *= scale_y;
} else {
this.mouseChange.multiplyScalar(this._eye.length() * this.panSpeed);
}
this.pan.copy(this._eye).cross(this.object.up).setLength(this.mouseChange.x);
this.pan.add(this.objectUp.copy(this.object.up).setLength(this.mouseChange.y));
this.object.position.add(this.pan);
this.target.add(this.pan);
if (this.staticMoving) {
this._panStart.copy(this._panEnd);
} else {
this._panStart.add(
this.mouseChange.subVectors(this._panEnd, this._panStart).multiplyScalar(this.dynamicDampingFactor)
);
}
}
});
__publicField(this, "checkDistances", () => {
if (!this.noZoom || !this.noPan) {
if (this._eye.lengthSq() > this.maxDistance * this.maxDistance) {
this.object.position.addVectors(this.target, this._eye.setLength(this.maxDistance));
this._zoomStart.copy(this._zoomEnd);
}
if (this._eye.lengthSq() < this.minDistance * this.minDistance) {
this.object.position.addVectors(this.target, this._eye.setLength(this.minDistance));
this._zoomStart.copy(this._zoomEnd);
}
}
});
__publicField(this, "handleResize", () => {
if (!this.domElement)
return;
const box = this.domElement.getBoundingClientRect();
const d = this.domElement.ownerDocument.documentElement;
this.screen.left = box.left + window.pageXOffset - d.clientLeft;
this.screen.top = box.top + window.pageYOffset - d.clientTop;
this.screen.width = box.width;
this.screen.height = box.height;
});
__publicField(this, "update", () => {
this._eye.subVectors(this.object.position, this.target);
if (!this.noRotate) {
this.rotateCamera();
}
if (!this.noZoom) {
this.zoomCamera();
}
if (!this.noPan) {
this.panCamera();
}
this.object.position.addVectors(this.target, this._eye);
if (this.object.isPerspectiveCamera) {
this.checkDistances();
this.object.lookAt(this.target);
if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS) {
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
}
} else if (this.object.isOrthographicCamera) {
this.object.lookAt(this.target);
if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS || this.lastZoom !== this.object.zoom) {
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
this.lastZoom = this.object.zoom;
}
} else {
console.warn("THREE.TrackballControls: Unsupported camera type");
}
});
__publicField(this, "reset", () => {
this._state = this.STATE.NONE;
this._keyState = this.STATE.NONE;
this.target.copy(this.target0);
this.object.position.copy(this.position0);
this.object.up.copy(this.up0);
this.object.zoom = this.zoom0;
this.object.updateProjectionMatrix();
this._eye.subVectors(this.object.position, this.target);
this.object.lookAt(this.target);
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
this.lastZoom = this.object.zoom;
});
__publicField(this, "keydown", (event) => {
if (this.enabled === false)
return;
window.removeEventListener("keydown", this.keydown);
if (this._keyState !== this.STATE.NONE) {
return;
} else if (event.code === this.keys[this.STATE.ROTATE] && !this.noRotate) {
this._keyState = this.STATE.ROTATE;
} else if (event.code === this.keys[this.STATE.ZOOM] && !this.noZoom) {
this._keyState = this.STATE.ZOOM;
} else if (event.code === this.keys[this.STATE.PAN] && !this.noPan) {
this._keyState = this.STATE.PAN;
}
});
__publicField(this, "onPointerDown", (event) => {
if (this.enabled === false)
return;
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseDown(event);
break;
}
});
__publicField(this, "onPointerMove", (event) => {
if (this.enabled === false)
return;
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseMove(event);
break;
}
});
__publicField(this, "onPointerUp", (event) => {
if (this.enabled === false)
return;
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseUp();
break;
}
});
__publicField(this, "keyup", () => {
if (this.enabled === false)
return;
this._keyState = this.STATE.NONE;
window.addEventListener("keydown", this.keydown);
});
__publicField(this, "onMouseDown", (event) => {
if (!this.domElement)
return;
if (this._state === this.STATE.NONE) {
switch (event.button) {
case this.mouseButtons.LEFT:
this._state = this.STATE.ROTATE;
break;
case this.mouseButtons.MIDDLE:
this._state = this.STATE.ZOOM;
break;
case this.mouseButtons.RIGHT:
this._state = this.STATE.PAN;
break;
}
}
const state = this._keyState !== this.STATE.NONE ? this._keyState : this._state;
if (state === this.STATE.ROTATE && !this.noRotate) {
this._moveCurr.copy(this.getMouseOnCircle(event.pageX, event.pageY));
this._movePrev.copy(this._moveCurr);
} else if (state === this.STATE.ZOOM && !this.noZoom) {
this._zoomStart.copy(this.getMouseOnScreen(event.pageX, event.pageY));
this._zoomEnd.copy(this._zoomStart);
} else if (state === this.STATE.PAN && !this.noPan) {
this._panStart.copy(this.getMouseOnScreen(event.pageX, event.pageY));
this._panEnd.copy(this._panStart);
}
this.domElement.ownerDocument.addEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.addEventListener("pointerup", this.onPointerUp);
this.dispatchEvent(this.startEvent);
});
__publicField(this, "onMouseMove", (event) => {
if (this.enabled === false)
return;
const state = this._keyState !== this.STATE.NONE ? this._keyState : this._state;
if (state === this.STATE.ROTATE && !this.noRotate) {
this._movePrev.copy(this._moveCurr);
this._moveCurr.copy(this.getMouseOnCircle(event.pageX, event.pageY));
} else if (state === this.STATE.ZOOM && !this.noZoom) {
this._zoomEnd.copy(this.getMouseOnScreen(event.pageX, event.pageY));
} else if (state === this.STATE.PAN && !this.noPan) {
this._panEnd.copy(this.getMouseOnScreen(event.pageX, event.pageY));
}
});
__publicField(this, "onMouseUp", () => {
if (!this.domElement)
return;
if (this.enabled === false)
return;
this._state = this.STATE.NONE;
this.domElement.ownerDocument.removeEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.removeEventListener("pointerup", this.onPointerUp);
this.dispatchEvent(this.endEvent);
});
__publicField(this, "mousewheel", (event) => {
if (this.enabled === false)
return;
if (this.noZoom === true)
return;
event.preventDefault();
switch (event.deltaMode) {
case 2:
this._zoomStart.y -= event.deltaY * 0.025;
break;
case 1:
this._zoomStart.y -= event.deltaY * 0.01;
break;
default:
this._zoomStart.y -= event.deltaY * 25e-5;
break;
}
this.mousePosition.x = event.offsetX / this.screen.width * 2 - 1;
this.mousePosition.y = -(event.offsetY / this.screen.height) * 2 + 1;
this.dispatchEvent(this.startEvent);
this.dispatchEvent(this.endEvent);
});
__publicField(this, "touchstart", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (event.touches.length) {
case 1:
this._state = this.STATE.TOUCH_ROTATE;
this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
this._movePrev.copy(this._moveCurr);
break;
default:
this._state = this.STATE.TOUCH_ZOOM_PAN;
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
this._touchZoomDistanceEnd = this._touchZoomDistanceStart = Math.sqrt(dx * dx + dy * dy);
const x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
const y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
this._panStart.copy(this.getMouseOnScreen(x, y));
this._panEnd.copy(this._panStart);
break;
}
this.dispatchEvent(this.startEvent);
});
__publicField(this, "touchmove", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (event.touches.length) {
case 1:
this._movePrev.copy(this._moveCurr);
this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
break;
default:
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
this._touchZoomDistanceEnd = Math.sqrt(dx * dx + dy * dy);
const x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
const y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
this._panEnd.copy(this.getMouseOnScreen(x, y));
break;
}
});
__publicField(this, "touchend", (event) => {
if (this.enabled === false)
return;
switch (event.touches.length) {
case 0:
this._state = this.STATE.NONE;
break;
case 1:
this._state = this.STATE.TOUCH_ROTATE;
this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
this._movePrev.copy(this._moveCurr);
break;
}
this.dispatchEvent(this.endEvent);
});
__publicField(this, "contextmenu", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
});
// https://github.com/mrdoob/three.js/issues/20575
__publicField(this, "connect", (domElement) => {
if (domElement === document) {
console.error(
'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.'
);
}
this.domElement = domElement;
this.domElement.addEventListener("contextmenu", this.contextmenu);
this.domElement.addEventListener("pointerdown", this.onPointerDown);
this.domElement.addEventListener("wheel", this.mousewheel);
this.domElement.addEventListener("touchstart", this.touchstart);
this.domElement.addEventListener("touchend", this.touchend);
this.domElement.addEventListener("touchmove", this.touchmove);
this.domElement.ownerDocument.addEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.addEventListener("pointerup", this.onPointerUp);
window.addEventListener("keydown", this.keydown);
window.addEventListener("keyup", this.keyup);
this.handleResize();
});
__publicField(this, "dispose", () => {
if (!this.domElement)
return;
this.domElement.removeEventListener("contextmenu", this.contextmenu);
this.domElement.removeEventListener("pointerdown", this.onPointerDown);
this.domElement.removeEventListener("wheel", this.mousewheel);
this.domElement.removeEventListener("touchstart", this.touchstart);
this.domElement.removeEventListener("touchend", this.touchend);
this.domElement.removeEventListener("touchmove", this.touchmove);
this.domElement.ownerDocument.removeEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.removeEventListener("pointerup", this.onPointerUp);
window.removeEventListener("keydown", this.keydown);
window.removeEventListener("keyup", this.keyup);
});
this.object = object;
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.up0 = this.object.up.clone();
this.zoom0 = this.object.zoom;
if (domElement !== void 0)
this.connect(domElement);
this.update();
}
}
exports.TrackballControls = TrackballControls;
//# sourceMappingURL=TrackballControls.cjs.map
File diff suppressed because one or more lines are too long
+97
View File
@@ -0,0 +1,97 @@
import { MOUSE, Vector3, PerspectiveCamera, OrthographicCamera } from 'three';
import { EventDispatcher } from './EventDispatcher';
import { StandardControlsEventMap } from './StandardControlsEventMap';
declare class TrackballControls extends EventDispatcher<StandardControlsEventMap> {
enabled: boolean;
screen: {
left: number;
top: number;
width: number;
height: number;
};
rotateSpeed: number;
zoomSpeed: number;
panSpeed: number;
noRotate: boolean;
noZoom: boolean;
noPan: boolean;
staticMoving: boolean;
dynamicDampingFactor: number;
minDistance: number;
maxDistance: number;
keys: [string, string, string];
mouseButtons: {
LEFT: MOUSE;
MIDDLE: MOUSE;
RIGHT: MOUSE;
};
object: PerspectiveCamera | OrthographicCamera;
domElement: HTMLElement | undefined;
cursorZoom: boolean;
readonly target: Vector3;
private mousePosition;
private STATE;
private EPS;
private lastZoom;
private lastPosition;
private cursorVector;
private targetVector;
private _state;
private _keyState;
private _eye;
private _movePrev;
private _moveCurr;
private _lastAxis;
private _lastAngle;
private _zoomStart;
private _zoomEnd;
private _touchZoomDistanceStart;
private _touchZoomDistanceEnd;
private _panStart;
private _panEnd;
private target0;
private position0;
private up0;
private zoom0;
private changeEvent;
private startEvent;
private endEvent;
constructor(object: PerspectiveCamera | OrthographicCamera, domElement?: HTMLElement);
private onScreenVector;
private getMouseOnScreen;
private onCircleVector;
private getMouseOnCircle;
private axis;
private quaternion;
private eyeDirection;
private objectUpDirection;
private objectSidewaysDirection;
private moveDirection;
private angle;
private rotateCamera;
private zoomCamera;
private mouseChange;
private objectUp;
private pan;
private panCamera;
private checkDistances;
handleResize: () => void;
update: () => void;
reset: () => void;
private keydown;
private onPointerDown;
private onPointerMove;
private onPointerUp;
private keyup;
private onMouseDown;
private onMouseMove;
private onMouseUp;
private mousewheel;
private touchstart;
private touchmove;
private touchend;
private contextmenu;
connect: (domElement: HTMLElement) => void;
dispose: () => void;
}
export { TrackballControls };
+502
View File
@@ -0,0 +1,502 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { MOUSE, Vector3, Vector2, Quaternion } from "three";
import { EventDispatcher } from "./EventDispatcher.js";
class TrackballControls extends EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "enabled", true);
__publicField(this, "screen", { left: 0, top: 0, width: 0, height: 0 });
__publicField(this, "rotateSpeed", 1);
__publicField(this, "zoomSpeed", 1.2);
__publicField(this, "panSpeed", 0.3);
__publicField(this, "noRotate", false);
__publicField(this, "noZoom", false);
__publicField(this, "noPan", false);
__publicField(this, "staticMoving", false);
__publicField(this, "dynamicDampingFactor", 0.2);
__publicField(this, "minDistance", 0);
__publicField(this, "maxDistance", Infinity);
__publicField(this, "keys", [
"KeyA",
"KeyS",
"KeyD"
/*D*/
]);
__publicField(this, "mouseButtons", {
LEFT: MOUSE.ROTATE,
MIDDLE: MOUSE.DOLLY,
RIGHT: MOUSE.PAN
});
__publicField(this, "object");
__publicField(this, "domElement");
__publicField(this, "cursorZoom", false);
__publicField(this, "target", new Vector3());
__publicField(this, "mousePosition", new Vector2());
// internals
__publicField(this, "STATE", {
NONE: -1,
ROTATE: 0,
ZOOM: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_ZOOM_PAN: 4
});
__publicField(this, "EPS", 1e-6);
__publicField(this, "lastZoom", 1);
__publicField(this, "lastPosition", new Vector3());
__publicField(this, "cursorVector", new Vector3());
__publicField(this, "targetVector", new Vector3());
__publicField(this, "_state", this.STATE.NONE);
__publicField(this, "_keyState", this.STATE.NONE);
__publicField(this, "_eye", new Vector3());
__publicField(this, "_movePrev", new Vector2());
__publicField(this, "_moveCurr", new Vector2());
__publicField(this, "_lastAxis", new Vector3());
__publicField(this, "_lastAngle", 0);
__publicField(this, "_zoomStart", new Vector2());
__publicField(this, "_zoomEnd", new Vector2());
__publicField(this, "_touchZoomDistanceStart", 0);
__publicField(this, "_touchZoomDistanceEnd", 0);
__publicField(this, "_panStart", new Vector2());
__publicField(this, "_panEnd", new Vector2());
__publicField(this, "target0");
__publicField(this, "position0");
__publicField(this, "up0");
__publicField(this, "zoom0");
// events
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "startEvent", { type: "start" });
__publicField(this, "endEvent", { type: "end" });
__publicField(this, "onScreenVector", new Vector2());
__publicField(this, "getMouseOnScreen", (pageX, pageY) => {
this.onScreenVector.set(
(pageX - this.screen.left) / this.screen.width,
(pageY - this.screen.top) / this.screen.height
);
return this.onScreenVector;
});
__publicField(this, "onCircleVector", new Vector2());
__publicField(this, "getMouseOnCircle", (pageX, pageY) => {
this.onCircleVector.set(
(pageX - this.screen.width * 0.5 - this.screen.left) / (this.screen.width * 0.5),
(this.screen.height + 2 * (this.screen.top - pageY)) / this.screen.width
// screen.width intentional
);
return this.onCircleVector;
});
__publicField(this, "axis", new Vector3());
__publicField(this, "quaternion", new Quaternion());
__publicField(this, "eyeDirection", new Vector3());
__publicField(this, "objectUpDirection", new Vector3());
__publicField(this, "objectSidewaysDirection", new Vector3());
__publicField(this, "moveDirection", new Vector3());
__publicField(this, "angle", 0);
__publicField(this, "rotateCamera", () => {
this.moveDirection.set(this._moveCurr.x - this._movePrev.x, this._moveCurr.y - this._movePrev.y, 0);
this.angle = this.moveDirection.length();
if (this.angle) {
this._eye.copy(this.object.position).sub(this.target);
this.eyeDirection.copy(this._eye).normalize();
this.objectUpDirection.copy(this.object.up).normalize();
this.objectSidewaysDirection.crossVectors(this.objectUpDirection, this.eyeDirection).normalize();
this.objectUpDirection.setLength(this._moveCurr.y - this._movePrev.y);
this.objectSidewaysDirection.setLength(this._moveCurr.x - this._movePrev.x);
this.moveDirection.copy(this.objectUpDirection.add(this.objectSidewaysDirection));
this.axis.crossVectors(this.moveDirection, this._eye).normalize();
this.angle *= this.rotateSpeed;
this.quaternion.setFromAxisAngle(this.axis, this.angle);
this._eye.applyQuaternion(this.quaternion);
this.object.up.applyQuaternion(this.quaternion);
this._lastAxis.copy(this.axis);
this._lastAngle = this.angle;
} else if (!this.staticMoving && this._lastAngle) {
this._lastAngle *= Math.sqrt(1 - this.dynamicDampingFactor);
this._eye.copy(this.object.position).sub(this.target);
this.quaternion.setFromAxisAngle(this._lastAxis, this._lastAngle);
this._eye.applyQuaternion(this.quaternion);
this.object.up.applyQuaternion(this.quaternion);
}
this._movePrev.copy(this._moveCurr);
});
__publicField(this, "zoomCamera", () => {
let factor;
if (this._state === this.STATE.TOUCH_ZOOM_PAN) {
factor = this._touchZoomDistanceStart / this._touchZoomDistanceEnd;
this._touchZoomDistanceStart = this._touchZoomDistanceEnd;
if (this.object.isPerspectiveCamera) {
this._eye.multiplyScalar(factor);
} else if (this.object.isOrthographicCamera) {
this.object.zoom /= factor;
this.object.updateProjectionMatrix();
} else {
console.warn("THREE.TrackballControls: Unsupported camera type");
}
} else {
factor = 1 + (this._zoomEnd.y - this._zoomStart.y) * this.zoomSpeed;
if (Math.abs(factor - 1) > this.EPS && factor > 0) {
if (this.object.isPerspectiveCamera) {
if (factor > 1 && this._eye.length() >= this.maxDistance - this.EPS) {
factor = 1;
}
this._eye.multiplyScalar(factor);
} else if (this.object.isOrthographicCamera) {
if (factor > 1 && this.object.zoom < this.maxDistance * this.maxDistance) {
factor = 1;
}
this.object.zoom /= factor;
} else {
console.warn("THREE.TrackballControls: Unsupported camera type");
}
}
if (this.staticMoving) {
this._zoomStart.copy(this._zoomEnd);
} else {
this._zoomStart.y += (this._zoomEnd.y - this._zoomStart.y) * this.dynamicDampingFactor;
}
if (this.cursorZoom) {
this.targetVector.copy(this.target).project(this.object);
let worldPos = this.cursorVector.set(this.mousePosition.x, this.mousePosition.y, this.targetVector.z).unproject(this.object);
this.target.lerpVectors(worldPos, this.target, factor);
}
if (this.object.isOrthographicCamera) {
this.object.updateProjectionMatrix();
}
}
});
__publicField(this, "mouseChange", new Vector2());
__publicField(this, "objectUp", new Vector3());
__publicField(this, "pan", new Vector3());
__publicField(this, "panCamera", () => {
if (!this.domElement)
return;
this.mouseChange.copy(this._panEnd).sub(this._panStart);
if (this.mouseChange.lengthSq() > this.EPS) {
if (this.object.isOrthographicCamera) {
const orthoObject = this.object;
const scale_x = (orthoObject.right - orthoObject.left) / this.object.zoom;
const scale_y = (orthoObject.top - orthoObject.bottom) / this.object.zoom;
this.mouseChange.x *= scale_x;
this.mouseChange.y *= scale_y;
} else {
this.mouseChange.multiplyScalar(this._eye.length() * this.panSpeed);
}
this.pan.copy(this._eye).cross(this.object.up).setLength(this.mouseChange.x);
this.pan.add(this.objectUp.copy(this.object.up).setLength(this.mouseChange.y));
this.object.position.add(this.pan);
this.target.add(this.pan);
if (this.staticMoving) {
this._panStart.copy(this._panEnd);
} else {
this._panStart.add(
this.mouseChange.subVectors(this._panEnd, this._panStart).multiplyScalar(this.dynamicDampingFactor)
);
}
}
});
__publicField(this, "checkDistances", () => {
if (!this.noZoom || !this.noPan) {
if (this._eye.lengthSq() > this.maxDistance * this.maxDistance) {
this.object.position.addVectors(this.target, this._eye.setLength(this.maxDistance));
this._zoomStart.copy(this._zoomEnd);
}
if (this._eye.lengthSq() < this.minDistance * this.minDistance) {
this.object.position.addVectors(this.target, this._eye.setLength(this.minDistance));
this._zoomStart.copy(this._zoomEnd);
}
}
});
__publicField(this, "handleResize", () => {
if (!this.domElement)
return;
const box = this.domElement.getBoundingClientRect();
const d = this.domElement.ownerDocument.documentElement;
this.screen.left = box.left + window.pageXOffset - d.clientLeft;
this.screen.top = box.top + window.pageYOffset - d.clientTop;
this.screen.width = box.width;
this.screen.height = box.height;
});
__publicField(this, "update", () => {
this._eye.subVectors(this.object.position, this.target);
if (!this.noRotate) {
this.rotateCamera();
}
if (!this.noZoom) {
this.zoomCamera();
}
if (!this.noPan) {
this.panCamera();
}
this.object.position.addVectors(this.target, this._eye);
if (this.object.isPerspectiveCamera) {
this.checkDistances();
this.object.lookAt(this.target);
if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS) {
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
}
} else if (this.object.isOrthographicCamera) {
this.object.lookAt(this.target);
if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS || this.lastZoom !== this.object.zoom) {
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
this.lastZoom = this.object.zoom;
}
} else {
console.warn("THREE.TrackballControls: Unsupported camera type");
}
});
__publicField(this, "reset", () => {
this._state = this.STATE.NONE;
this._keyState = this.STATE.NONE;
this.target.copy(this.target0);
this.object.position.copy(this.position0);
this.object.up.copy(this.up0);
this.object.zoom = this.zoom0;
this.object.updateProjectionMatrix();
this._eye.subVectors(this.object.position, this.target);
this.object.lookAt(this.target);
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
this.lastZoom = this.object.zoom;
});
__publicField(this, "keydown", (event) => {
if (this.enabled === false)
return;
window.removeEventListener("keydown", this.keydown);
if (this._keyState !== this.STATE.NONE) {
return;
} else if (event.code === this.keys[this.STATE.ROTATE] && !this.noRotate) {
this._keyState = this.STATE.ROTATE;
} else if (event.code === this.keys[this.STATE.ZOOM] && !this.noZoom) {
this._keyState = this.STATE.ZOOM;
} else if (event.code === this.keys[this.STATE.PAN] && !this.noPan) {
this._keyState = this.STATE.PAN;
}
});
__publicField(this, "onPointerDown", (event) => {
if (this.enabled === false)
return;
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseDown(event);
break;
}
});
__publicField(this, "onPointerMove", (event) => {
if (this.enabled === false)
return;
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseMove(event);
break;
}
});
__publicField(this, "onPointerUp", (event) => {
if (this.enabled === false)
return;
switch (event.pointerType) {
case "mouse":
case "pen":
this.onMouseUp();
break;
}
});
__publicField(this, "keyup", () => {
if (this.enabled === false)
return;
this._keyState = this.STATE.NONE;
window.addEventListener("keydown", this.keydown);
});
__publicField(this, "onMouseDown", (event) => {
if (!this.domElement)
return;
if (this._state === this.STATE.NONE) {
switch (event.button) {
case this.mouseButtons.LEFT:
this._state = this.STATE.ROTATE;
break;
case this.mouseButtons.MIDDLE:
this._state = this.STATE.ZOOM;
break;
case this.mouseButtons.RIGHT:
this._state = this.STATE.PAN;
break;
}
}
const state = this._keyState !== this.STATE.NONE ? this._keyState : this._state;
if (state === this.STATE.ROTATE && !this.noRotate) {
this._moveCurr.copy(this.getMouseOnCircle(event.pageX, event.pageY));
this._movePrev.copy(this._moveCurr);
} else if (state === this.STATE.ZOOM && !this.noZoom) {
this._zoomStart.copy(this.getMouseOnScreen(event.pageX, event.pageY));
this._zoomEnd.copy(this._zoomStart);
} else if (state === this.STATE.PAN && !this.noPan) {
this._panStart.copy(this.getMouseOnScreen(event.pageX, event.pageY));
this._panEnd.copy(this._panStart);
}
this.domElement.ownerDocument.addEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.addEventListener("pointerup", this.onPointerUp);
this.dispatchEvent(this.startEvent);
});
__publicField(this, "onMouseMove", (event) => {
if (this.enabled === false)
return;
const state = this._keyState !== this.STATE.NONE ? this._keyState : this._state;
if (state === this.STATE.ROTATE && !this.noRotate) {
this._movePrev.copy(this._moveCurr);
this._moveCurr.copy(this.getMouseOnCircle(event.pageX, event.pageY));
} else if (state === this.STATE.ZOOM && !this.noZoom) {
this._zoomEnd.copy(this.getMouseOnScreen(event.pageX, event.pageY));
} else if (state === this.STATE.PAN && !this.noPan) {
this._panEnd.copy(this.getMouseOnScreen(event.pageX, event.pageY));
}
});
__publicField(this, "onMouseUp", () => {
if (!this.domElement)
return;
if (this.enabled === false)
return;
this._state = this.STATE.NONE;
this.domElement.ownerDocument.removeEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.removeEventListener("pointerup", this.onPointerUp);
this.dispatchEvent(this.endEvent);
});
__publicField(this, "mousewheel", (event) => {
if (this.enabled === false)
return;
if (this.noZoom === true)
return;
event.preventDefault();
switch (event.deltaMode) {
case 2:
this._zoomStart.y -= event.deltaY * 0.025;
break;
case 1:
this._zoomStart.y -= event.deltaY * 0.01;
break;
default:
this._zoomStart.y -= event.deltaY * 25e-5;
break;
}
this.mousePosition.x = event.offsetX / this.screen.width * 2 - 1;
this.mousePosition.y = -(event.offsetY / this.screen.height) * 2 + 1;
this.dispatchEvent(this.startEvent);
this.dispatchEvent(this.endEvent);
});
__publicField(this, "touchstart", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (event.touches.length) {
case 1:
this._state = this.STATE.TOUCH_ROTATE;
this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
this._movePrev.copy(this._moveCurr);
break;
default:
this._state = this.STATE.TOUCH_ZOOM_PAN;
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
this._touchZoomDistanceEnd = this._touchZoomDistanceStart = Math.sqrt(dx * dx + dy * dy);
const x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
const y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
this._panStart.copy(this.getMouseOnScreen(x, y));
this._panEnd.copy(this._panStart);
break;
}
this.dispatchEvent(this.startEvent);
});
__publicField(this, "touchmove", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (event.touches.length) {
case 1:
this._movePrev.copy(this._moveCurr);
this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
break;
default:
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
this._touchZoomDistanceEnd = Math.sqrt(dx * dx + dy * dy);
const x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
const y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
this._panEnd.copy(this.getMouseOnScreen(x, y));
break;
}
});
__publicField(this, "touchend", (event) => {
if (this.enabled === false)
return;
switch (event.touches.length) {
case 0:
this._state = this.STATE.NONE;
break;
case 1:
this._state = this.STATE.TOUCH_ROTATE;
this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
this._movePrev.copy(this._moveCurr);
break;
}
this.dispatchEvent(this.endEvent);
});
__publicField(this, "contextmenu", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
});
// https://github.com/mrdoob/three.js/issues/20575
__publicField(this, "connect", (domElement) => {
if (domElement === document) {
console.error(
'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.'
);
}
this.domElement = domElement;
this.domElement.addEventListener("contextmenu", this.contextmenu);
this.domElement.addEventListener("pointerdown", this.onPointerDown);
this.domElement.addEventListener("wheel", this.mousewheel);
this.domElement.addEventListener("touchstart", this.touchstart);
this.domElement.addEventListener("touchend", this.touchend);
this.domElement.addEventListener("touchmove", this.touchmove);
this.domElement.ownerDocument.addEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.addEventListener("pointerup", this.onPointerUp);
window.addEventListener("keydown", this.keydown);
window.addEventListener("keyup", this.keyup);
this.handleResize();
});
__publicField(this, "dispose", () => {
if (!this.domElement)
return;
this.domElement.removeEventListener("contextmenu", this.contextmenu);
this.domElement.removeEventListener("pointerdown", this.onPointerDown);
this.domElement.removeEventListener("wheel", this.mousewheel);
this.domElement.removeEventListener("touchstart", this.touchstart);
this.domElement.removeEventListener("touchend", this.touchend);
this.domElement.removeEventListener("touchmove", this.touchmove);
this.domElement.ownerDocument.removeEventListener("pointermove", this.onPointerMove);
this.domElement.ownerDocument.removeEventListener("pointerup", this.onPointerUp);
window.removeEventListener("keydown", this.keydown);
window.removeEventListener("keyup", this.keyup);
});
this.object = object;
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.up0 = this.object.up.clone();
this.zoom0 = this.object.zoom;
if (domElement !== void 0)
this.connect(domElement);
this.update();
}
}
export {
TrackballControls
};
//# sourceMappingURL=TrackballControls.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+151
View File
@@ -0,0 +1,151 @@
import { Mesh, MeshBasicMaterial, Object3D, PlaneGeometry, Camera } from 'three';
export interface TransformControlsPointerObject {
x: number;
y: number;
button: number;
}
declare class TransformControls<TCamera extends Camera = Camera> extends Object3D {
readonly isTransformControls = true;
visible: boolean;
private domElement;
private raycaster;
private gizmo;
private plane;
private tempVector;
private tempVector2;
private tempQuaternion;
private unit;
private pointStart;
private pointEnd;
private offset;
private rotationAxis;
private startNorm;
private endNorm;
private rotationAngle;
private cameraPosition;
private cameraQuaternion;
private cameraScale;
private parentPosition;
private parentQuaternion;
private parentQuaternionInv;
private parentScale;
private worldPositionStart;
private worldQuaternionStart;
private worldScaleStart;
private worldPosition;
private worldQuaternion;
private worldQuaternionInv;
private worldScale;
private eye;
private positionStart;
private quaternionStart;
private scaleStart;
private camera;
private object;
private enabled;
private axis;
private mode;
private translationSnap;
private rotationSnap;
private scaleSnap;
private space;
private size;
private dragging;
private showX;
private showY;
private showZ;
private changeEvent;
private mouseDownEvent;
private mouseUpEvent;
private objectChangeEvent;
constructor(camera: TCamera, domElement: HTMLElement | undefined);
private intersectObjectWithRay;
attach: (object: Object3D) => this;
detach: () => this;
reset: () => this;
updateMatrixWorld: () => void;
private pointerHover;
private pointerDown;
private pointerMove;
private pointerUp;
private getPointer;
private onPointerHover;
private onPointerDown;
private onPointerMove;
private onPointerUp;
getMode: () => TransformControls['mode'];
setMode: (mode: TransformControls['mode']) => void;
setTranslationSnap: (translationSnap: number) => void;
setRotationSnap: (rotationSnap: number) => void;
setScaleSnap: (scaleSnap: number) => void;
setSize: (size: number) => void;
setSpace: (space: string) => void;
update: () => void;
connect: (domElement: HTMLElement) => void;
dispose: () => void;
}
type TransformControlsGizmoPrivateGizmos = {
['translate']: Object3D;
['scale']: Object3D;
['rotate']: Object3D;
['visible']: boolean;
};
declare class TransformControlsGizmo extends Object3D {
private isTransformControlsGizmo;
type: string;
private tempVector;
private tempEuler;
private alignVector;
private zeroVector;
private lookAtMatrix;
private tempQuaternion;
private tempQuaternion2;
private identityQuaternion;
private unitX;
private unitY;
private unitZ;
private gizmo;
picker: TransformControlsGizmoPrivateGizmos;
private helper;
private rotationAxis;
private cameraPosition;
private worldPositionStart;
private worldQuaternionStart;
private worldPosition;
private worldQuaternion;
private eye;
private camera;
private enabled;
private axis;
private mode;
private space;
private size;
private dragging;
private showX;
private showY;
private showZ;
constructor();
updateMatrixWorld: () => void;
}
declare class TransformControlsPlane extends Mesh<PlaneGeometry, MeshBasicMaterial> {
private isTransformControlsPlane;
type: string;
constructor();
private unitX;
private unitY;
private unitZ;
private tempVector;
private dirVector;
private alignVector;
private tempMatrix;
private identityQuaternion;
private cameraQuaternion;
private worldPosition;
private worldQuaternion;
private eye;
private axis;
private mode;
private space;
updateMatrixWorld: () => void;
}
export { TransformControls, TransformControlsGizmo, TransformControlsPlane };
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+737
View File
@@ -0,0 +1,737 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const EventDispatcher = require("../EventDispatcher.cjs");
const STATE = {
NONE: -1,
ROTATE: 0,
DOLLY: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_PAN: 4,
TOUCH_DOLLY_PAN: 5,
TOUCH_DOLLY_ROTATE: 6
};
class CameraControls extends EventDispatcher.EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement");
/** Set to false to disable this control */
__publicField(this, "enabled", true);
/** "target" sets the location of focus, where the object orbits around */
__publicField(this, "target", new THREE.Vector3());
/** Set to true to enable trackball behavior */
__publicField(this, "trackball", false);
/** How far you can dolly in ( PerspectiveCamera only ) */
__publicField(this, "minDistance", 0);
/** How far you can dolly out ( PerspectiveCamera only ) */
__publicField(this, "maxDistance", Infinity);
// How far you can zoom in and out ( OrthographicCamera only )
__publicField(this, "minZoom", 0);
__publicField(this, "maxZoom", Infinity);
// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
__publicField(this, "minPolarAngle", 0);
__publicField(this, "maxPolarAngle", Math.PI);
// How far you can orbit horizontally, upper and lower limits.
// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
__publicField(this, "minAzimuthAngle", -Infinity);
// radians
__publicField(this, "maxAzimuthAngle", Infinity);
// radians
// Set to true to enable damping (inertia)
// If damping is enabled, you must call controls.update() in your animation loop
__publicField(this, "enableDamping", false);
__publicField(this, "dampingFactor", 0.05);
/**
* This option enables dollying in and out; property named as "zoom" for backwards compatibility
* Set to false to disable zooming
*/
__publicField(this, "enableZoom", true);
__publicField(this, "zoomSpeed", 1);
/** Set to false to disable rotating */
__publicField(this, "enableRotate", true);
__publicField(this, "rotateSpeed", 1);
/** Set to false to disable panning */
__publicField(this, "enablePan", true);
__publicField(this, "panSpeed", 1);
/** if true, pan in screen-space */
__publicField(this, "screenSpacePanning", false);
/** pixels moved per arrow key push */
__publicField(this, "keyPanSpeed", 7);
/**
* Set to true to automatically rotate around the target
* If auto-rotate is enabled, you must call controls.update() in your animation loop
* auto-rotate is not supported for trackball behavior
*/
__publicField(this, "autoRotate", false);
__publicField(this, "autoRotateSpeed", 2);
// 30 seconds per round when fps is 60
/** Set to false to disable use of the keys */
__publicField(this, "enableKeys", true);
/** The four arrow keys */
__publicField(this, "keys", { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" });
__publicField(this, "mouseButtons");
/** Touch fingers */
__publicField(this, "touches", { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN });
// for reset
__publicField(this, "target0");
__publicField(this, "position0");
__publicField(this, "quaternion0");
__publicField(this, "zoom0");
// current position in spherical coordinates
__publicField(this, "spherical", new THREE.Spherical());
__publicField(this, "sphericalDelta", new THREE.Spherical());
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "startEvent", { type: "start" });
__publicField(this, "endEvent", { type: "end" });
__publicField(this, "state", STATE.NONE);
__publicField(this, "EPS", 1e-6);
__publicField(this, "scale", 1);
__publicField(this, "panOffset", new THREE.Vector3());
__publicField(this, "zoomChanged", false);
__publicField(this, "rotateStart", new THREE.Vector2());
__publicField(this, "rotateEnd", new THREE.Vector2());
__publicField(this, "rotateDelta", new THREE.Vector2());
__publicField(this, "panStart", new THREE.Vector2());
__publicField(this, "panEnd", new THREE.Vector2());
__publicField(this, "panDelta", new THREE.Vector2());
__publicField(this, "dollyStart", new THREE.Vector2());
__publicField(this, "dollyEnd", new THREE.Vector2());
__publicField(this, "dollyDelta", new THREE.Vector2());
__publicField(this, "offset", new THREE.Vector3());
__publicField(this, "lastPosition", new THREE.Vector3());
__publicField(this, "lastQuaternion", new THREE.Quaternion());
__publicField(this, "q", new THREE.Quaternion());
__publicField(this, "v", new THREE.Vector3());
__publicField(this, "vec", new THREE.Vector3());
__publicField(this, "quat");
__publicField(this, "quatInverse");
__publicField(this, "getPolarAngle", () => this.spherical.phi);
__publicField(this, "getAzimuthalAngle", () => this.spherical.theta);
__publicField(this, "saveState", () => {
this.target0.copy(this.target);
this.position0.copy(this.object.position);
this.quaternion0.copy(this.object.quaternion);
this.zoom0 = this.object.zoom;
});
__publicField(this, "reset", () => {
this.target.copy(this.target0);
this.object.position.copy(this.position0);
this.object.quaternion.copy(this.quaternion0);
this.object.zoom = this.zoom0;
this.object.updateProjectionMatrix();
this.dispatchEvent(this.changeEvent);
this.update();
this.state = STATE.NONE;
});
__publicField(this, "dispose", () => {
this.domElement.removeEventListener("contextmenu", this.onContextMenu, false);
this.domElement.removeEventListener("mousedown", this.onMouseDown, false);
this.domElement.removeEventListener("wheel", this.onMouseWheel, false);
this.domElement.removeEventListener("touchstart", this.onTouchStart, false);
this.domElement.removeEventListener("touchend", this.onTouchEnd, false);
this.domElement.removeEventListener("touchmove", this.onTouchMove, false);
document.removeEventListener("mousemove", this.onMouseMove, false);
document.removeEventListener("mouseup", this.onMouseUp, false);
this.domElement.removeEventListener("keydown", this.onKeyDown, false);
});
__publicField(this, "update", () => {
const position = this.object.position;
this.offset.copy(position).sub(this.target);
if (this.trackball) {
if (this.sphericalDelta.theta) {
this.vec.set(0, 1, 0).applyQuaternion(this.object.quaternion);
const factor = this.enableDamping ? this.dampingFactor : 1;
this.q.setFromAxisAngle(this.vec, this.sphericalDelta.theta * factor);
this.object.quaternion.premultiply(this.q);
this.offset.applyQuaternion(this.q);
}
if (this.sphericalDelta.phi) {
this.vec.set(1, 0, 0).applyQuaternion(this.object.quaternion);
const factor = this.enableDamping ? this.dampingFactor : 1;
this.q.setFromAxisAngle(this.vec, this.sphericalDelta.phi * factor);
this.object.quaternion.premultiply(this.q);
this.offset.applyQuaternion(this.q);
}
this.offset.multiplyScalar(this.scale);
this.offset.clampLength(this.minDistance, this.maxDistance);
} else {
this.offset.applyQuaternion(this.quat);
if (this.autoRotate && this.state === STATE.NONE) {
this.rotateLeft(this.getAutoRotationAngle());
}
this.spherical.setFromVector3(this.offset);
if (this.enableDamping) {
this.spherical.theta += this.sphericalDelta.theta * this.dampingFactor;
this.spherical.phi += this.sphericalDelta.phi * this.dampingFactor;
} else {
this.spherical.theta += this.sphericalDelta.theta;
this.spherical.phi += this.sphericalDelta.phi;
}
this.spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, this.spherical.theta));
this.spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.spherical.phi));
this.spherical.makeSafe();
this.spherical.radius *= this.scale;
this.spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, this.spherical.radius));
this.offset.setFromSpherical(this.spherical);
this.offset.applyQuaternion(this.quatInverse);
}
if (this.enableDamping === true) {
this.target.addScaledVector(this.panOffset, this.dampingFactor);
} else {
this.target.add(this.panOffset);
}
position.copy(this.target).add(this.offset);
if (this.trackball === false) {
this.object.lookAt(this.target);
}
if (this.enableDamping === true) {
this.sphericalDelta.theta *= 1 - this.dampingFactor;
this.sphericalDelta.phi *= 1 - this.dampingFactor;
this.panOffset.multiplyScalar(1 - this.dampingFactor);
} else {
this.sphericalDelta.set(0, 0, 0);
this.panOffset.set(0, 0, 0);
}
this.scale = 1;
if (this.zoomChanged || this.lastPosition.distanceToSquared(this.object.position) > this.EPS || 8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
this.lastQuaternion.copy(this.object.quaternion);
this.zoomChanged = false;
return true;
}
return false;
});
__publicField(this, "getAutoRotationAngle", () => 2 * Math.PI / 60 / 60 * this.autoRotateSpeed);
__publicField(this, "getZoomScale", () => Math.pow(0.95, this.zoomSpeed));
__publicField(this, "rotateLeft", (angle) => {
this.sphericalDelta.theta -= angle;
});
__publicField(this, "rotateUp", (angle) => {
this.sphericalDelta.phi -= angle;
});
__publicField(this, "panLeft", (distance, objectMatrix) => {
this.v.setFromMatrixColumn(objectMatrix, 0);
this.v.multiplyScalar(-distance);
this.panOffset.add(this.v);
});
__publicField(this, "panUp", (distance, objectMatrix) => {
if (this.screenSpacePanning === true) {
this.v.setFromMatrixColumn(objectMatrix, 1);
} else {
this.v.setFromMatrixColumn(objectMatrix, 0);
this.v.crossVectors(this.object.up, this.v);
}
this.v.multiplyScalar(distance);
this.panOffset.add(this.v);
});
// deltaX and deltaY are in pixels; right and down are positive
__publicField(this, "pan", (deltaX, deltaY) => {
const element = this.domElement;
if (this.object instanceof THREE.PerspectiveCamera) {
const position = this.object.position;
this.offset.copy(position).sub(this.target);
let targetDistance = this.offset.length();
targetDistance *= Math.tan(this.object.fov / 2 * Math.PI / 180);
this.panLeft(2 * deltaX * targetDistance / element.clientHeight, this.object.matrix);
this.panUp(2 * deltaY * targetDistance / element.clientHeight, this.object.matrix);
} else if (this.object.isOrthographicCamera) {
this.panLeft(
deltaX * (this.object.right - this.object.left) / this.object.zoom / element.clientWidth,
this.object.matrix
);
this.panUp(
deltaY * (this.object.top - this.object.bottom) / this.object.zoom / element.clientHeight,
this.object.matrix
);
} else {
console.warn("WARNING: CameraControls.js encountered an unknown camera type - pan disabled.");
this.enablePan = false;
}
});
__publicField(this, "dollyIn", (dollyScale) => {
if (this.object instanceof THREE.PerspectiveCamera) {
this.scale /= dollyScale;
} else if (this.object instanceof THREE.OrthographicCamera) {
this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale));
this.object.updateProjectionMatrix();
this.zoomChanged = true;
} else {
console.warn("WARNING: CameraControls.js encountered an unknown camera type - dolly/zoom disabled.");
this.enableZoom = false;
}
});
__publicField(this, "dollyOut", (dollyScale) => {
if (this.object instanceof THREE.PerspectiveCamera) {
this.scale *= dollyScale;
} else if (this.object instanceof THREE.OrthographicCamera) {
this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale));
this.object.updateProjectionMatrix();
this.zoomChanged = true;
} else {
console.warn("WARNING: CameraControls.js encountered an unknown camera type - dolly/zoom disabled.");
this.enableZoom = false;
}
});
// event callbacks - update the object state
__publicField(this, "handleMouseDownRotate", (event) => {
this.rotateStart.set(event.clientX, event.clientY);
});
// TODO: confirm if worthwhile to return the Vector2 instead of void
__publicField(this, "handleMouseDownDolly", (event) => {
this.dollyStart.set(event.clientX, event.clientY);
});
__publicField(this, "handleMouseDownPan", (event) => {
this.panStart.set(event.clientX, event.clientY);
});
__publicField(this, "handleMouseMoveRotate", (event) => {
this.rotateEnd.set(event.clientX, event.clientY);
this.rotateDelta.subVectors(this.rotateEnd, this.rotateStart).multiplyScalar(this.rotateSpeed);
const element = this.domElement;
this.rotateLeft(2 * Math.PI * this.rotateDelta.x / element.clientHeight);
this.rotateUp(2 * Math.PI * this.rotateDelta.y / element.clientHeight);
this.rotateStart.copy(this.rotateEnd);
this.update();
});
__publicField(this, "handleMouseMoveDolly", (event) => {
this.dollyEnd.set(event.clientX, event.clientY);
this.dollyDelta.subVectors(this.dollyEnd, this.dollyStart);
if (this.dollyDelta.y > 0) {
this.dollyIn(this.getZoomScale());
} else if (this.dollyDelta.y < 0) {
this.dollyOut(this.getZoomScale());
}
this.dollyStart.copy(this.dollyEnd);
this.update();
});
__publicField(this, "handleMouseMovePan", (event) => {
this.panEnd.set(event.clientX, event.clientY);
this.panDelta.subVectors(this.panEnd, this.panStart).multiplyScalar(this.panSpeed);
this.pan(this.panDelta.x, this.panDelta.y);
this.panStart.copy(this.panEnd);
this.update();
});
__publicField(this, "handleMouseWheel", (event) => {
if (event.deltaY < 0) {
this.dollyOut(this.getZoomScale());
} else if (event.deltaY > 0) {
this.dollyIn(this.getZoomScale());
}
this.update();
});
__publicField(this, "handleKeyDown", (event) => {
let needsUpdate = false;
switch (event.code) {
case this.keys.UP:
this.pan(0, this.keyPanSpeed);
needsUpdate = true;
break;
case this.keys.BOTTOM:
this.pan(0, -this.keyPanSpeed);
needsUpdate = true;
break;
case this.keys.LEFT:
this.pan(this.keyPanSpeed, 0);
needsUpdate = true;
break;
case this.keys.RIGHT:
this.pan(-this.keyPanSpeed, 0);
needsUpdate = true;
break;
}
if (needsUpdate) {
event.preventDefault();
this.update();
}
});
__publicField(this, "handleTouchStartRotate", (event) => {
if (event.touches.length == 1) {
this.rotateStart.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.rotateStart.set(x, y);
}
});
__publicField(this, "handleTouchStartPan", (event) => {
if (event.touches.length == 1) {
this.panStart.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.panStart.set(x, y);
}
});
__publicField(this, "handleTouchStartDolly", (event) => {
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
const distance = Math.sqrt(dx * dx + dy * dy);
this.dollyStart.set(0, distance);
});
__publicField(this, "handleTouchStartDollyPan", (event) => {
if (this.enableZoom)
this.handleTouchStartDolly(event);
if (this.enablePan)
this.handleTouchStartPan(event);
});
__publicField(this, "handleTouchStartDollyRotate", (event) => {
if (this.enableZoom)
this.handleTouchStartDolly(event);
if (this.enableRotate)
this.handleTouchStartRotate(event);
});
__publicField(this, "handleTouchMoveRotate", (event) => {
if (event.touches.length == 1) {
this.rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.rotateEnd.set(x, y);
}
this.rotateDelta.subVectors(this.rotateEnd, this.rotateStart).multiplyScalar(this.rotateSpeed);
const element = this.domElement;
this.rotateLeft(2 * Math.PI * this.rotateDelta.x / element.clientHeight);
this.rotateUp(2 * Math.PI * this.rotateDelta.y / element.clientHeight);
this.rotateStart.copy(this.rotateEnd);
});
__publicField(this, "handleTouchMovePan", (event) => {
if (event.touches.length == 1) {
this.panEnd.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.panEnd.set(x, y);
}
this.panDelta.subVectors(this.panEnd, this.panStart).multiplyScalar(this.panSpeed);
this.pan(this.panDelta.x, this.panDelta.y);
this.panStart.copy(this.panEnd);
});
__publicField(this, "handleTouchMoveDolly", (event) => {
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
const distance = Math.sqrt(dx * dx + dy * dy);
this.dollyEnd.set(0, distance);
this.dollyDelta.set(0, Math.pow(this.dollyEnd.y / this.dollyStart.y, this.zoomSpeed));
this.dollyIn(this.dollyDelta.y);
this.dollyStart.copy(this.dollyEnd);
});
__publicField(this, "handleTouchMoveDollyPan", (event) => {
if (this.enableZoom)
this.handleTouchMoveDolly(event);
if (this.enablePan)
this.handleTouchMovePan(event);
});
__publicField(this, "handleTouchMoveDollyRotate", (event) => {
if (this.enableZoom)
this.handleTouchMoveDolly(event);
if (this.enableRotate)
this.handleTouchMoveRotate(event);
});
//
// event handlers - FSM: listen for events and reset state
//
__publicField(this, "onMouseDown", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
this.domElement.focus ? this.domElement.focus() : window.focus();
let mouseAction;
switch (event.button) {
case 0:
mouseAction = this.mouseButtons.LEFT;
break;
case 1:
mouseAction = this.mouseButtons.MIDDLE;
break;
case 2:
mouseAction = this.mouseButtons.RIGHT;
break;
default:
mouseAction = -1;
}
switch (mouseAction) {
case THREE.MOUSE.DOLLY:
if (this.enableZoom === false)
return;
this.handleMouseDownDolly(event);
this.state = STATE.DOLLY;
break;
case THREE.MOUSE.ROTATE:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (this.enablePan === false)
return;
this.handleMouseDownPan(event);
this.state = STATE.PAN;
} else {
if (this.enableRotate === false)
return;
this.handleMouseDownRotate(event);
this.state = STATE.ROTATE;
}
break;
case THREE.MOUSE.PAN:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (this.enableRotate === false)
return;
this.handleMouseDownRotate(event);
this.state = STATE.ROTATE;
} else {
if (this.enablePan === false)
return;
this.handleMouseDownPan(event);
this.state = STATE.PAN;
}
break;
default:
this.state = STATE.NONE;
}
if (this.state !== STATE.NONE) {
document.addEventListener("mousemove", this.onMouseMove, false);
document.addEventListener("mouseup", this.onMouseUp, false);
this.dispatchEvent(this.startEvent);
}
});
__publicField(this, "onMouseMove", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (this.state) {
case STATE.ROTATE:
if (this.enableRotate === false)
return;
this.handleMouseMoveRotate(event);
break;
case STATE.DOLLY:
if (this.enableZoom === false)
return;
this.handleMouseMoveDolly(event);
break;
case STATE.PAN:
if (this.enablePan === false)
return;
this.handleMouseMovePan(event);
break;
}
});
__publicField(this, "onMouseUp", () => {
if (this.enabled === false)
return;
document.removeEventListener("mousemove", this.onMouseMove, false);
document.removeEventListener("mouseup", this.onMouseUp, false);
this.dispatchEvent(this.endEvent);
this.state = STATE.NONE;
});
__publicField(this, "onMouseWheel", (event) => {
if (this.enabled === false || this.enableZoom === false || this.state !== STATE.NONE && this.state !== STATE.ROTATE) {
return;
}
event.preventDefault();
this.dispatchEvent(this.startEvent);
this.handleMouseWheel(event);
this.dispatchEvent(this.endEvent);
});
__publicField(this, "onKeyDown", (event) => {
if (this.enabled === false || this.enableKeys === false || this.enablePan === false)
return;
this.handleKeyDown(event);
});
__publicField(this, "onTouchStart", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (event.touches.length) {
case 1:
switch (this.touches.ONE) {
case THREE.TOUCH.ROTATE:
if (this.enableRotate === false)
return;
this.handleTouchStartRotate(event);
this.state = STATE.TOUCH_ROTATE;
break;
case THREE.TOUCH.PAN:
if (this.enablePan === false)
return;
this.handleTouchStartPan(event);
this.state = STATE.TOUCH_PAN;
break;
default:
this.state = STATE.NONE;
}
break;
case 2:
switch (this.touches.TWO) {
case THREE.TOUCH.DOLLY_PAN:
if (this.enableZoom === false && this.enablePan === false)
return;
this.handleTouchStartDollyPan(event);
this.state = STATE.TOUCH_DOLLY_PAN;
break;
case THREE.TOUCH.DOLLY_ROTATE:
if (this.enableZoom === false && this.enableRotate === false)
return;
this.handleTouchStartDollyRotate(event);
this.state = STATE.TOUCH_DOLLY_ROTATE;
break;
default:
this.state = STATE.NONE;
}
break;
default:
this.state = STATE.NONE;
}
if (this.state !== STATE.NONE) {
this.dispatchEvent(this.startEvent);
}
});
__publicField(this, "onTouchMove", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (this.state) {
case STATE.TOUCH_ROTATE:
if (this.enableRotate === false)
return;
this.handleTouchMoveRotate(event);
this.update();
break;
case STATE.TOUCH_PAN:
if (this.enablePan === false)
return;
this.handleTouchMovePan(event);
this.update();
break;
case STATE.TOUCH_DOLLY_PAN:
if (this.enableZoom === false && this.enablePan === false)
return;
this.handleTouchMoveDollyPan(event);
this.update();
break;
case STATE.TOUCH_DOLLY_ROTATE:
if (this.enableZoom === false && this.enableRotate === false)
return;
this.handleTouchMoveDollyRotate(event);
this.update();
break;
default:
this.state = STATE.NONE;
}
});
__publicField(this, "onTouchEnd", () => {
if (this.enabled === false)
return;
this.dispatchEvent(this.endEvent);
this.state = STATE.NONE;
});
__publicField(this, "onContextMenu", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
});
if (domElement === void 0) {
console.warn('THREE.CameraControls: The second parameter "domElement" is now mandatory.');
}
if (domElement instanceof Document) {
console.error(
'THREE.CameraControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.'
);
}
this.object = object;
this.domElement = domElement;
this.mouseButtons = {
LEFT: THREE.MOUSE.ROTATE,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.PAN
};
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.quaternion0 = this.object.quaternion.clone();
this.zoom0 = this.object.zoom;
this.quat = new THREE.Quaternion().setFromUnitVectors(this.object.up, new THREE.Vector3(0, 1, 0));
this.quatInverse = this.quat.clone().invert();
this.lastPosition = new THREE.Vector3();
this.lastQuaternion = new THREE.Quaternion();
this.domElement.addEventListener("contextmenu", this.onContextMenu, false);
this.domElement.addEventListener("mousedown", this.onMouseDown, false);
this.domElement.addEventListener("wheel", this.onMouseWheel, false);
this.domElement.addEventListener("touchstart", this.onTouchStart, false);
this.domElement.addEventListener("touchend", this.onTouchEnd, false);
this.domElement.addEventListener("touchmove", this.onTouchMove, false);
this.domElement.addEventListener("keydown", this.onKeyDown, false);
if (this.domElement.tabIndex === -1) {
this.domElement.tabIndex = 0;
}
this.object.lookAt(this.target);
this.update();
this.saveState();
}
handleMouseUp() {
}
handleTouchEnd() {
}
}
class OrbitControlsExp extends CameraControls {
constructor(object, domElement) {
super(object, domElement);
__publicField(this, "mouseButtons");
__publicField(this, "touches");
this.mouseButtons = {
LEFT: THREE.MOUSE.ROTATE,
RIGHT: THREE.MOUSE.PAN
};
this.touches = {
ONE: THREE.TOUCH.ROTATE,
TWO: THREE.TOUCH.DOLLY_PAN
};
}
}
class MapControlsExp extends CameraControls {
constructor(object, domElement) {
super(object, domElement);
__publicField(this, "mouseButtons");
__publicField(this, "touches");
this.mouseButtons = {
LEFT: THREE.MOUSE.PAN,
RIGHT: THREE.MOUSE.ROTATE
};
this.touches = {
ONE: THREE.TOUCH.PAN,
TWO: THREE.TOUCH.DOLLY_ROTATE
};
}
}
class TrackballControlsExp extends CameraControls {
constructor(object, domElement) {
super(object, domElement);
__publicField(this, "trackball");
__publicField(this, "screenSpacePanning");
__publicField(this, "autoRotate");
__publicField(this, "mouseButtons");
__publicField(this, "touches");
this.trackball = true;
this.screenSpacePanning = true;
this.autoRotate = false;
this.mouseButtons = {
LEFT: THREE.MOUSE.ROTATE,
RIGHT: THREE.MOUSE.PAN
};
this.touches = {
ONE: THREE.TOUCH.ROTATE,
TWO: THREE.TOUCH.DOLLY_PAN
};
}
}
exports.CameraControls = CameraControls;
exports.MapControlsExp = MapControlsExp;
exports.OrbitControlsExp = OrbitControlsExp;
exports.STATE = STATE;
exports.TrackballControlsExp = TrackballControlsExp;
//# sourceMappingURL=CameraControls.cjs.map
File diff suppressed because one or more lines are too long
+213
View File
@@ -0,0 +1,213 @@
import { MOUSE, OrthographicCamera, PerspectiveCamera, Quaternion, Spherical, TOUCH, Vector3 } from 'three';
import { EventDispatcher } from '../EventDispatcher';
export type CHANGE_EVENT = {
type: 'change' | 'start' | 'end';
};
export declare const STATE: {
NONE: number;
ROTATE: number;
DOLLY: number;
PAN: number;
TOUCH_ROTATE: number;
TOUCH_PAN: number;
TOUCH_DOLLY_PAN: number;
TOUCH_DOLLY_ROTATE: number;
};
declare class CameraControls extends EventDispatcher<Record<string, {}>> {
object: PerspectiveCamera | OrthographicCamera;
domElement: HTMLElement;
/** Set to false to disable this control */
enabled: boolean;
/** "target" sets the location of focus, where the object orbits around */
target: Vector3;
/** Set to true to enable trackball behavior */
trackball: boolean;
/** How far you can dolly in ( PerspectiveCamera only ) */
minDistance: number;
/** How far you can dolly out ( PerspectiveCamera only ) */
maxDistance: number;
minZoom: number;
maxZoom: number;
minPolarAngle: number;
maxPolarAngle: number;
minAzimuthAngle: number;
maxAzimuthAngle: number;
enableDamping: boolean;
dampingFactor: number;
/**
* This option enables dollying in and out; property named as "zoom" for backwards compatibility
* Set to false to disable zooming
*/
enableZoom: boolean;
zoomSpeed: number;
/** Set to false to disable rotating */
enableRotate: boolean;
rotateSpeed: number;
/** Set to false to disable panning */
enablePan: boolean;
panSpeed: number;
/** if true, pan in screen-space */
screenSpacePanning: boolean;
/** pixels moved per arrow key push */
keyPanSpeed: number;
/**
* Set to true to automatically rotate around the target
* If auto-rotate is enabled, you must call controls.update() in your animation loop
* auto-rotate is not supported for trackball behavior
*/
autoRotate: boolean;
autoRotateSpeed: number;
/** Set to false to disable use of the keys */
enableKeys: boolean;
/** The four arrow keys */
keys: {
LEFT: string;
UP: string;
RIGHT: string;
BOTTOM: string;
};
mouseButtons: {
LEFT: MOUSE;
MIDDLE?: MOUSE;
RIGHT: MOUSE;
};
/** Touch fingers */
touches: {
ONE: TOUCH;
TWO: TOUCH;
};
target0: Vector3;
position0: Vector3;
quaternion0: Quaternion;
zoom0: number;
spherical: Spherical;
sphericalDelta: Spherical;
private changeEvent;
private startEvent;
private endEvent;
private state;
private EPS;
private scale;
private panOffset;
private zoomChanged;
private rotateStart;
private rotateEnd;
private rotateDelta;
private panStart;
private panEnd;
private panDelta;
private dollyStart;
private dollyEnd;
private dollyDelta;
private offset;
private lastPosition;
private lastQuaternion;
private q;
private v;
private vec;
private quat;
private quatInverse;
constructor(object: PerspectiveCamera | OrthographicCamera, domElement: HTMLElement);
getPolarAngle: () => number;
getAzimuthalAngle: () => number;
saveState: () => void;
reset: () => void;
dispose: () => void;
private update;
private getAutoRotationAngle;
private getZoomScale;
private rotateLeft;
private rotateUp;
private panLeft;
private panUp;
private pan;
private dollyIn;
private dollyOut;
private handleMouseDownRotate;
private handleMouseDownDolly;
private handleMouseDownPan;
private handleMouseMoveRotate;
private handleMouseMoveDolly;
private handleMouseMovePan;
private handleMouseUp;
private handleMouseWheel;
private handleKeyDown;
private handleTouchStartRotate;
private handleTouchStartPan;
private handleTouchStartDolly;
private handleTouchStartDollyPan;
private handleTouchStartDollyRotate;
private handleTouchMoveRotate;
private handleTouchMovePan;
private handleTouchMoveDolly;
private handleTouchMoveDollyPan;
private handleTouchMoveDollyRotate;
private handleTouchEnd;
private onMouseDown;
private onMouseMove;
private onMouseUp;
private onMouseWheel;
private onKeyDown;
private onTouchStart;
private onTouchMove;
private onTouchEnd;
private onContextMenu;
}
/**
* OrbitControls maintains the "up" direction, camera.up (+Y by default).
*
* @event Orbit - left mouse / touch: one-finger move
* @event Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
* @event Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
*/
declare class OrbitControlsExp extends CameraControls {
mouseButtons: {
LEFT: MOUSE;
RIGHT: MOUSE;
};
touches: {
ONE: TOUCH;
TWO: TOUCH;
};
constructor(object: PerspectiveCamera | OrthographicCamera, domElement: HTMLElement);
}
/**
* MapControls maintains the "up" direction, camera.up (+Y by default)
*
* @event Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate
* @event Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
* @event Pan - left mouse, or left right + ctrl/meta/shiftKey, or arrow keys / touch: one-finger move
*/
declare class MapControlsExp extends CameraControls {
mouseButtons: {
LEFT: MOUSE;
RIGHT: MOUSE;
};
touches: {
ONE: TOUCH;
TWO: TOUCH;
};
constructor(object: PerspectiveCamera | OrthographicCamera, domElement: HTMLElement);
}
/**
* TrackballControls allows the camera to rotate over the polls and does not maintain camera.up
*
* @event Orbit - left mouse / touch: one-finger move
* @event Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
* @event Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
*/
declare class TrackballControlsExp extends CameraControls {
trackball: boolean;
screenSpacePanning: boolean;
autoRotate: boolean;
mouseButtons: {
LEFT: MOUSE;
RIGHT: MOUSE;
};
touches: {
ONE: TOUCH;
TWO: TOUCH;
};
constructor(object: PerspectiveCamera | OrthographicCamera, domElement: HTMLElement);
}
export { CameraControls, OrbitControlsExp, MapControlsExp, TrackballControlsExp };
+737
View File
@@ -0,0 +1,737 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
import { Vector3, TOUCH, Spherical, Vector2, Quaternion, MOUSE, PerspectiveCamera, OrthographicCamera } from "three";
import { EventDispatcher } from "../EventDispatcher.js";
const STATE = {
NONE: -1,
ROTATE: 0,
DOLLY: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_PAN: 4,
TOUCH_DOLLY_PAN: 5,
TOUCH_DOLLY_ROTATE: 6
};
class CameraControls extends EventDispatcher {
constructor(object, domElement) {
super();
__publicField(this, "object");
__publicField(this, "domElement");
/** Set to false to disable this control */
__publicField(this, "enabled", true);
/** "target" sets the location of focus, where the object orbits around */
__publicField(this, "target", new Vector3());
/** Set to true to enable trackball behavior */
__publicField(this, "trackball", false);
/** How far you can dolly in ( PerspectiveCamera only ) */
__publicField(this, "minDistance", 0);
/** How far you can dolly out ( PerspectiveCamera only ) */
__publicField(this, "maxDistance", Infinity);
// How far you can zoom in and out ( OrthographicCamera only )
__publicField(this, "minZoom", 0);
__publicField(this, "maxZoom", Infinity);
// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
__publicField(this, "minPolarAngle", 0);
__publicField(this, "maxPolarAngle", Math.PI);
// How far you can orbit horizontally, upper and lower limits.
// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
__publicField(this, "minAzimuthAngle", -Infinity);
// radians
__publicField(this, "maxAzimuthAngle", Infinity);
// radians
// Set to true to enable damping (inertia)
// If damping is enabled, you must call controls.update() in your animation loop
__publicField(this, "enableDamping", false);
__publicField(this, "dampingFactor", 0.05);
/**
* This option enables dollying in and out; property named as "zoom" for backwards compatibility
* Set to false to disable zooming
*/
__publicField(this, "enableZoom", true);
__publicField(this, "zoomSpeed", 1);
/** Set to false to disable rotating */
__publicField(this, "enableRotate", true);
__publicField(this, "rotateSpeed", 1);
/** Set to false to disable panning */
__publicField(this, "enablePan", true);
__publicField(this, "panSpeed", 1);
/** if true, pan in screen-space */
__publicField(this, "screenSpacePanning", false);
/** pixels moved per arrow key push */
__publicField(this, "keyPanSpeed", 7);
/**
* Set to true to automatically rotate around the target
* If auto-rotate is enabled, you must call controls.update() in your animation loop
* auto-rotate is not supported for trackball behavior
*/
__publicField(this, "autoRotate", false);
__publicField(this, "autoRotateSpeed", 2);
// 30 seconds per round when fps is 60
/** Set to false to disable use of the keys */
__publicField(this, "enableKeys", true);
/** The four arrow keys */
__publicField(this, "keys", { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" });
__publicField(this, "mouseButtons");
/** Touch fingers */
__publicField(this, "touches", { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN });
// for reset
__publicField(this, "target0");
__publicField(this, "position0");
__publicField(this, "quaternion0");
__publicField(this, "zoom0");
// current position in spherical coordinates
__publicField(this, "spherical", new Spherical());
__publicField(this, "sphericalDelta", new Spherical());
__publicField(this, "changeEvent", { type: "change" });
__publicField(this, "startEvent", { type: "start" });
__publicField(this, "endEvent", { type: "end" });
__publicField(this, "state", STATE.NONE);
__publicField(this, "EPS", 1e-6);
__publicField(this, "scale", 1);
__publicField(this, "panOffset", new Vector3());
__publicField(this, "zoomChanged", false);
__publicField(this, "rotateStart", new Vector2());
__publicField(this, "rotateEnd", new Vector2());
__publicField(this, "rotateDelta", new Vector2());
__publicField(this, "panStart", new Vector2());
__publicField(this, "panEnd", new Vector2());
__publicField(this, "panDelta", new Vector2());
__publicField(this, "dollyStart", new Vector2());
__publicField(this, "dollyEnd", new Vector2());
__publicField(this, "dollyDelta", new Vector2());
__publicField(this, "offset", new Vector3());
__publicField(this, "lastPosition", new Vector3());
__publicField(this, "lastQuaternion", new Quaternion());
__publicField(this, "q", new Quaternion());
__publicField(this, "v", new Vector3());
__publicField(this, "vec", new Vector3());
__publicField(this, "quat");
__publicField(this, "quatInverse");
__publicField(this, "getPolarAngle", () => this.spherical.phi);
__publicField(this, "getAzimuthalAngle", () => this.spherical.theta);
__publicField(this, "saveState", () => {
this.target0.copy(this.target);
this.position0.copy(this.object.position);
this.quaternion0.copy(this.object.quaternion);
this.zoom0 = this.object.zoom;
});
__publicField(this, "reset", () => {
this.target.copy(this.target0);
this.object.position.copy(this.position0);
this.object.quaternion.copy(this.quaternion0);
this.object.zoom = this.zoom0;
this.object.updateProjectionMatrix();
this.dispatchEvent(this.changeEvent);
this.update();
this.state = STATE.NONE;
});
__publicField(this, "dispose", () => {
this.domElement.removeEventListener("contextmenu", this.onContextMenu, false);
this.domElement.removeEventListener("mousedown", this.onMouseDown, false);
this.domElement.removeEventListener("wheel", this.onMouseWheel, false);
this.domElement.removeEventListener("touchstart", this.onTouchStart, false);
this.domElement.removeEventListener("touchend", this.onTouchEnd, false);
this.domElement.removeEventListener("touchmove", this.onTouchMove, false);
document.removeEventListener("mousemove", this.onMouseMove, false);
document.removeEventListener("mouseup", this.onMouseUp, false);
this.domElement.removeEventListener("keydown", this.onKeyDown, false);
});
__publicField(this, "update", () => {
const position = this.object.position;
this.offset.copy(position).sub(this.target);
if (this.trackball) {
if (this.sphericalDelta.theta) {
this.vec.set(0, 1, 0).applyQuaternion(this.object.quaternion);
const factor = this.enableDamping ? this.dampingFactor : 1;
this.q.setFromAxisAngle(this.vec, this.sphericalDelta.theta * factor);
this.object.quaternion.premultiply(this.q);
this.offset.applyQuaternion(this.q);
}
if (this.sphericalDelta.phi) {
this.vec.set(1, 0, 0).applyQuaternion(this.object.quaternion);
const factor = this.enableDamping ? this.dampingFactor : 1;
this.q.setFromAxisAngle(this.vec, this.sphericalDelta.phi * factor);
this.object.quaternion.premultiply(this.q);
this.offset.applyQuaternion(this.q);
}
this.offset.multiplyScalar(this.scale);
this.offset.clampLength(this.minDistance, this.maxDistance);
} else {
this.offset.applyQuaternion(this.quat);
if (this.autoRotate && this.state === STATE.NONE) {
this.rotateLeft(this.getAutoRotationAngle());
}
this.spherical.setFromVector3(this.offset);
if (this.enableDamping) {
this.spherical.theta += this.sphericalDelta.theta * this.dampingFactor;
this.spherical.phi += this.sphericalDelta.phi * this.dampingFactor;
} else {
this.spherical.theta += this.sphericalDelta.theta;
this.spherical.phi += this.sphericalDelta.phi;
}
this.spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, this.spherical.theta));
this.spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.spherical.phi));
this.spherical.makeSafe();
this.spherical.radius *= this.scale;
this.spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, this.spherical.radius));
this.offset.setFromSpherical(this.spherical);
this.offset.applyQuaternion(this.quatInverse);
}
if (this.enableDamping === true) {
this.target.addScaledVector(this.panOffset, this.dampingFactor);
} else {
this.target.add(this.panOffset);
}
position.copy(this.target).add(this.offset);
if (this.trackball === false) {
this.object.lookAt(this.target);
}
if (this.enableDamping === true) {
this.sphericalDelta.theta *= 1 - this.dampingFactor;
this.sphericalDelta.phi *= 1 - this.dampingFactor;
this.panOffset.multiplyScalar(1 - this.dampingFactor);
} else {
this.sphericalDelta.set(0, 0, 0);
this.panOffset.set(0, 0, 0);
}
this.scale = 1;
if (this.zoomChanged || this.lastPosition.distanceToSquared(this.object.position) > this.EPS || 8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
this.dispatchEvent(this.changeEvent);
this.lastPosition.copy(this.object.position);
this.lastQuaternion.copy(this.object.quaternion);
this.zoomChanged = false;
return true;
}
return false;
});
__publicField(this, "getAutoRotationAngle", () => 2 * Math.PI / 60 / 60 * this.autoRotateSpeed);
__publicField(this, "getZoomScale", () => Math.pow(0.95, this.zoomSpeed));
__publicField(this, "rotateLeft", (angle) => {
this.sphericalDelta.theta -= angle;
});
__publicField(this, "rotateUp", (angle) => {
this.sphericalDelta.phi -= angle;
});
__publicField(this, "panLeft", (distance, objectMatrix) => {
this.v.setFromMatrixColumn(objectMatrix, 0);
this.v.multiplyScalar(-distance);
this.panOffset.add(this.v);
});
__publicField(this, "panUp", (distance, objectMatrix) => {
if (this.screenSpacePanning === true) {
this.v.setFromMatrixColumn(objectMatrix, 1);
} else {
this.v.setFromMatrixColumn(objectMatrix, 0);
this.v.crossVectors(this.object.up, this.v);
}
this.v.multiplyScalar(distance);
this.panOffset.add(this.v);
});
// deltaX and deltaY are in pixels; right and down are positive
__publicField(this, "pan", (deltaX, deltaY) => {
const element = this.domElement;
if (this.object instanceof PerspectiveCamera) {
const position = this.object.position;
this.offset.copy(position).sub(this.target);
let targetDistance = this.offset.length();
targetDistance *= Math.tan(this.object.fov / 2 * Math.PI / 180);
this.panLeft(2 * deltaX * targetDistance / element.clientHeight, this.object.matrix);
this.panUp(2 * deltaY * targetDistance / element.clientHeight, this.object.matrix);
} else if (this.object.isOrthographicCamera) {
this.panLeft(
deltaX * (this.object.right - this.object.left) / this.object.zoom / element.clientWidth,
this.object.matrix
);
this.panUp(
deltaY * (this.object.top - this.object.bottom) / this.object.zoom / element.clientHeight,
this.object.matrix
);
} else {
console.warn("WARNING: CameraControls.js encountered an unknown camera type - pan disabled.");
this.enablePan = false;
}
});
__publicField(this, "dollyIn", (dollyScale) => {
if (this.object instanceof PerspectiveCamera) {
this.scale /= dollyScale;
} else if (this.object instanceof OrthographicCamera) {
this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale));
this.object.updateProjectionMatrix();
this.zoomChanged = true;
} else {
console.warn("WARNING: CameraControls.js encountered an unknown camera type - dolly/zoom disabled.");
this.enableZoom = false;
}
});
__publicField(this, "dollyOut", (dollyScale) => {
if (this.object instanceof PerspectiveCamera) {
this.scale *= dollyScale;
} else if (this.object instanceof OrthographicCamera) {
this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale));
this.object.updateProjectionMatrix();
this.zoomChanged = true;
} else {
console.warn("WARNING: CameraControls.js encountered an unknown camera type - dolly/zoom disabled.");
this.enableZoom = false;
}
});
// event callbacks - update the object state
__publicField(this, "handleMouseDownRotate", (event) => {
this.rotateStart.set(event.clientX, event.clientY);
});
// TODO: confirm if worthwhile to return the Vector2 instead of void
__publicField(this, "handleMouseDownDolly", (event) => {
this.dollyStart.set(event.clientX, event.clientY);
});
__publicField(this, "handleMouseDownPan", (event) => {
this.panStart.set(event.clientX, event.clientY);
});
__publicField(this, "handleMouseMoveRotate", (event) => {
this.rotateEnd.set(event.clientX, event.clientY);
this.rotateDelta.subVectors(this.rotateEnd, this.rotateStart).multiplyScalar(this.rotateSpeed);
const element = this.domElement;
this.rotateLeft(2 * Math.PI * this.rotateDelta.x / element.clientHeight);
this.rotateUp(2 * Math.PI * this.rotateDelta.y / element.clientHeight);
this.rotateStart.copy(this.rotateEnd);
this.update();
});
__publicField(this, "handleMouseMoveDolly", (event) => {
this.dollyEnd.set(event.clientX, event.clientY);
this.dollyDelta.subVectors(this.dollyEnd, this.dollyStart);
if (this.dollyDelta.y > 0) {
this.dollyIn(this.getZoomScale());
} else if (this.dollyDelta.y < 0) {
this.dollyOut(this.getZoomScale());
}
this.dollyStart.copy(this.dollyEnd);
this.update();
});
__publicField(this, "handleMouseMovePan", (event) => {
this.panEnd.set(event.clientX, event.clientY);
this.panDelta.subVectors(this.panEnd, this.panStart).multiplyScalar(this.panSpeed);
this.pan(this.panDelta.x, this.panDelta.y);
this.panStart.copy(this.panEnd);
this.update();
});
__publicField(this, "handleMouseWheel", (event) => {
if (event.deltaY < 0) {
this.dollyOut(this.getZoomScale());
} else if (event.deltaY > 0) {
this.dollyIn(this.getZoomScale());
}
this.update();
});
__publicField(this, "handleKeyDown", (event) => {
let needsUpdate = false;
switch (event.code) {
case this.keys.UP:
this.pan(0, this.keyPanSpeed);
needsUpdate = true;
break;
case this.keys.BOTTOM:
this.pan(0, -this.keyPanSpeed);
needsUpdate = true;
break;
case this.keys.LEFT:
this.pan(this.keyPanSpeed, 0);
needsUpdate = true;
break;
case this.keys.RIGHT:
this.pan(-this.keyPanSpeed, 0);
needsUpdate = true;
break;
}
if (needsUpdate) {
event.preventDefault();
this.update();
}
});
__publicField(this, "handleTouchStartRotate", (event) => {
if (event.touches.length == 1) {
this.rotateStart.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.rotateStart.set(x, y);
}
});
__publicField(this, "handleTouchStartPan", (event) => {
if (event.touches.length == 1) {
this.panStart.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.panStart.set(x, y);
}
});
__publicField(this, "handleTouchStartDolly", (event) => {
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
const distance = Math.sqrt(dx * dx + dy * dy);
this.dollyStart.set(0, distance);
});
__publicField(this, "handleTouchStartDollyPan", (event) => {
if (this.enableZoom)
this.handleTouchStartDolly(event);
if (this.enablePan)
this.handleTouchStartPan(event);
});
__publicField(this, "handleTouchStartDollyRotate", (event) => {
if (this.enableZoom)
this.handleTouchStartDolly(event);
if (this.enableRotate)
this.handleTouchStartRotate(event);
});
__publicField(this, "handleTouchMoveRotate", (event) => {
if (event.touches.length == 1) {
this.rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.rotateEnd.set(x, y);
}
this.rotateDelta.subVectors(this.rotateEnd, this.rotateStart).multiplyScalar(this.rotateSpeed);
const element = this.domElement;
this.rotateLeft(2 * Math.PI * this.rotateDelta.x / element.clientHeight);
this.rotateUp(2 * Math.PI * this.rotateDelta.y / element.clientHeight);
this.rotateStart.copy(this.rotateEnd);
});
__publicField(this, "handleTouchMovePan", (event) => {
if (event.touches.length == 1) {
this.panEnd.set(event.touches[0].pageX, event.touches[0].pageY);
} else {
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
this.panEnd.set(x, y);
}
this.panDelta.subVectors(this.panEnd, this.panStart).multiplyScalar(this.panSpeed);
this.pan(this.panDelta.x, this.panDelta.y);
this.panStart.copy(this.panEnd);
});
__publicField(this, "handleTouchMoveDolly", (event) => {
const dx = event.touches[0].pageX - event.touches[1].pageX;
const dy = event.touches[0].pageY - event.touches[1].pageY;
const distance = Math.sqrt(dx * dx + dy * dy);
this.dollyEnd.set(0, distance);
this.dollyDelta.set(0, Math.pow(this.dollyEnd.y / this.dollyStart.y, this.zoomSpeed));
this.dollyIn(this.dollyDelta.y);
this.dollyStart.copy(this.dollyEnd);
});
__publicField(this, "handleTouchMoveDollyPan", (event) => {
if (this.enableZoom)
this.handleTouchMoveDolly(event);
if (this.enablePan)
this.handleTouchMovePan(event);
});
__publicField(this, "handleTouchMoveDollyRotate", (event) => {
if (this.enableZoom)
this.handleTouchMoveDolly(event);
if (this.enableRotate)
this.handleTouchMoveRotate(event);
});
//
// event handlers - FSM: listen for events and reset state
//
__publicField(this, "onMouseDown", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
this.domElement.focus ? this.domElement.focus() : window.focus();
let mouseAction;
switch (event.button) {
case 0:
mouseAction = this.mouseButtons.LEFT;
break;
case 1:
mouseAction = this.mouseButtons.MIDDLE;
break;
case 2:
mouseAction = this.mouseButtons.RIGHT;
break;
default:
mouseAction = -1;
}
switch (mouseAction) {
case MOUSE.DOLLY:
if (this.enableZoom === false)
return;
this.handleMouseDownDolly(event);
this.state = STATE.DOLLY;
break;
case MOUSE.ROTATE:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (this.enablePan === false)
return;
this.handleMouseDownPan(event);
this.state = STATE.PAN;
} else {
if (this.enableRotate === false)
return;
this.handleMouseDownRotate(event);
this.state = STATE.ROTATE;
}
break;
case MOUSE.PAN:
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (this.enableRotate === false)
return;
this.handleMouseDownRotate(event);
this.state = STATE.ROTATE;
} else {
if (this.enablePan === false)
return;
this.handleMouseDownPan(event);
this.state = STATE.PAN;
}
break;
default:
this.state = STATE.NONE;
}
if (this.state !== STATE.NONE) {
document.addEventListener("mousemove", this.onMouseMove, false);
document.addEventListener("mouseup", this.onMouseUp, false);
this.dispatchEvent(this.startEvent);
}
});
__publicField(this, "onMouseMove", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (this.state) {
case STATE.ROTATE:
if (this.enableRotate === false)
return;
this.handleMouseMoveRotate(event);
break;
case STATE.DOLLY:
if (this.enableZoom === false)
return;
this.handleMouseMoveDolly(event);
break;
case STATE.PAN:
if (this.enablePan === false)
return;
this.handleMouseMovePan(event);
break;
}
});
__publicField(this, "onMouseUp", () => {
if (this.enabled === false)
return;
document.removeEventListener("mousemove", this.onMouseMove, false);
document.removeEventListener("mouseup", this.onMouseUp, false);
this.dispatchEvent(this.endEvent);
this.state = STATE.NONE;
});
__publicField(this, "onMouseWheel", (event) => {
if (this.enabled === false || this.enableZoom === false || this.state !== STATE.NONE && this.state !== STATE.ROTATE) {
return;
}
event.preventDefault();
this.dispatchEvent(this.startEvent);
this.handleMouseWheel(event);
this.dispatchEvent(this.endEvent);
});
__publicField(this, "onKeyDown", (event) => {
if (this.enabled === false || this.enableKeys === false || this.enablePan === false)
return;
this.handleKeyDown(event);
});
__publicField(this, "onTouchStart", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (event.touches.length) {
case 1:
switch (this.touches.ONE) {
case TOUCH.ROTATE:
if (this.enableRotate === false)
return;
this.handleTouchStartRotate(event);
this.state = STATE.TOUCH_ROTATE;
break;
case TOUCH.PAN:
if (this.enablePan === false)
return;
this.handleTouchStartPan(event);
this.state = STATE.TOUCH_PAN;
break;
default:
this.state = STATE.NONE;
}
break;
case 2:
switch (this.touches.TWO) {
case TOUCH.DOLLY_PAN:
if (this.enableZoom === false && this.enablePan === false)
return;
this.handleTouchStartDollyPan(event);
this.state = STATE.TOUCH_DOLLY_PAN;
break;
case TOUCH.DOLLY_ROTATE:
if (this.enableZoom === false && this.enableRotate === false)
return;
this.handleTouchStartDollyRotate(event);
this.state = STATE.TOUCH_DOLLY_ROTATE;
break;
default:
this.state = STATE.NONE;
}
break;
default:
this.state = STATE.NONE;
}
if (this.state !== STATE.NONE) {
this.dispatchEvent(this.startEvent);
}
});
__publicField(this, "onTouchMove", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
switch (this.state) {
case STATE.TOUCH_ROTATE:
if (this.enableRotate === false)
return;
this.handleTouchMoveRotate(event);
this.update();
break;
case STATE.TOUCH_PAN:
if (this.enablePan === false)
return;
this.handleTouchMovePan(event);
this.update();
break;
case STATE.TOUCH_DOLLY_PAN:
if (this.enableZoom === false && this.enablePan === false)
return;
this.handleTouchMoveDollyPan(event);
this.update();
break;
case STATE.TOUCH_DOLLY_ROTATE:
if (this.enableZoom === false && this.enableRotate === false)
return;
this.handleTouchMoveDollyRotate(event);
this.update();
break;
default:
this.state = STATE.NONE;
}
});
__publicField(this, "onTouchEnd", () => {
if (this.enabled === false)
return;
this.dispatchEvent(this.endEvent);
this.state = STATE.NONE;
});
__publicField(this, "onContextMenu", (event) => {
if (this.enabled === false)
return;
event.preventDefault();
});
if (domElement === void 0) {
console.warn('THREE.CameraControls: The second parameter "domElement" is now mandatory.');
}
if (domElement instanceof Document) {
console.error(
'THREE.CameraControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.'
);
}
this.object = object;
this.domElement = domElement;
this.mouseButtons = {
LEFT: MOUSE.ROTATE,
MIDDLE: MOUSE.DOLLY,
RIGHT: MOUSE.PAN
};
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.quaternion0 = this.object.quaternion.clone();
this.zoom0 = this.object.zoom;
this.quat = new Quaternion().setFromUnitVectors(this.object.up, new Vector3(0, 1, 0));
this.quatInverse = this.quat.clone().invert();
this.lastPosition = new Vector3();
this.lastQuaternion = new Quaternion();
this.domElement.addEventListener("contextmenu", this.onContextMenu, false);
this.domElement.addEventListener("mousedown", this.onMouseDown, false);
this.domElement.addEventListener("wheel", this.onMouseWheel, false);
this.domElement.addEventListener("touchstart", this.onTouchStart, false);
this.domElement.addEventListener("touchend", this.onTouchEnd, false);
this.domElement.addEventListener("touchmove", this.onTouchMove, false);
this.domElement.addEventListener("keydown", this.onKeyDown, false);
if (this.domElement.tabIndex === -1) {
this.domElement.tabIndex = 0;
}
this.object.lookAt(this.target);
this.update();
this.saveState();
}
handleMouseUp() {
}
handleTouchEnd() {
}
}
class OrbitControlsExp extends CameraControls {
constructor(object, domElement) {
super(object, domElement);
__publicField(this, "mouseButtons");
__publicField(this, "touches");
this.mouseButtons = {
LEFT: MOUSE.ROTATE,
RIGHT: MOUSE.PAN
};
this.touches = {
ONE: TOUCH.ROTATE,
TWO: TOUCH.DOLLY_PAN
};
}
}
class MapControlsExp extends CameraControls {
constructor(object, domElement) {
super(object, domElement);
__publicField(this, "mouseButtons");
__publicField(this, "touches");
this.mouseButtons = {
LEFT: MOUSE.PAN,
RIGHT: MOUSE.ROTATE
};
this.touches = {
ONE: TOUCH.PAN,
TWO: TOUCH.DOLLY_ROTATE
};
}
}
class TrackballControlsExp extends CameraControls {
constructor(object, domElement) {
super(object, domElement);
__publicField(this, "trackball");
__publicField(this, "screenSpacePanning");
__publicField(this, "autoRotate");
__publicField(this, "mouseButtons");
__publicField(this, "touches");
this.trackball = true;
this.screenSpacePanning = true;
this.autoRotate = false;
this.mouseButtons = {
LEFT: MOUSE.ROTATE,
RIGHT: MOUSE.PAN
};
this.touches = {
ONE: TOUCH.ROTATE,
TWO: TOUCH.DOLLY_PAN
};
}
}
export {
CameraControls,
MapControlsExp,
OrbitControlsExp,
STATE,
TrackballControlsExp
};
//# sourceMappingURL=CameraControls.js.map
File diff suppressed because one or more lines are too long