feat: sign interlude, window plate and a two-button control bay
The sign closes in over the road on a gantry truss, arcs into a wider window and hands off to a flat 2D plate that mirrors its face; content steps aside for the interlude and rises after. The bay keeps sound and settings; volume and Pause motion move into the settings popover.
This commit is contained in:
@@ -154,6 +154,7 @@ export async function createProceduralSceneGeneration(
|
||||
car.group,
|
||||
speedWake.group,
|
||||
sign.group,
|
||||
sign.truss,
|
||||
);
|
||||
|
||||
const postProcessor = quality.postEffects
|
||||
@@ -192,6 +193,8 @@ export async function createProceduralSceneGeneration(
|
||||
// The outro mirrors the intro: on arrival the camera cranes back up toward
|
||||
// the sun on a long lens. Leaving the destination reverses it, faster.
|
||||
let outroProgress = 0;
|
||||
let interludeOn = false;
|
||||
let riseUntil = 0;
|
||||
let gantryState = '';
|
||||
|
||||
const resize = (): void => {
|
||||
@@ -373,7 +376,8 @@ export async function createProceduralSceneGeneration(
|
||||
car.group.position,
|
||||
width < 1100 || height < 620 ? 2.32 : 2.78,
|
||||
);
|
||||
sign.update(snapshot.sign, now);
|
||||
sign.setResting(snapshot.activeSectionId);
|
||||
sign.update(snapshot.sign, now, snapshot.driveSpeed);
|
||||
atmosphere.update(
|
||||
driveDistance,
|
||||
visualSpeed,
|
||||
@@ -568,6 +572,18 @@ export async function createProceduralSceneGeneration(
|
||||
gantryState = gantry;
|
||||
document.documentElement.dataset.gantry = gantry;
|
||||
}
|
||||
// The interlude: the reading plates step aside while the sign has the
|
||||
// road to itself (CSS keys off this attribute).
|
||||
// 'on' while the sign approaches, then 'rise' while the plates return.
|
||||
const interlude = sign.interlude();
|
||||
if (interlude !== interludeOn) {
|
||||
interludeOn = interlude;
|
||||
riseUntil = interlude ? 0 : now + INTERLUDE_RISE_MS;
|
||||
document.documentElement.dataset.interlude = interlude ? 'on' : 'rise';
|
||||
} else if (riseUntil > 0 && now > riseUntil) {
|
||||
riseUntil = 0;
|
||||
delete document.documentElement.dataset.interlude;
|
||||
}
|
||||
if (TEST_BUILD && snapshot.sign !== null) {
|
||||
const presentation = sign.inspect(camera, width, height);
|
||||
if (presentation !== null) {
|
||||
@@ -603,6 +619,7 @@ export async function createProceduralSceneGeneration(
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
delete document.documentElement.dataset.gantry;
|
||||
delete document.documentElement.dataset.interlude;
|
||||
// Quality changes reuse the canvas context. Leave texture upload flags at
|
||||
// defaults before the next renderer creates its empty array textures.
|
||||
const gl = renderer.getContext();
|
||||
@@ -617,6 +634,8 @@ const INTRO_SECONDS = 4.2;
|
||||
const OUTRO_SECONDS = 5.5;
|
||||
const OUTRO_RETURN_SECONDS = 1.6;
|
||||
const OUTRO_REACH = 0.62;
|
||||
/** Plates rise back over 720 ms with up to three 90 ms staggers. */
|
||||
const INTERLUDE_RISE_MS = 1100;
|
||||
|
||||
function easeInOutCubic(t: number): number {
|
||||
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
||||
|
||||
Reference in New Issue
Block a user