@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
375 lines • 36.2 kB
JavaScript
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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