Venues: song sky, ride roadside, room camera, filmstrip venue pin
- Shared sky dome (src/venues/sky.js): gradient backdrop from palette / section light / style texture, wired into chamber/stage/ride with fog matched to the dome mid colour — replaces clear-to-black - Ride roadside: houses, signs, trees, seeded viz billboard, all analytic scroll; popMul fade for crew, arrangement-gated roadside (no mid-section popping); parked idle creep + engine shake; analytic dash clock - Room camera: traverse glide + progress look sweep + per-section dolly, single-side room visits, one re-hang max; venue framing per archetype - Filmstrip venue selector (?venueSel=) with cache key; seed persisted to URL on reroll; gallery query plumbing
This commit is contained in:
@@ -88,6 +88,7 @@
|
||||
<div class="bar" id="bar">
|
||||
<span class="spinner"></span>
|
||||
<button id="rebuild">rebuild</button>
|
||||
<select id="venueSel" title="pin one venue in every row, or census"></select>
|
||||
<select id="sort">
|
||||
<option value="direction">sort: least direction first</option>
|
||||
<option value="drift">sort: least drift first</option>
|
||||
@@ -103,6 +104,7 @@
|
||||
|
||||
<script type="module">
|
||||
import { buildFilmstrip, songNames, STRIP, DEFAULT_EVERY, DEFAULT_DURATION } from '/src/checks/filmstrip.js';
|
||||
import { venues } from '/src/venues/registry.js';
|
||||
import { blit } from '/src/checks/blit.js';
|
||||
import { hashString } from '/src/engine/rng.js';
|
||||
import {
|
||||
@@ -115,6 +117,7 @@ const every = Number(params.get('every')) || DEFAULT_EVERY;
|
||||
const duration = Number(params.get('duration')) || DEFAULT_DURATION;
|
||||
const only = params.get('song') ? params.get('song').split(',') : null;
|
||||
const venueEnabled = params.get('venue') === '1';
|
||||
const venueSelParam = params.get('venueSel') || '';
|
||||
|
||||
document.getElementById('everyLabel').textContent = every;
|
||||
|
||||
@@ -122,9 +125,21 @@ const bar = document.getElementById('bar');
|
||||
const out = document.getElementById('out');
|
||||
const status = document.getElementById('status');
|
||||
const sortSel = document.getElementById('sort');
|
||||
const venueSel = document.getElementById('venueSel');
|
||||
const progress = document.querySelector('#progress i');
|
||||
const rebuildBtn = document.getElementById('rebuild');
|
||||
|
||||
venueSel.innerHTML = `<option value="">all venues (census)</option>` +
|
||||
venues.map((v) => `<option value="${v.name}">${v.name} (${v.archetype})</option>`).join('');
|
||||
if ([...venueSel.options].some((o) => o.value === venueSelParam)) venueSel.value = venueSelParam;
|
||||
venueSel.addEventListener('change', () => {
|
||||
const p = new URLSearchParams(location.search);
|
||||
if (venueSel.value) p.set('venueSel', venueSel.value);
|
||||
else p.delete('venueSel');
|
||||
history.replaceState(null, '', `${location.pathname}?${p}`);
|
||||
build();
|
||||
});
|
||||
|
||||
let rows = [];
|
||||
|
||||
// Read against the arcless reference the variety report prints: around zero is
|
||||
@@ -224,7 +239,8 @@ function summarise(built) {
|
||||
? rows.reduce((a, r) => a + (r.direction || 0), 0) / rows.length : 0;
|
||||
const meanAgit = rows.length
|
||||
? rows.reduce((a, r) => a + (r.agitation ?? 0), 0) / rows.length : 0;
|
||||
return `${rows.length} songs · every ${every}s of ${duration}s · ` +
|
||||
const venueNote = venueSel.value ? ` · venue ${venueSel.value}` : (venueEnabled ? ' · venues from census' : '');
|
||||
return `${rows.length} songs · every ${every}s of ${duration}s${venueNote} · ` +
|
||||
`mean direction ${meanDir.toFixed(2)} · ${flat} with no direction` +
|
||||
` · mean agit ${meanAgit.toFixed(2)} · ${agited} agitated (≥${AGIT_CEILING.toFixed(2)})${validatedNote}` +
|
||||
(built ? ` · built ${new Date(built).toLocaleString()}` : '');
|
||||
@@ -232,7 +248,7 @@ function summarise(built) {
|
||||
|
||||
// The cache key carries the sampling parameters as well as the source, so
|
||||
// changing `?every=` does not silently show you the previous spacing's pixels.
|
||||
const cacheKey = () => `filmstrip:${every}:${duration}:${only ? only.join(',') : 'all'}:v${venueEnabled ? 1 : 0}:${sourceFingerprint()}`;
|
||||
const cacheKey = () => `filmstrip:${every}:${duration}:${only ? only.join(',') : 'all'}:v${venueEnabled ? 1 : 0}:${venueSel.value || 'auto'}:${sourceFingerprint()}`;
|
||||
|
||||
async function build() {
|
||||
bar.classList.add('building');
|
||||
@@ -242,7 +258,7 @@ async function build() {
|
||||
|
||||
const total = (only || songNames()).length;
|
||||
const built = await buildFilmstrip({
|
||||
duration, every, names: only, venueEnabled,
|
||||
duration, every, names: only, venueEnabled, venueSel: venueSel.value || null,
|
||||
// Painted as they land, in bank order, rather than after the whole run.
|
||||
// A full build is a couple of minutes of GPU work and the interesting
|
||||
// failure — a strip whose frames could be shuffled — is visible in the
|
||||
|
||||
Reference in New Issue
Block a user