diff --git a/src/globe/cesium/follow.js b/src/globe/cesium/follow.js index 2fc90b16e..601e134e3 100644 --- a/src/globe/cesium/follow.js +++ b/src/globe/cesium/follow.js @@ -188,6 +188,8 @@ export function createCesiumFollow(viewer, { commanded }) { if (!handle) { handle = { native: entity, + target: () => + displayPosition(entity, viewer.clock.currentTime, undefined), stop() { if (viewer.trackedEntity === entity) viewer.trackedEntity = undefined; }, @@ -306,6 +308,13 @@ export function createCesiumFollow(viewer, { commanded }) { const state = { entity: null, proxy: null, options, handle: null }; state.handle = { native: options.native, + target() { + try { + return state.options.position(); + } catch { + return undefined; + } + }, stop() { if (own !== state) return; if (viewer.trackedEntity === state.entity) diff --git a/src/globe/contract.js b/src/globe/contract.js index 5f787b813..931f478a0 100644 --- a/src/globe/contract.js +++ b/src/globe/contract.js @@ -150,6 +150,8 @@ * @typedef {object} FollowHandle * @property {() => void} stop * @property {(next: Partial) => void} retarget + * @property {() => (Cartesian3 | undefined)} target Where the followed + * target is now (what the follow centres). * @property {any} [native] * @property {object} [label] FollowOptions.label. * diff --git a/src/globe/follow.js b/src/globe/follow.js index 40bbdb108..5ba343b25 100644 --- a/src/globe/follow.js +++ b/src/globe/follow.js @@ -350,6 +350,13 @@ export function createFollowController({ label: options.label, offset: null, previous: null, + target() { + try { + return handle.options.position(); + } catch { + return undefined; + } + }, stop: () => end(handle), retarget(next) { const updated = normalizeFollowOptions({ ...options, ...next }); diff --git a/src/globe/testing/contractSuite.mjs b/src/globe/testing/contractSuite.mjs index d6b6761df..1a84d9619 100644 --- a/src/globe/testing/contractSuite.mjs +++ b/src/globe/testing/contractSuite.mjs @@ -1209,8 +1209,10 @@ export function createContractSuite( count++; return count; }; + // ready() turns true once the glTF has loaded (the magenta point + // and sprites above can already fill the region before then). + await until(() => models.ready(), 'the model set ready()'); await until(() => modelPixels() > 150, 'the model drawn'); - ensure(models.ready(), 'a drawn model set is not ready()'); } finally { for (const set of sets) set.destroy(); } @@ -2572,6 +2574,11 @@ export function createContractSuite( ); await until(() => offCentre() <= 3, 'the follow centring its target'); near(range(), Math.hypot(1000, 400), 5, 'follow range at viewFrom'); + // target(): where the followed target is now. + ensure( + cartesian3.distance(handle.target(), at(step)) < 1, + 'following().target() is not the target', + ); // 2 s of motion (at least 120 frames), centred within 3 px. const began = performance.now(); const firstStep = step;