Camera view frame, viewport clipping, overlay layer for editor symbols
- Camera assets get width/height properties; play mode renders only the camera frame (letterboxed, masked, culled) and nothing without a camera - Remove demo arrow-key/camera-follow systems from play mode - Clip world and gizmos to the viewport (selection frame no longer leaks over the left panel) - Blur focused widget on pointerdown outside it so inspector edits commit before selection changes - Separate objects/overlay layers so camera symbols always render on top - Add tools/seed-demo.mjs for reproducible E2E runs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
5a46124454
commit
aaa8154adf
11 files changed
+307
-142
No files matched your search
@@ -18,7 +18,11 @@ export type PropertySchema = readonly PropertyDef[];
|
||||
/** Property schema per asset type. Position is deliberately absent: it belongs to scene objects. */
|
||||
export const ASSET_SCHEMAS: Record<AssetType, PropertySchema> = {
|
||||
scene: [{ key: 'backgroundColor', label: 'Background', kind: 'color', default: 0x2a2d34 }],
|
||||
camera: [{ key: 'zoom', label: 'Zoom', kind: 'number', default: 1, min: 0.1, max: 10, step: 0.1 }],
|
||||
camera: [
|
||||
{ key: 'width', label: 'View width', kind: 'number', default: 640, min: 16, step: 1 },
|
||||
{ key: 'height', label: 'View height', kind: 'number', default: 360, min: 16, step: 1 },
|
||||
{ key: 'zoom', label: 'Zoom', kind: 'number', default: 1, min: 0.1, max: 10, step: 0.1 },
|
||||
],
|
||||
sprite: [
|
||||
{ key: 'width', label: 'Width', kind: 'number', default: 100, min: 1, step: 1 },
|
||||
{ key: 'height', label: 'Height', kind: 'number', default: 100, min: 1, step: 1 },
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { PropertyBag } from '../model/Properties';
|
||||
import { defaultsFor } from './PropertySchema';
|
||||
|
||||
/** Axis-aligned rectangle in world units. */
|
||||
export interface WorldRect {
|
||||
left: number;
|
||||
top: number;
|
||||
right: number;
|
||||
bottom: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the world region a camera shows, in world units: its view size divided by its
|
||||
* zoom. This is the frame drawn in edit mode and the only region rendered in play mode.
|
||||
*/
|
||||
export function cameraFrame(props: PropertyBag): { w: number; h: number } {
|
||||
const d = defaultsFor('camera');
|
||||
const zoom = Math.max(0.01, Number(props.zoom ?? d.zoom));
|
||||
return { w: Number(props.width ?? d.width) / zoom, h: Number(props.height ?? d.height) / zoom };
|
||||
}
|
||||
|
||||
export function rectAround(cx: number, cy: number, w: number, h: number): WorldRect {
|
||||
return { left: cx - w / 2, top: cy - h / 2, right: cx + w / 2, bottom: cy + h / 2 };
|
||||
}
|
||||
|
||||
export function rectsIntersect(a: WorldRect, b: WorldRect): boolean {
|
||||
return a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top;
|
||||
}
|
||||
Reference in new issue
Block a user