UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

189 lines 15.6 kB
/* eslint-disable unicorn/prevent-abbreviations */ import { TgdCameraPerspective } from "./../../camera/index.js"; import { TgdContext } from "./../../context/index.js"; import { TgdControllerCameraOrbit } from "./../../controller/index.js"; import { TgdEvent } from "./../../event/index.js"; import { TgdQuat, TgdMat3, TgdVec3 } from "./../../math/index.js"; import { TgdPainterClear, TgdPainterDepth, TgdPainterLogic } from "./../../painter/index.js"; import { TipsPainter } from "./painter/tips.js"; /** * The Gizmo displays the orientation of an attached camera. * You can click one of the axis to force the camera to face it. */ export class TgdCanvasGizmo { constructor(options = {}) { this.options = options; /** * The user clicked a tip, so we dispatch the target orientation. */ this.eventTipClick = new TgdEvent(); this._canvas = null; this.context = null; this.contextExternal = null; this.cameraInternal = new TgdCameraPerspective({ fovy: Math.PI / 3, near: 0.01, far: 10, transfo: { distance: 2.7 }, }); this.orbiter = null; this.tipsPainter = null; this.handleExternalPaint = () => { var _a; (_a = this.context) === null || _a === void 0 ? void 0 : _a.paint(); }; this.handleInternalToExternal = (internalCamera) => { const { contextExternal } = this; if (contextExternal === null || contextExternal === void 0 ? void 0 : contextExternal.camera) { contextExternal.camera.transfo.orientation = internalCamera.transfo.orientation; contextExternal.paint(); } }; this.handleTap = (event) => { var _a; const camera = (_a = this.context) === null || _a === void 0 ? void 0 : _a.camera; if (!camera) return; const { origin, direction } = camera.castRay(event.x, event.y); const maxDistance = 1; let bestDistance = maxDistance; let bestTip = TIPS[0]; for (const tip of TIPS) { const distance = tip.distanceToLineSquared(origin, direction); if (distance < bestDistance) { bestDistance = distance; bestTip = tip; } } if (bestDistance < maxDistance) { const axisX = new TgdVec3(); const axisY = new TgdVec3(); const axisZ = bestTip; axisX.from(this.findAxisX()); if (axisX.isClose(axisZ)) { axisY.from(this.findAxisY()); axisX.from(axisY).cross(axisZ); } else { axisY.from(axisZ).cross(axisX); } const quat = new TgdQuat().fromAxes(axisX, axisY, axisZ); if (quat.isEqual(camera.transfo.orientation)) { quat.rotateAroundY(Math.PI); } this.eventTipClick.dispatch({ from: camera.transfo.orientation, to: quat, }); } }; if (options.canvas) this.canvas = options.canvas; } /** * Attach the camera we want to track and control. */ attachContext(context) { this.detach(); this.contextExternal = context; this.attach(); } detach() { if (!this.contextExternal) return; this.contextExternal.eventPaint.removeListener(this.handleExternalPaint); this.contextExternal = null; } attach() { var _a, _b; (_a = this.contextExternal) === null || _a === void 0 ? void 0 : _a.eventPaint.addListener(this.handleExternalPaint); (_b = this.context) === null || _b === void 0 ? void 0 : _b.paint(); } get canvas() { return this._canvas; } set canvas(canvas) { var _a; if (canvas === this._canvas) return; this._canvas = canvas; if (this.context) { this.context.inputs.pointer.eventTap.removeListener(this.handleTap); this.context.destroy(); this.context = null; const { orbiter } = this; if (orbiter) { orbiter.detach(); orbiter.eventChange.removeListener(this.handleInternalToExternal); } } (_a = this.tipsPainter) === null || _a === void 0 ? void 0 : _a.delete(); if (!canvas) return; const context = new TgdContext(canvas, Object.assign({ alpha: true, depth: true, antialias: true, name: "GizmoCanvas" }, this.options)); context.inputs.pointer.eventTap.addListener(this.handleTap); this.context = context; context.camera = this.cameraInternal; this.orbiter = new TgdControllerCameraOrbit(context, { speedPanning: 0, speedZoom: 0, }); this.orbiter.eventChange.addListener(this.handleInternalToExternal); const painter = new TipsPainter(context); this.tipsPainter = painter; context.add(new TgdPainterLogic(() => { var _a, _b; const srcTransfo = (_a = this.contextExternal) === null || _a === void 0 ? void 0 : _a.camera.transfo; if (!srcTransfo) return; const dstTransfo = (_b = this.context) === null || _b === void 0 ? void 0 : _b.camera.transfo; if (!dstTransfo) return; dstTransfo.orientation = srcTransfo.orientation; }), new TgdPainterClear(context, { color: [0, 0, 0, 0], depth: 1, }), new TgdPainterDepth(context, { enabled: true }), painter); context.paint(); } findAxisX() { let bestScore = 0; let bestTip = TIPS[0]; const vec = new TgdVec3(); const mat = new TgdMat3(); mat.fromQuat(this.cameraInternal.transfo.orientation).transpose(); for (const tip of TIPS) { vec.from(tip).applyMatrix(mat); if (vec.x > bestScore) { bestScore = vec.x; bestTip = tip; } } return bestTip; } findAxisY() { let bestScore = 0; let bestTip = TIPS[0]; const vec = new TgdVec3(); const mat = new TgdMat3(); mat.fromQuat(this.cameraInternal.transfo.orientation).transpose(); for (const tip of TIPS) { vec.from(tip).applyMatrix(mat); if (vec.y > bestScore) { bestScore = vec.y; bestTip = tip; } } return bestTip; } } const TIPS = [ new TgdVec3(1, 0, 0), new TgdVec3(0, 1, 0), new TgdVec3(0, 0, 1), new TgdVec3(-1, 0, 0), new TgdVec3(0, -1, 0), new TgdVec3(0, 0, -1), ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l6bW8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2FudmFzL2dpem1vL2dpem1vLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGtEQUFrRDtBQUNsRCxPQUFPLEVBQWEsb0JBQW9CLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDN0QsT0FBTyxFQUFFLFVBQVUsRUFBcUIsTUFBTSxjQUFjLENBQUE7QUFDNUQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDMUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNyQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBRWhGLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQU01Qzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sY0FBYztJQXFCdkIsWUFBNkIsVUFBaUMsRUFBRTtRQUFuQyxZQUFPLEdBQVAsT0FBTyxDQUE0QjtRQXBCaEU7O1dBRUc7UUFDSSxrQkFBYSxHQUFHLElBQUksUUFBUSxFQUcvQixDQUFBO1FBRUksWUFBTyxHQUE2QixJQUFJLENBQUE7UUFDeEMsWUFBTyxHQUFzQixJQUFJLENBQUE7UUFDakMsb0JBQWUsR0FBc0IsSUFBSSxDQUFBO1FBQ2hDLG1CQUFjLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQztZQUN2RCxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDO1lBQ2pCLElBQUksRUFBRSxJQUFJO1lBQ1YsR0FBRyxFQUFFLEVBQUU7WUFDUCxPQUFPLEVBQUUsRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFO1NBQzdCLENBQUMsQ0FBQTtRQUNNLFlBQU8sR0FBb0MsSUFBSSxDQUFBO1FBQy9DLGdCQUFXLEdBQXVCLElB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