fix(awareness): bound the range ring pulses so a parked view goes quiet

Review follow-up for the sonar pulses.

Bounded repaint: the pulses used to ask for a frame every 80 ms from a
setInterval for as long as a subject was shown, so a parked view
repainted at 12.5 fps indefinitely. They now run for 9 s (three ring
flashes) after a selection or a camera move, fading in and out over
1.2 s, then rest: the ring stands on screen at full strength, the pulse
lines and gradient disc are hidden, echoes stop, and nothing asks for
frames. A moving subject does not wake them, since a flying subject
moves on every refresh. The lifecycle's existing camera pose signature
wakes them.

No beat with the Cyber sonar: the setInterval is replaced by a
postRender-armed setTimeout on CYBER_SONAR_RENDER_INTERVAL_MS, as in
cyberSonarScene. Every drawn frame, whoever asked for it, re-arms the
request 80 ms later, so requests never land inside the detection
lane's 80 ms gate.

Reduced motion mid-session: a change listener on the media query
rebuilds the visual, and the same-subject refresh path rebuilds when
the preference no longer matches. The listener is removed in
clearVisual.

Readable edge: restOpacity goes from 0 to 0.4, so the 250 km ring stays
visible between flashes, in screenshots and for low-vision viewers.

The echo field takes an optional level so echoes rest with the pulses.
CURRENT-STATE and the changelog fragment describe the bounded run and
the dimmed ring.

Tests: render requests stop after the bound and stay stopped for a
minute; a camera move seen by the lifecycle wakes them for another
bounded run; a foreign frame postpones the next request to 80 ms after
it; reduced motion flipped by event and by a later refresh; the ring
never drops below restOpacity; echoes scale with the level; the level
fades in, holds, fades out and keeps its value when woken.
This commit is contained in:
Manjunath committed 2026-11-03 19:17:03 +05:30
1 parent 20770e52a9
commit 0c025987ef
8 files changed
+491 -86

No files matched your search

+13 -6
View File
@@ -15,6 +15,8 @@ import * as Cesium from 'cesium';
* @property {number} radiusM Range the pulses grow to.
* @property {{count: number, periodMs: number, startFraction: number}} pulse
* @property {{fadeMs: number, layerIds: string[]}} echo
* @property {(nowMs: number) => number} [level] How far the pulses are
* switched on, 0 to 1; echoes scale with it, so they rest with the pulses.
*/
/** @type {AwarenessEchoField|null} */
@@ -94,11 +96,16 @@ export function awarenessEchoAt(layerId, position, nowMs) {
groundScratch,
);
if (!ground) return 0;
return awarenessEchoStrength(
nowMs,
Cesium.Cartesian3.distance(field.center, ground),
field.radiusM,
field.pulse,
field.echo,
const level = field.level?.(nowMs) ?? 1;
if (!(level > 0)) return 0;
return (
level *
awarenessEchoStrength(
nowMs,
Cesium.Cartesian3.distance(field.center, ground),
field.radiusM,
field.pulse,
field.echo,
)
);
}