feat: add contextual layer inspector

This commit is contained in:
syntaxbullet
2026-07-11 12:07:36 +02:00
parent bef2fb3051
commit 4d7358af4b
14 changed files with 405 additions and 42 deletions

33
renderer/rotated-rect.ts Normal file
View File

@@ -0,0 +1,33 @@
import type { ScreenRect } from "./types";
export type ScreenPoint = { x: number; y: number };
/** Returns corners in northwest, northeast, southwest, southeast order. */
export function rotatedRectCorners(rect: ScreenRect, rotation: number): [ScreenPoint, ScreenPoint, ScreenPoint, ScreenPoint] {
if (!Number.isFinite(rotation)) rotation = 0;
const center = { x: rect.x + rect.w / 2, y: rect.y + rect.h / 2 };
const cosine = Math.cos(rotation);
const sine = Math.sin(rotation);
const rotate = (point: ScreenPoint): ScreenPoint => {
const x = point.x - center.x;
const y = point.y - center.y;
return { x: center.x + x * cosine - y * sine, y: center.y + x * sine + y * cosine };
};
return [
rotate({ x: rect.x, y: rect.y }),
rotate({ x: rect.x + rect.w, y: rect.y }),
rotate({ x: rect.x, y: rect.y + rect.h }),
rotate({ x: rect.x + rect.w, y: rect.y + rect.h }),
];
}
/** Axis-aligned screen bounds used to constrain WebGL scissoring around a rotated quad. */
export function rotatedRectBounds(rect: ScreenRect, rotation: number): ScreenRect {
if (rotation === 0) return rect;
const points = rotatedRectCorners(rect, rotation);
const xs = points.map((point) => point.x);
const ys = points.map((point) => point.y);
const x = Math.min(...xs);
const y = Math.min(...ys);
return { x, y, w: Math.max(...xs) - x, h: Math.max(...ys) - y };
}