mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
Drop the late feature changes of deleted Navara vector layers, which kept the view from going idle
This commit is contained in:
1 parent
843c4a111d
commit
e1d3a588fc
5 files changed
+85
-1
No files matched your search
@@ -3700,6 +3700,7 @@
|
||||
"src/globe/navara/index.js",
|
||||
"src/globe/navara/input.js",
|
||||
"src/globe/navara/internals.js",
|
||||
"src/globe/navara/featureQueue.js",
|
||||
"src/globe/navara/look.js",
|
||||
"src/globe/navara/maps.js",
|
||||
"src/globe/navara/sharpen.js",
|
||||
|
||||
@@ -90,7 +90,7 @@ function rayRaisedEllipsoid({ origin, direction }, height) {
|
||||
/**
|
||||
* @param {object} view An initialised Navara ThreeView.
|
||||
* @param {{
|
||||
* hooks: { tileRoots: Function, isIdle: Function, retainTileGeometry: Function },
|
||||
* hooks: { tileRoots: Function, isIdle: Function, retainTileGeometry: Function, dropOrphanFeatureChanges?: Function },
|
||||
* container?: HTMLElement,
|
||||
* fetch?: typeof fetch,
|
||||
* clock?: object,
|
||||
@@ -196,6 +196,8 @@ export function createNavaraEngine(
|
||||
let drawing = false;
|
||||
const handlers = {
|
||||
preUpdate: (time) => {
|
||||
// Before the view decides whether it is idle (internals.js).
|
||||
hooks.dropOrphanFeatureChanges?.();
|
||||
engineClock.beginFrame();
|
||||
frames.preUpdate.raiseEvent(time);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Logic over a Navara view internal that internals.js reads (the queued
|
||||
// feature changes), kept apart so Node tests can load it without the SDK.
|
||||
|
||||
/**
|
||||
* Drop the queued feature changes of vector layers that no longer exist, and
|
||||
* return how many went. Navara processes a change only for a feature it
|
||||
* knows, and keeps any other in its queue for good: a change that arrives
|
||||
* after its layer was deleted (a polygon display replacing its layers while
|
||||
* their tiles are still being cut) leaves the queue non-empty, so the view
|
||||
* never goes idle and tilesLoaded() stays false.
|
||||
* @param {{ events: object[], remove: (index: number) => void } | null} queue
|
||||
* The queued changes (internals.js featureChangeQueue).
|
||||
* @param {(layerId: string) => boolean} layerExists
|
||||
*/
|
||||
export function dropOrphanFeatureChanges(queue, layerExists) {
|
||||
if (!queue?.events.length) return 0;
|
||||
let dropped = 0;
|
||||
for (let index = queue.events.length - 1; index >= 0; index--) {
|
||||
const event = queue.events[index];
|
||||
const layerId = event?.layer_id;
|
||||
if (layerId == null || layerExists(String(layerId))) continue;
|
||||
queue.remove(index);
|
||||
event.free?.();
|
||||
dropped++;
|
||||
}
|
||||
return dropped;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import { ModelMesh } from '@navaramap/three';
|
||||
import { patchCascadedLightCopy } from './cascadedLightCopy.js';
|
||||
import { dropOrphanFeatureChanges } from './featureQueue.js';
|
||||
|
||||
export const NAVARA_INTERNALS_VERSION = '0.2.1';
|
||||
|
||||
@@ -156,11 +157,35 @@ export function keepCascadedLightIds(view) {
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The view's queued feature changes, for featureQueue.js, or null. Navara
|
||||
* keeps a change for a feature it does not know in that queue for good, so
|
||||
* a deleted layer's late changes keep the view from going idle. Private:
|
||||
* view._eventManager (stacks, removeAt). Upstream ask: drop a deleted
|
||||
* layer's pending feature events, or skip them in needsUpdate.
|
||||
*/
|
||||
export function featureChangeQueue(view) {
|
||||
const manager = view._eventManager;
|
||||
const events = manager?.stacks?.renderable_feature_changed;
|
||||
return events
|
||||
? {
|
||||
events,
|
||||
remove: (index) =>
|
||||
manager.removeAt('renderable_feature_changed', index),
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
/** The hooks createNavaraEngine takes. */
|
||||
export const navaraHooks = (view) => ({
|
||||
retainTileGeometry,
|
||||
tileRoots: () => tileRoots(view),
|
||||
isIdle: () => isIdle(view),
|
||||
dropOrphanFeatureChanges: () =>
|
||||
dropOrphanFeatureChanges(
|
||||
featureChangeQueue(view),
|
||||
(id) => view.findLayerById(id) != null,
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,3 +44,32 @@ test('only internals.js reaches private Navara members', () => {
|
||||
);
|
||||
assert.deepEqual(offenders, []);
|
||||
});
|
||||
|
||||
test('feature changes of a deleted vector layer leave the queue; live ones stay', async () => {
|
||||
const { dropOrphanFeatureChanges } = await import('./featureQueue.js');
|
||||
const freed = [];
|
||||
const change = (layerId) => ({
|
||||
layer_id: layerId,
|
||||
free: () => freed.push(layerId),
|
||||
});
|
||||
const events = [change('gone'), change('live'), change('gone'), change(null)];
|
||||
const queue = { events, remove: (index) => events.splice(index, 1) };
|
||||
assert.equal(
|
||||
dropOrphanFeatureChanges(queue, (id) => id === 'live'),
|
||||
2,
|
||||
);
|
||||
assert.deepEqual(
|
||||
events.map((event) => event.layer_id),
|
||||
['live', null],
|
||||
);
|
||||
assert.deepEqual(freed, ['gone', 'gone']);
|
||||
// No queue, or an empty one, costs nothing.
|
||||
assert.equal(
|
||||
dropOrphanFeatureChanges(null, () => false),
|
||||
0,
|
||||
);
|
||||
assert.equal(
|
||||
dropOrphanFeatureChanges({ events: [], remove() {} }, () => false),
|
||||
0,
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user