fix(awareness): stop the subject echoing itself and cover the echo wiring

Remaining review follow-ups for the sonar pulses.

No self-echo: pulses are born 5 km out (startFraction of the radius),
but contacts nearer than that, the subject included, still lit on every
pulse birth. They now never echo. Just past the birth ring, an echo is
scaled with the front's own fade-in, so a bracket no longer flashes
before a visible front reaches it. The ring flash at the full radius is
unchanged.

Older Safari: the reduced-motion listener falls back to the media
query's addListener / removeListener when addEventListener is missing,
as other modules here already do.

Echo wiring test: a detectionHost test now paints through the real
detection lane with an echo field set, and checks the echo stroke takes
the echo colour on the default style and each style's line colour under
CRT, NVG and FLIR. CURRENT-STATE notes the 5 km no-echo zone.
This commit is contained in:
Manjunath committed 2026-11-03 20:04:33 +05:30
1 parent 013cfdf91d
commit 0f56b3147b
6 files changed
+146 -29

No files matched your search

+52
View File
@@ -24,6 +24,10 @@ import {
setOverlayEntries,
} from '../overlays/worldOverlay.js';
import { DETECTION_THEME_MAP } from '../overlays/worldOverlayTokens.js';
import {
clearAwarenessEchoField,
setAwarenessEchoField,
} from '../awarenessEcho.js';
import { composeLabel, resolveTier } from './detectionDraw.js';
test('detection diagnostics count rendered fading rows instead of absent selected identities', () => {
@@ -627,6 +631,54 @@ test('surveillance military tier reaches the dedicated render target as shipped
}
});
test('Global Context echo brackets reach the canvas in the detection style colour', () => {
const env = installEnvironment();
// Fronts every millisecond with a long fade, so the contact is lit on
// whatever frame paints; a distinctive width picks the echo stroke out.
const echo = {
layerIds: ['military'],
fadeMs: 60_000,
color: 'rgb(1, 2, 3)',
spreadPx: 8,
lineWidth: 3.25,
};
const echoStrokes = () =>
env.detectionCtx.calls
.filter(([name, , , width]) => name === 'stroke' && width === echo.lineWidth)
.map(([, , style]) => style);
try {
setAwarenessEchoField({
center: Cesium.Cartesian3.fromDegrees(0, 89, 0),
radiusM: 250_000,
pulse: { count: 1000, periodMs: 1000, startFraction: 0 },
echo,
});
initWorldOverlay(env.viewer);
initDetection(env.viewer, [militaryLayer()], () => {});
setMode('DENSE');
setDetectionStyle('normal');
settleFrame(env);
assert.ok(echoStrokes().length > 0, 'the echo bracket is painted');
assert.ok(echoStrokes().every((style) => style === echo.color));
// CRT, NVG and FLIR keep their own palettes.
for (const style of ['retro', 'surveillance', 'thermal']) {
env.detectionCtx.calls.length = 0;
setDetectionStyle(style);
settleFrame(env);
const strokes = echoStrokes();
assert.ok(strokes.length > 0, style);
assert.ok(
strokes.every((stroke) => stroke === DETECTION_THEME_MAP[style].line),
`${style} echoes take the style line colour, got ${strokes}`,
);
}
} finally {
clearAwarenessEchoField();
env.cleanup();
}
});
test('pathological detection paint holds alternate frames without freezing shared lanes', () => {
// Opts into the telemetry banner: the held-frame assertions count banner paints.
const env = installEnvironment({ search: '?detectDebug=1' });