Files
music-video-gen/flow-state/src/venues/pin.js
T
Dejvino 6c7e314a3e Clickable previews: every still links to its exact app frame
New shared component src/ui/preview.js (appFrameUrl + previewLink): song + seed + frame + venue/venueSel deep-links. App honors ?frame= (warm seek on bank-song load) and ?venueSel= via shared pinVenueShell helper (src/venues/pin.js), which filmstrip and venue-gallery now also use. Filmstrip figures and venue-gallery cards wrap canvases; gallery cells stay unlinked (isolated scene probes, not reproducible in-app).
2026-09-20 17:08:03 +02:00

45 lines
1.9 KiB
JavaScript

// Pin one venue shell onto a look.
//
// The same shell-swap in three places: the filmstrip's `venueSel`, the venue
// gallery's venue picker, and the app's `?venueSel=`. Only the shell is
// forced — module/name/archetype. The VenueSpec population stays the census
// one (counts overlap between archetypes), so this is what makes a pinned
// preview the exact image the app reproduces, rather than a nearby one.
import { venues } from './registry.js';
/**
* Force `look.venue` to render as the named venue.
*
* @param {object} look LookSpec from generateLook (mutated in place)
* @param {string} name venue name, e.g. 'Ride'
* @param {object} [opts]
* @param {number} [opts.seed] seed for a from-scratch spec (default 1)
* @param {boolean} [opts.buildIfMissing] build a neutral spec when the
* census produced no venue at all (the venue gallery does; the filmstrip
* keeps the no-venue video instead)
* @returns {boolean} true when a venue is pinned afterwards
*/
export function pinVenueShell(look, name, { seed = 1, buildIfMissing = false } = {}) {
if (!name || !look) return false;
const picked = venues.find((v) => v.name === name);
if (!picked) throw new Error(`unknown venue "${name}"`);
if (!look.venue) {
if (!buildIfMissing) return false;
look.venue = {
archetype: picked.archetype, name: picked.name, seed,
shell: { kind: picked.archetype }, projection: { kind: 'screen' },
population: { kind: 'scatter', count: 5, spread: 0.7, jitter: 0.25 },
paletteMap: [0, 1, 2, 3],
perSection: (look.sections || []).map(
() => ({ light: 0.7, fog: 0.35, popMul: 0.65, reachMul: 0.85 })),
venue: true, readsDepth: false, module: picked,
};
return true;
}
look.venue.module = picked;
look.venue.name = picked.name;
look.venue.archetype = picked.archetype;
return true;
}