Continuity rule: discrete params hold per cue; add DESIGN.md + AGENTS.md
Actors and objects change only at camera cuts. int/bool/discrete params skip drift, lookahead and reactivity; discrete slowAxis steps on the section-held journey. Venues fade instead of toggling on interpolated popMul; roadside density is arrangement-only. DESIGN.md collects the project's design decisions; AGENTS.md points agents at it and the build-visualizer loop.
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { createLayer } from '../engine/Layer.js';
|
||||
import { Rng } from '../engine/rng.js';
|
||||
import { clampValue } from '../params/schema.js';
|
||||
import { clampValue, isDiscreteParam } from '../params/schema.js';
|
||||
import { paletteShiftAt } from './paletteArc.js';
|
||||
import { shiftPalette, lerpPalettes } from './palette.js';
|
||||
import { frameShot, neutralFraming } from './framing.js';
|
||||
import { planGaze, gazeAt } from './Camera.js';
|
||||
import { planVenueShots, venueShotAt, describeVenueShot } from './venueShots.js';
|
||||
import { storyStateAt, NEUTRAL_STATE } from './Story.js';
|
||||
import { storyStateAt, storyForSection, NEUTRAL_STATE } from './Story.js';
|
||||
import { subjectIndexOf, isGround } from './stack.js';
|
||||
import { groundPersonalityFrom } from '../scenes/surface.js';
|
||||
import { derivePalettePlan, directorByName } from './directors.js';
|
||||
@@ -383,6 +383,10 @@ export class ArcDriver {
|
||||
for (const [name, def] of Object.entries(spec.module.params || {})) {
|
||||
if (def.type === 'palette' || def.type === 'bool' || def.fixed) continue;
|
||||
if (def.noDrift || def.rate) continue; // see schema.js RATE_FLAG
|
||||
// Continuity rule (see schema.js isDiscreteParam): a drifting count
|
||||
// pops members mid-shot. Discrete params hold for the whole cue and
|
||||
// change only at cuts, via the per-section/variant sample.
|
||||
if (isDiscreteParam(def)) continue;
|
||||
const [lo, hi] = def.range || [0, 1];
|
||||
plan.push({
|
||||
name,
|
||||
@@ -517,10 +521,28 @@ export class ArcDriver {
|
||||
const p = Math.max(0, Math.min(1, time / duration));
|
||||
journey = p * p * (3 - 2 * p);
|
||||
}
|
||||
// Discrete params step their slow-axis travel at cuts instead of
|
||||
// sliding it: the section-held journey moves only at section
|
||||
// boundaries (which are always cuts), and without a story the cue's
|
||||
// own start frame is the step. Either way nothing pops mid-shot.
|
||||
// See params/schema.js isDiscreteParam.
|
||||
let journeyStepped = null;
|
||||
const steppedJourney = () => {
|
||||
if (journeyStepped !== null) return journeyStepped;
|
||||
if (this.look.story) {
|
||||
journeyStepped = storyForSection(this.look.story, cue.sectionIndex).journey;
|
||||
} else {
|
||||
const duration = Math.max(1e-6, this.track.duration);
|
||||
const pc = Math.max(0, Math.min(1, (cue.startFrame / this.track.fps) / duration));
|
||||
journeyStepped = pc * pc * (3 - 2 * pc);
|
||||
}
|
||||
return journeyStepped;
|
||||
};
|
||||
for (const item of this._slowAxisFor(spec.module)) {
|
||||
const base = out[item.name];
|
||||
if (typeof base !== 'number') continue;
|
||||
out[item.name] = clampValue(item.def, base + item.travel * (journey - 0.5));
|
||||
const j = isDiscreteParam(item.def) ? steppedJourney() : journey;
|
||||
out[item.name] = clampValue(item.def, base + item.travel * (j - 0.5));
|
||||
}
|
||||
|
||||
for (const item of this._driftPlan(cue.sectionIndex, cue.variant, slot)) {
|
||||
@@ -545,6 +567,7 @@ export class ArcDriver {
|
||||
const target = next.params;
|
||||
for (const [name, def] of Object.entries(spec.module.params || {})) {
|
||||
if (def.type === 'palette' || typeof out[name] !== 'number') continue;
|
||||
if (isDiscreteParam(def)) continue;
|
||||
if (typeof target[name] !== 'number') continue;
|
||||
out[name] = clampValue(def, out[name] + (target[name] - out[name]) * slope);
|
||||
}
|
||||
@@ -553,6 +576,7 @@ export class ArcDriver {
|
||||
// of their range so the build still reads as a build.
|
||||
for (const [name, def] of Object.entries(spec.module.params || {})) {
|
||||
if (typeof out[name] !== 'number') continue;
|
||||
if (isDiscreteParam(def)) continue;
|
||||
if (def.bias !== 'energy' && def.bias !== 'density') continue;
|
||||
const hi = (def.range || [0, 1])[1];
|
||||
out[name] = clampValue(def, out[name] + (hi - out[name]) * slope * 0.5);
|
||||
|
||||
Reference in New Issue
Block a user