Lane A: grammar.js (shot/angle/focal/light/mark data), presets.js (bbox shot solver, light/mark appliers, DIRECT bar UI, NL box), stage video plates (VideoTexture plane/corner/dome, screen kind, syncVideos), dock video cards. Lane B: scenegod:direct → grouped-undo keys/cuts, 🗣 lip-sync from audio via /rhubarb, Cmd+wheel zoom / wheel scroll, audio trim, video clock-follow via nullable entityVideo seam. Lane C: POST /director (LLM proxy, server-side op validation vs vocab+scene, mock-tested), render.js awaits stage.syncVideos. Sync6 (orchestrator): VIDEO_EXTS in server tree/media types (video primary, img poster as thumb), stage.entityVideo accessor, syncVideos forces videoTex.needsUpdate (rVFC never fires in hidden tabs → black plates). Verified: 9 server groups + timeline + presets suites green; browser SYNC: one-click MCU framing lands camera+fov keys+cut (single undo), golden_hour relight keys, plate scrub-follow frame-exact, finalRender mp4 shows the Flow golden-hour street plate behind an animated character. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
58 lines
3.0 KiB
JavaScript
58 lines
3.0 KiB
JavaScript
// grammar.js — classic cinema vocabulary as PURE DATA (Lane A owns; every lane reads).
|
||
// No imports, no DOM, no three — safe under plain node. Presets/LLM ops both resolve here,
|
||
// so the button path and the /director path can never drift apart.
|
||
|
||
// Shot sizes: vertical span the framing should cover, as a fraction of subject height,
|
||
// @ where the frame centers on the body (fraction of subject height from the feet).
|
||
export const SHOTS = {
|
||
ECU: { span: 0.12, center: 0.93, label: 'extreme close-up' },
|
||
CU: { span: 0.25, center: 0.87, label: 'close-up' },
|
||
MCU: { span: 0.45, center: 0.75, label: 'medium close-up' },
|
||
MS: { span: 0.65, center: 0.65, label: 'medium shot' },
|
||
MWS: { span: 0.85, center: 0.55, label: 'medium wide' },
|
||
WS: { span: 1.2, center: 0.5, label: 'wide shot' },
|
||
EWS: { span: 2.5, center: 0.5, label: 'extreme wide' },
|
||
};
|
||
|
||
// Camera attitude relative to the aim point. elev = degrees above (+) / below (−) the
|
||
// aim; roll = dutch tilt in degrees; ots = over-the-shoulder of the OTHER subject.
|
||
export const ANGLES = {
|
||
eye: { elev: 0, roll: 0 },
|
||
low: { elev: -18, roll: 0 },
|
||
high: { elev: 22, roll: 0 },
|
||
dutch: { elev: 0, roll: 8 },
|
||
ots_L: { elev: 0, roll: 0, ots: 'L' },
|
||
ots_R: { elev: 0, roll: 0, ots: 'R' },
|
||
};
|
||
|
||
// Full-frame focal lengths (mm). Vertical fov = 2·atan(12/f) — 24mm-tall sensor.
|
||
export const FOCALS = [18, 24, 35, 50, 85];
|
||
|
||
// Lighting looks: key ("sun") color/intensity + boom direction (degrees), hemisphere
|
||
// ambient, and a background clear color. Values are what applyLight writes verbatim.
|
||
export const LIGHTS = {
|
||
day: { sun: { color: '#fff6e4', intensity: 3.0, elev: 55, azim: 35 },
|
||
ambient: { color: '#dfe9ff', intensity: 1.15 }, bg: '#8fb0d6' },
|
||
golden_hour: { sun: { color: '#ffb469', intensity: 2.6, elev: 9, azim: -55 },
|
||
ambient: { color: '#ffd9b0', intensity: 0.55 }, bg: '#d98a52' },
|
||
night: { sun: { color: '#7e93d6', intensity: 0.6, elev: 40, azim: 150 },
|
||
ambient: { color: '#31405e', intensity: 0.4 }, bg: '#0a0e1a' },
|
||
noir: { sun: { color: '#ffffff', intensity: 3.4, elev: 52, azim: 75 },
|
||
ambient: { color: '#1c1c24', intensity: 0.15 }, bg: '#08080a' },
|
||
horror: { sun: { color: '#b9d6a4', intensity: 1.7, elev: -30, azim: 10 }, // underlight
|
||
ambient: { color: '#25302b', intensity: 0.25 }, bg: '#05070a' },
|
||
neon: { sun: { color: '#ff4fd8', intensity: 1.9, elev: 25, azim: 120 },
|
||
ambient: { color: '#2de2e6', intensity: 0.9 }, bg: '#150420' },
|
||
overcast: { sun: { color: '#dfe4ea', intensity: 1.2, elev: 70, azim: 0 },
|
||
ambient: { color: '#c7cdd6', intensity: 1.4 }, bg: '#9aa3ad' },
|
||
};
|
||
|
||
// Blocking marks, stage-relative. pos marks move (keep current y); face marks rotate.
|
||
export const MARKS = {
|
||
center: { pos: [0, 0, 0] },
|
||
two_shot_L: { pos: [-0.7, 0, 0] },
|
||
two_shot_R: { pos: [0.7, 0, 0] },
|
||
face_camera: { face: 'camera' },
|
||
face_other: { face: 'other' },
|
||
};
|