UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

375 lines 36.2 kB
import { TgdEvent } from "./../../event/index.js"; import { resolvePointerButtons } from "./../../input/index.js"; import { TgdMat3, TgdQuat, TgdVec3 } from "./../../math/index.js"; import { tgdCalcClamp } from "./../../math/index.js"; import { tgdActionCreateCameraInterpolation, tgdEasingFunctionOutQuad } from "./../../utils/index.js"; var GestureEnum; (function (GestureEnum) { GestureEnum[GestureEnum["None"] = 0] = "None"; GestureEnum[GestureEnum["Orbit"] = 1] = "Orbit"; GestureEnum[GestureEnum["Pan"] = 2] = "Pan"; })(GestureEnum || (GestureEnum = {})); export class TgdControllerCameraOrbit { constructor(context, { name, geo, zoom = 1, minZoom = 1e-3, maxZoom = Infinity, speedZoom = 1, speedOrbit = 1, speedPanning = 1, inertiaZoom = 0, inertiaOrbit = 0, inertiaPanning = 0, fixedTarget = false, debug = false, onZoomRequest = alwaysTrue, cameraInitialState, } = {}) { this.id = `TgdControllerCameraOrbit#${TgdControllerCameraOrbit.ID++}`; this.eventChange = new TgdEvent(); this.minZoom = 1e-3; this.maxZoom = Infinity; this.speedZoom = 1; this.speedOrbit = 1; this.speedPanning = 1; this.inertiaZoom = 0; this.inertiaOrbit = 0; this.inertiaPanning = 0; /** * If `true`, pannig will only act on `camera.shift`, * not on `camera.target`. */ this.fixedTarget = false; this.cameraInitialState = { distance: 10, orientation: new TgdQuat(), position: new TgdVec3(), spaceHeightAtTarget: 10, zoom: 1, }; /** * The camera will only move if `enabled === true`. */ this._enabled = true; this.animGestureInertia = null; /** * This is the space height at target for zoom == 1.0 * * @see resetZoom() */ this.spaceHeightAtTargetForZoom1 = 1; /** * It can be usefull to disable to orbit controller for some time * because an animation is going on on the camera, for instance. */ this.disabledUntil = 0; this.tmpQuat = new TgdQuat(); this.lastPointerEventTimestamp = 0; this._context = null; this.currentGesture = GestureEnum.None; this.handleMove = (event) => { this.lastPointerEventTimestamp = event.current.t; if (!this.enabled || this.animGestureInertia) return; this.actualMove(event); }; this.actualMove = (event) => { const dt = event.current.t - event.previous.t; if (dt <= 0) return; const { context } = this; const { keyboard } = context.inputs; if (event.altKey || event.current.fingersCount === 2) { this.currentGesture = GestureEnum.Pan; return this.handlePan(event); } this.currentGesture = GestureEnum.Orbit; if (this.geo) { const speed = keyboard.isDown("Shift") ? 0.2 : 2; const lngDelta = keyboard.isDown("x") ? 0 : speed * (event.previous.x - event.current.x); const latDelta = keyboard.isDown("y") ? 0 : speed * (event.previous.y - event.current.y); const lng = this.geo.lng + lngDelta; const lat = this.geo.lat + latDelta; this.orbitGeo(lat, lng); return; } if (keyboard.isDown("z")) return this.handleRotateAroundZ(event); this.orbit(event.current.x - event.previous.x, event.current.y - event.previous.y, event.shiftKey); }; this.handleMoveStart = () => { if (!this.enabled) return; const { animGestureInertia: animOrbit, context } = this; if (animOrbit) { context.animCancel(animOrbit); this.animGestureInertia = null; } }; this.handleMoveEnd = (event) => { if (!this.enabled) return; const { context, inertiaOrbit, inertiaPanning, currentGesture } = this; if (this.animGestureInertia) context.animCancel(this.animGestureInertia); if (currentGesture === GestureEnum.Orbit && inertiaOrbit > 0) { const inverseDeltaTime = 1e-3 / (event.current.t - event.previous.t); const speedX = inverseDeltaTime * (event.current.x - event.previous.x); const speedY = inverseDeltaTime * (event.current.y - event.previous.y); const currentEvent = structuredClone(event); currentEvent.current.t = Date.now(); currentEvent.buttons = 1; currentEvent.altKey = false; this.animGestureInertia = { duration: inertiaOrbit * 1e-3, action: (alpha) => { currentEvent.previous.t = currentEvent.current.t; currentEvent.previous.x = currentEvent.current.x; currentEvent.previous.y = currentEvent.current.y; currentEvent.previous.fingersCount = currentEvent.current.fingersCount; currentEvent.current.t = Date.now(); const deltaTime = currentEvent.current.t - currentEvent.previous.t; const strength = 1 - alpha; const factor = strength * deltaTime; currentEvent.current.x += factor * speedX; currentEvent.current.y += factor * speedY; this.actualMove(currentEvent); }, easingFunction: tgdEasingFunctionOutQuad, }; context.animSchedule(this.animGestureInertia); } if (currentGesture === GestureEnum.Pan && inertiaPanning > 0) { const inverseDeltaTime = 1e-3 / (event.current.t - event.previous.t); const speedX = inverseDeltaTime * (event.current.x - event.previous.x); const speedY = inverseDeltaTime * (event.current.y - event.previous.y); const currentEvent = structuredClone(event); currentEvent.current.t = Date.now(); currentEvent.buttons = 2; currentEvent.altKey = true; this.animGestureInertia = { duration: inertiaPanning * 1e-3, action: (alpha) => { currentEvent.previous.t = currentEvent.current.t; currentEvent.previous.x = currentEvent.current.x; currentEvent.previous.y = currentEvent.current.y; currentEvent.previous.fingersCount = currentEvent.current.fingersCount; currentEvent.current.t = Date.now(); const deltaTime = currentEvent.current.t - currentEvent.previous.t; const strength = 1 - alpha; const factor = strength * deltaTime; currentEvent.current.x += factor * speedX; currentEvent.current.y += factor * speedY; this.actualMove(currentEvent); }, easingFunction: tgdEasingFunctionOutQuad, }; context.animSchedule(this.animGestureInertia); } this.currentGesture = GestureEnum.None; }; this.handleZoom = (event) => { if (this.lastPointerEventTimestamp > 0 && this.enabled && this.speedZoom > 0) { // Msec since last mouse event const time = 16e-3; // We assume 60 FPS let speed = this.speedZoom * time; if (this.context.inputs.keyboard.isDown("Shift")) speed *= 0.1; else if (this.context.inputs.keyboard.isDown("Control")) speed *= 10; const factor = 1 + speed; const zoom = tgdCalcClamp(this.zoom * (event.direction < 0 ? factor : 1 / factor), this.minZoom, this.maxZoom); if (zoom !== this.zoom && this.onZoomRequest({ ...resolvePointerButtons(event), altKey: event.altKey, ctrlKey: event.ctrlKey, metaKey: event.metaKey, shiftKey: event.shiftKey, x: event.current.x, y: event.current.y, zoom, })) { this.zoom = zoom; this.fireZoomChange(); } event.preventDefault(); } this.lastPointerEventTimestamp = event.current.t; }; this.handleDebug = (event) => { if (event.key === "?") { this.context.camera.debug(this.name); console.debug(this.context.camera.toCode()); } }; this.name = name ?? this.id; this.context = context; this.geo = undefined; if (geo) { this.geo = { lat: 0, lng: 0, minLat: -Math.PI / 2, maxLat: +Math.PI / 2, minLng: -Number.MAX_VALUE, maxLng: +Number.MAX_VALUE, ...geo, }; } this.debug = debug; this.cameraInitialState = { ...context.camera.getCurrentState(), ...cameraInitialState, }; const { inputs } = context; inputs.pointer.eventMoveStart.addListener(this.handleMoveStart, -1); inputs.pointer.eventMoveEnd.addListener(this.handleMoveEnd, -1); inputs.pointer.eventMove.addListener(this.handleMove, -1); inputs.pointer.eventZoom.addListener(this.handleZoom, -1); this.speedOrbit = speedOrbit; this.speedZoom = speedZoom; this.speedPanning = speedPanning; this.inertiaOrbit = inertiaOrbit; this.inertiaZoom = inertiaZoom; this.inertiaPanning = inertiaPanning; this.fixedTarget = fixedTarget; this.minZoom = minZoom; this.maxZoom = maxZoom; this.onZoomRequest = onZoomRequest; if (this.geo) this.orbitGeo(this.geo.lat, this.geo.lng); globalThis.setTimeout(() => context.paint()); this.zoom = zoom; } get context() { return this._context; } set context(context) { if (this._context) { this._context.inputs.keyboard.eventKeyPress.removeListener(this.handleDebug); } this._context = context; if (this.debug) { context.inputs.keyboard.eventKeyPress.addListener(this.handleDebug); } } get zoom() { return this.context.camera.zoom; } set zoom(value) { const newZoom = tgdCalcClamp(value, this.minZoom, this.maxZoom); if (newZoom === this.context.camera.zoom) return; this.context.camera.zoom = newZoom; } get enabled() { return this.context.time > this.disabledUntil && this._enabled; } set enabled(value) { this._enabled = value; } reset(animDuration, { easingFunction, onEnd, onAction, delay = 0, } = {}) { const { context } = this; this.disableForSomeTime(animDuration); const action = tgdActionCreateCameraInterpolation(context.camera, this.cameraInitialState); context.animSchedule({ action: (t) => { action(t); onAction?.(t); }, duration: animDuration, easingFunction, onEnd, delay, }); } disableForSomeTime(delayInMsec) { this.disabledUntil = Math.max(this.disabledUntil, this.context.time + delayInMsec); } detach() { const { inputs } = this.context; inputs.keyboard.eventKeyPress.removeListener(this.handleDebug); inputs.pointer.eventMoveStart.removeListener(this.handleMoveStart); inputs.pointer.eventMoveEnd.removeListener(this.handleMoveEnd); inputs.pointer.eventMove.removeListener(this.handleMove); inputs.pointer.eventZoom.removeListener(this.handleZoom); this.eventChange.removeAllListeners(); } orbit(deltaX, deltaY, slowDown) { const { context } = this; const { camera } = context; const { keyboard } = context.inputs; const speed = 3 * (slowDown ? 0.1 : 1) * this.speedOrbit; const dx = deltaX * speed; const dy = deltaY * speed; if (!keyboard.isDown("x")) camera.transfo.orbitAroundY(dx); if (!keyboard.isDown("y")) camera.transfo.orbitAroundX(-dy); this.fireOrbitChange(); } /** * Set the camera orientation from latitude/longitude * @param lat Expressed in radians * @param lng Expressed in radians */ orbitGeo(lat, lng) { const { geo } = this; if (!geo) return; lat = tgdCalcClamp(lat, geo.minLat, geo.maxLat); geo.lat = lat; lng = tgdCalcClamp(lng, geo.minLng, geo.maxLng); geo.lng = lng; const { orientation } = this.cameraInitialState; const vecZ = makeGeoVec3(lat, lng); const vecY = makeGeoVec3(lat + Math.PI / 2, lng); const vecX = new TgdVec3(vecY).cross(vecZ); const mat = new TgdMat3(); orientation.toMatrix(mat); const final = new TgdMat3(vecX, vecY, vecZ); final.multiply(mat); this.tmpQuat.fromMatrix(final); this.context.camera.transfo.orientation = this.tmpQuat; this.fireOrbitChange(); } handlePan(event) { const { fixedTarget, speedPanning, context } = this; const { camera } = context; const inverseZoom = 1 / camera.zoom; const panSpeed = 0.5 * speedPanning * inverseZoom; const dx = (event.current.x - event.previous.x) * panSpeed * camera.spaceWidthAtTarget; const dy = (event.current.y - event.previous.y) * panSpeed * camera.spaceHeightAtTarget; if (fixedTarget) { // camera.moveShift(-dx, -dy, 0) } else { camera.transfo.moveAlongAxes(-dx, -dy, 0); } this.fireOrbitChange(); } handleRotateAroundZ(event) { const { camera } = this.context; const x1 = event.previous.x; const y1 = event.previous.y; if (Math.abs(x1) + Math.abs(y1) === 0) return; const x2 = event.current.x; const y2 = event.current.y; if (Math.abs(x2) + Math.abs(y2) === 0) return; const x = x1 * x2 + y1 * y2; const y = x1 * y2 - y1 * x2; const ang = Math.atan2(y, x) * this.speedOrbit; camera.transfo.orbitAroundZ(ang); this.fireOrbitChange(); } fireOrbitChange() { this.context.paint(); this.eventChange.dispatch(this.context.camera); } fireZoomChange() { this.context.paint(); this.eventChange.dispatch(this.context.camera); } } TgdControllerCameraOrbit.ID = 1; /** * Default function for `onZoomRequest`. */ const alwaysTrue = () => true; function makeGeoVec3(lat, lng) { const radius = Math.cos(lat); const y = Math.sin(lat); const z = radius * Math.cos(lng); const x = radius * Math.sin(lng); return new TgdVec3(x, y, z); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JiaXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29udHJvbGxlci9jYW1lcmEvb3JiaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNyQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDbEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFHeEMsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sWUFBWSxDQUFBO0FBMEZ6RixJQUFLLFdBSUo7QUFKRCxXQUFLLFdBQVc7SUFDWiw2Q0FBUSxDQUFBO0lBQ1IsK0NBQVMsQ0FBQTtJQUNULDJDQUFPLENBQUE7QUFDWCxDQUFDLEVBSkksV0FBVyxLQUFYLFdBQVcsUUFJZjtBQUVELE1BQU0sT0FBTyx3QkFBd0I7SUFvRWpDLFlBQ0ksT0FBbUIsRUFDbkIsRUFDSSxJQUFJLEVBQ0osR0FBRyxFQUNILElBQUksR0FBRyxDQUFDLEVBQ1IsT0FBTyxHQUFHLElBQUksRUFDZCxPQUFPLEdBQUcsUUFBUSxFQUNsQixTQUFTLEdBQUcsQ0FBQyxFQUNiLFVBQVUsR0FBRyxDQUFDLEVBQ2QsWUFBWSxHQUFHLENBQUMsRUFDaEIsV0FBVyxHQUFHLENBQUMsRUFDZixZQUFZLEdBQUcsQ0FBQyxFQUNoQixjQUFjLEdBQUcsQ0FBQyxFQUNsQixXQUFXLEdBQUcsS0FBSyxFQUNuQixLQUFLLEdBQUcsS0FBSyxFQUNiLGFBQWEsR0FBRyxVQUFVLEVBQzFCLGtCQUFrQixNQUN3QixFQUFFO1FBbEZwQyxPQUFFLEdBQUcsNEJBQTRCLHdCQUF3QixDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUE7UUFDaEUsZ0JBQVcsR0FBRyxJQUFJLFFBQVEsRUFB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