Release a running camera verb when a Navara scene is parked or torn down, as the Cesium scene does

This commit is contained in:
German Khokhlov committed 2026-11-03 21:11:30 +04:00
1 parent dcb8de9d2c
commit 074f4af10e
2 files changed
+72 -2

No files matched your search

+56
View File
@@ -204,3 +204,59 @@ test('Navara keeps attribution for every available W1/W2 source and excludes una
keys.map((key) => `Credit ${key}`),
);
});
test('parking or tearing down the Navara scene releases a running camera verb', async (t) => {
const { initCameraVerbs, moveCamera, getActiveCameraMotion } =
await import('../cameraVerbs.js');
const { createRendererCache } =
await import('../standalone/rendererCache.js');
for (const end of ['park', 'teardown']) {
const dom = installDom();
t.after(dom.restore);
// The renderer cache's own host element (parking needs one).
const element = () => ({
className: '',
prepend() {},
remove() {},
});
globalThis.document.createElement = element;
dom.container.prepend = () => {};
const engine = createFakeEngine({
kind: 'navara',
canvas: new EventTarget(),
});
const cache = createRendererCache();
const cleanups = [];
await createApplicationScene({
engineKind: 'navara',
requestServices,
googleApiKey: '',
credits: [],
loaderStatus: { textContent: '' },
signal: new AbortController().signal,
defer: (dispose) => cleanups.push(dispose),
rendererCache: cache,
loadNavaraGlobe: async () => async () => ({
engine,
setRenderLoop() {},
destroy: () => engine.destroy(),
}),
});
initCameraVerbs(engine);
assert.equal(
moveCamera({ motion: 'pan', direction: 'left', mode: 'continuous' }).ok,
true,
);
assert.equal(getActiveCameraMotion()?.rig, 'engine');
// An engine switch parks the renderer (its scene's suspend); a page
// teardown disposes it.
if (end === 'park') cache.retain('navara');
while (cleanups.length) await cleanups.pop()();
if (end === 'teardown') cache.clear();
assert.equal(getActiveCameraMotion(), null, end);
engine.fake.resetCalls();
if (!engine.isDestroyed()) engine.fake.frames(3);
assert.equal(engine.fake.callsOf('camera.setView').length, 0, end);
if (end === 'park') cache.clear();
}
});
+16 -2
View File
@@ -112,8 +112,10 @@ async function createRenderer({
}) {
// The Navara mode's own code loads only in that mode, with Navara itself,
// so the Cesium-mode bundle carries none of it.
if (engineKind === 'navara')
return (await import('./navaraMode.js')).createNavaraScene({
if (engineKind === 'navara') {
const scene = await (
await import('./navaraMode.js')
).createNavaraScene({
container,
cesiumToken,
credits,
@@ -124,6 +126,17 @@ async function createRenderer({
signal,
defer,
});
// As the Cesium scene below: a parked or released engine keeps no camera
// verb running on it (a Directions flight is parked before this).
const { engine } = scene;
defer(() => releaseCameraVerbs(engine));
const suspend = scene.suspend;
scene.suspend = () => {
releaseCameraVerbs(engine);
suspend();
};
return scene;
}
if (engineKind !== 'cesium')
throw new TypeError(`Unknown globe engine: ${engineKind}`);
loaderStatus.textContent = t('Configuring viewer...');
@@ -228,6 +241,7 @@ async function createRenderer({
uninstallRenderGovernor(viewer);
engine.camera.cancelFlight();
releaseCameraVerbs(viewer);
releaseCameraVerbs(engine);
viewer.useDefaultRenderLoop = false;
},
resume() {