feat: dashcam photo mode with telemetry frame, lens drift and postcard capture

This commit is contained in:
2026-10-11 07:49:56 +03:00
parent d71b0ecfd4
commit 568b0802b4
29 changed files with 1472 additions and 7 deletions

View File

@@ -0,0 +1,57 @@
/**
* DASHCAM, the slot the DOM and the scene share (initial chunk, kept tiny).
* The DOM writes whether the dashcam is open, whether the lens may drift and
* the latest normalised pointer; the scene reads it inside its own frame and
* eases the lens itself (src/scene/world/dashcam-lens.ts). Nothing here
* schedules work.
*/
export interface DashcamFeed {
open: boolean;
/** Fine pointer on the high or medium tier: the lens follows the pointer. */
drift: boolean;
/** Pointer in [-1, 1], right and down positive. */
px: number;
py: number;
/** performance.now() of the last pointer move (the scene returns to centre after 3 s). */
movedAt: number;
}
const feed: DashcamFeed = { open: false, drift: false, px: 0, py: 0, movedAt: 0 };
export const readDashcam = (): Readonly<DashcamFeed> => feed;
export function setDashcamOpen(open: boolean, drift: boolean): void {
feed.open = open;
feed.drift = open && drift;
feed.px = 0;
feed.py = 0;
if (!open) capture = null;
}
export function setDashcamPointer(px: number, py: number, now: number): void {
feed.px = Math.max(-1, Math.min(1, px));
feed.py = Math.max(-1, Math.min(1, py));
feed.movedAt = now;
}
/**
* One queued capture. The scene calls it synchronously right after its final
* render pass with the WebGL canvas, the only moment the drawing buffer is
* valid (preserveDrawingBuffer is false).
*/
let capture: ((canvas: HTMLCanvasElement) => void) | null = null;
export function requestDashcamCapture(resolve: (canvas: HTMLCanvasElement) => void): void {
capture = resolve;
}
export function cancelDashcamCapture(): void {
capture = null;
}
/** The scene's side: take (and clear) the queued capture, if any. */
export function takeDashcamCapture(): ((canvas: HTMLCanvasElement) => void) | null {
const next = capture;
capture = null;
return next;
}