diff --git a/scripts/qa-wind-engine-switch.mjs b/scripts/qa-wind-engine-switch.mjs index ac155feba..f9b6c7e05 100644 --- a/scripts/qa-wind-engine-switch.mjs +++ b/scripts/qa-wind-engine-switch.mjs @@ -81,7 +81,7 @@ await strict.run({}, async (b) => { }); await p.waitForFunction( () => - window.qaWind.getDiagnostics().surface?.ready && + window.qaWind.getDiagnostics().imageryActive && window.qaWind.getDiagnostics().gpu?.ready, ); await p.evaluate(() => window.qaWind.setParams({ inspect: true })); diff --git a/src/data/bhoteKoshiEvent.js b/src/data/bhoteKoshiEvent.js index bff2e169e..5e32285f0 100644 --- a/src/data/bhoteKoshiEvent.js +++ b/src/data/bhoteKoshiEvent.js @@ -1010,6 +1010,7 @@ export function createBhoteKoshiEventLayer({ imageryProviderFactory = DEFAULT_IMAGERY_PROVIDER_FACTORY, terrainSampler = DEFAULT_TERRAIN_SAMPLER, mediaLoader = DEFAULT_MEDIA_LOADER, + imageLoader = DEFAULT_MEDIA_LOADER, evidenceFrameFactory = createEvidenceFrame, evidenceFrameUpdater = updateEvidenceFrame, videoFactory = DEFAULT_VIDEO_FACTORY, @@ -1022,6 +1023,9 @@ export function createBhoteKoshiEventLayer({ let _native = null; let _nativeFlood = null; let _providers = null; + // The before and after images, decoded once for every engine the event + // is drawn on (as Cesium's providers were kept across switches). + let _imageryImages = null; const cameraForScene = () => _engine?.camera ?? _viewer?.camera; const canvasForScene = () => _engine?.host.canvas ?? _viewer?.scene?.canvas; let _dataManager = null; @@ -1183,12 +1187,21 @@ export function createBhoteKoshiEventLayer({ async function createImagery(event, current = () => true) { if (_native) { // The engine's display draws the images through engine.imagery. + _imageryImages ??= Promise.all( + [event.imagery.before.path, event.imagery.after.path].map((path) => + imageLoader(eventAsset(path)), + ), + ); + let images; + try { + images = await _imageryImages; + } catch { + _imageryImages = null; + throw new Error('Bhote Koshi imagery unavailable'); + } await _native.loadImages( event.imagery.rectangle, - [ - eventAsset(event.imagery.before.path), - eventAsset(event.imagery.after.path), - ], + images, 'Vantor WorldView Open Data ยท CC BY-NC 4.0', ); if (_enabled && current()) setSplit(_split); @@ -3793,6 +3806,7 @@ export function createBhoteKoshiEventLayer({ _nativeFlood = null; _native?.clear(); _providers = null; + _imageryImages = null; if (_floodDataSource && _viewer) _viewer.dataSources.remove(_floodDataSource, true); _floodDataSource = null; diff --git a/src/layers/bhoteKoshi/render/display.js b/src/layers/bhoteKoshi/render/display.js index 05b3ab820..2172bb1db 100644 --- a/src/layers/bhoteKoshi/render/display.js +++ b/src/layers/bhoteKoshi/render/display.js @@ -44,11 +44,11 @@ export function createBhoteKoshiDisplay(engine) { }; }, /** - * The before and after images over `box` (degrees); resolves once both - * draw, rejects when one would not load (unless replaced or cleared - * first). + * The before and after images over `box` (degrees), each a URL or an + * image already decoded; resolves once both draw, rejects when one + * would not load (unless replaced or cleared first). */ - async loadImages(box, urls, credit = null) { + async loadImages(box, images, credit = null) { if (destroyed) return; clear(); const load = loads; @@ -60,7 +60,7 @@ export function createBhoteKoshiDisplay(engine) { }; // Each layer stages its image over an empty one, which tells whether // the image loaded. - layers = urls.map((_url, index) => + layers = images.map((_image, index) => engine.imagery.createLayer({ id: `${id}-${SIDES[index]}`, order: IMAGERY_ORDER, @@ -75,7 +75,9 @@ export function createBhoteKoshiDisplay(engine) { layer.setSource( { kind: 'image', - url: urls[index], + ...(typeof images[index] === 'string' + ? { url: images[index] } + : { image: images[index] }), rectangle, ...(credit ? { credit } : {}), },