mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
fix(camera): run a recovery check a scene deferred once it ends
A check skipped because a flight or a playing Director scene was in progress used to be dropped, so a run that ended or held on a stars-only shot stayed there until the next camera move. Keep watching instead: the settle check retries once the flight or scene ends, within its existing five-minute bound, and a moveEnd that arrives while it is deferred keeps the check armed rather than stopping it. Also test that the free-look limit never raises Cesium's trackball height and that dispose keeps a value set after install, note in its JSDoc the enableLook case it cannot tell apart, and document the trackball change and the retry in CURRENT-STATE and the changelog.
This commit is contained in:
1 parent
2f9d13f39d
commit
29935cc094
4 files changed
+76
-31
No files matched your search
@@ -1,8 +1,9 @@
|
||||
- Keep the globe in view from orbit. Cesium's free look (Shift+drag) turned
|
||||
the camera in place, so a few drags from the whole-globe view left only
|
||||
stars, and the pose stayed in the share link. Free look now works only below
|
||||
1,000 km; a camera move that ends above it with no planet surface in view
|
||||
(inside the scope keyhole when the scope is on) turns straight down; and
|
||||
voice tilt and turns from orbit stop while the planet is still on screen and
|
||||
say so instead of reporting a turn they could not make (Manjunath,
|
||||
@manjunath22466, #1532).
|
||||
1,000 km, and above it a drag that starts on the stars orbits the globe
|
||||
instead of turning the camera; a camera move that ends above it with no
|
||||
planet surface in view (inside the scope keyhole when the scope is on) turns
|
||||
straight down; and voice tilt and turns from orbit stop while the planet is
|
||||
still on screen and say so instead of reporting a turn they could not make
|
||||
(Manjunath, @manjunath22466, #1532).
|
||||
+17
-15
@@ -67,10 +67,11 @@ the real browser controller at desktop and phone widths with keyless fixtures.
|
||||
|
||||
Cesium's free look (Shift+drag, which turns the camera in place) works only
|
||||
below 1,000 km. Above that height a few drags could turn the whole planet out of
|
||||
frame and leave only stars, so Shift+drag does nothing there. Cesium also
|
||||
turns the camera in place for a drag that starts on the stars below its
|
||||
trackball height (7,500 km by default); that height is lowered to 1,000 km, so
|
||||
such a drag orbits the globe above it, as it does higher up. Orbit, tilt and
|
||||
frame and leave only stars, so Shift+drag does nothing there. Cesium also turns
|
||||
the camera in place for a drag that starts on the stars below its trackball
|
||||
height (7,500 km by default); that height is lowered to 1,000 km, so such a drag
|
||||
orbits the globe above it, as it does higher up, and a tilt drag from the stars
|
||||
there tilts about the planet's edge or does nothing. Otherwise orbit, tilt and
|
||||
zoom are unchanged at every height. How much of the frame shows the planet's
|
||||
surface is measured by casting a 32×18 grid of view rays at the ellipsoid; while
|
||||
the scope mask is on (the default) only the rays inside its keyhole count, since
|
||||
@@ -97,17 +98,18 @@ rounding error every frame and Cesium never sees it stop. That check keeps
|
||||
watching until move-end arrives, recovering once after each move that comes to
|
||||
rest, and gives up five minutes after the camera last moved. Limb glow, and a
|
||||
surface sliver up to about one grid cell thick (some 50 px on a 900 px tall
|
||||
frame), can count as out of view. The zoom-out guard above keeps wheel and
|
||||
pinch zoom-outs in view; this catches the other ways a move can end looking
|
||||
away, such as a saved or shared view that did.
|
||||
Views with more surface than that, such as the oblique orbital Director shots,
|
||||
are left as they are, and so are tracked or locked cameras, a camera flight in
|
||||
progress, a Director scene while it plays (holds included) and the 2D and
|
||||
Columbus modes. A view that loses its surface without a camera move (a resize,
|
||||
or turning the scope on) is left as it is until the next move. A voice turn
|
||||
requested while the camera is tracked is judged
|
||||
by the pose voice's release of the follow camera will leave, before that
|
||||
release, so a refused turn keeps the tracking.
|
||||
frame), can count as out of view. The zoom-out guard above keeps wheel and pinch
|
||||
zoom-outs in view; this catches the other ways a move can end looking away, such
|
||||
as a saved or shared view that did. Views with more surface than that, such as
|
||||
the oblique orbital Director shots, are left as they are, and so are tracked or
|
||||
locked cameras, a camera flight in progress, a Director scene while it plays
|
||||
(holds included) and the 2D and Columbus modes; a check a flight or scene defers
|
||||
runs once it ends. A Director shot loaded or replayed outside a run is not a
|
||||
playing scene. A view that loses its surface without a camera move (a resize, or
|
||||
turning the scope on) is left as it is until the next move. A voice turn
|
||||
requested while the camera is tracked is judged by the pose voice's release of
|
||||
the follow camera will leave, before that release, so a refused turn keeps the
|
||||
tracking.
|
||||
|
||||
Analyst region queries resolve unique Natural Earth names offline without
|
||||
geocoding, so Gold Coast and Ivory Coast name the West African natural regions.
|
||||
|
||||
@@ -412,12 +412,24 @@ test('drags that start on the stars orbit above the free-look height', () => {
|
||||
|
||||
const lower = freeLookFixture({ height: 500 });
|
||||
lower.controller.minimumTrackBallHeight = 500_000;
|
||||
installFreeLookHeightLimit(lower.viewer)();
|
||||
const disposeLower = installFreeLookHeightLimit(lower.viewer);
|
||||
assert.equal(
|
||||
lower.controller.minimumTrackBallHeight,
|
||||
500_000,
|
||||
'never raised',
|
||||
);
|
||||
disposeLower();
|
||||
assert.equal(lower.controller.minimumTrackBallHeight, 500_000);
|
||||
|
||||
const later = freeLookFixture({ height: 500 });
|
||||
const disposeLater = installFreeLookHeightLimit(later.viewer);
|
||||
later.controller.minimumTrackBallHeight = 2_000_000;
|
||||
disposeLater();
|
||||
assert.equal(
|
||||
later.controller.minimumTrackBallHeight,
|
||||
2_000_000,
|
||||
'dispose keeps a value set after install',
|
||||
);
|
||||
});
|
||||
|
||||
test('free look keeps a setting other code makes after it is installed', () => {
|
||||
@@ -739,6 +751,31 @@ test('the recovery leaves a camera flight and an authored scene alone', () => {
|
||||
assert.ok(Cesium.Math.equalsEpsilon(camera.pitch, -Math.PI / 2, 1e-6));
|
||||
});
|
||||
|
||||
test('a check a scene or flight defers runs once it ends', () => {
|
||||
for (const viaMoveEnd of [false, true]) {
|
||||
let playing = true;
|
||||
const timers = fakeTimers();
|
||||
const { camera, viewer } = realCamera({ width: 1225, height: 923 });
|
||||
installGlobeInViewRecovery(viewer, {
|
||||
paused: () => playing,
|
||||
...timers,
|
||||
});
|
||||
aim(camera, reportedStuckView);
|
||||
camera.moveStart.raiseEvent();
|
||||
// A hold on a stars-only shot: quiet, with or without Cesium's moveEnd.
|
||||
for (let i = 0; i < 4; i += 1) timers.tick();
|
||||
if (viaMoveEnd) camera.moveEnd.raiseEvent();
|
||||
assert.equal(globeOutOfFrame(camera), true, 'left alone while it plays');
|
||||
assert.equal(timers.pending(), 1, 'still watching');
|
||||
playing = false;
|
||||
timers.tick();
|
||||
assert.ok(
|
||||
Cesium.Math.equalsEpsilon(camera.pitch, -Math.PI / 2, 1e-6),
|
||||
`recovered once the scene ends (${viaMoveEnd ? 'after moveEnd' : 'no moveEnd'})`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function fakeTimers() {
|
||||
let next = 1;
|
||||
const pending = new Map();
|
||||
|
||||
+15
-10
@@ -112,7 +112,9 @@ export function installTrackpadPinchZoom(
|
||||
* Allow Cesium's free look only below `maxHeight` and return its disposer.
|
||||
* Orbit, tilt and zoom stay available at every height. A value other code
|
||||
* sets later is kept as the one to allow below that height, and restored on
|
||||
* dispose. `enableLook` gates the Shift+drag binding only: below its trackball
|
||||
* dispose; a `false` written while the camera is above `maxHeight` cannot be
|
||||
* told apart from this limit's own write, so dispose restores the earlier
|
||||
* value then. `enableLook` gates the Shift+drag binding only: below its trackball
|
||||
* height Cesium also turns the camera in place for a drag that starts on the
|
||||
* stars. That height is lowered to `maxHeight` too, so above it such a drag
|
||||
* orbits the globe, as it does above Cesium's own 7,500 km.
|
||||
@@ -171,7 +173,8 @@ const SETTLE_GIVE_UP_MS = 5 * 60_000;
|
||||
* looking away from the planet.
|
||||
* Heading and position are kept. Tracked cameras, locked ones (non-identity
|
||||
* transform), a camera flight in progress, the 2D and Columbus modes, and any
|
||||
* time `paused` returns true (an authored scene playing) are left alone.
|
||||
* time `paused` returns true (an authored scene playing) are left alone; a
|
||||
* check they defer runs again once they end, within the settle check's bound.
|
||||
* `keyholeRadius`
|
||||
* returns the radius of the visible circle when a scope mask hides the rest of
|
||||
* the frame (see `globeFrameShare`), or 0; it is read at every check.
|
||||
@@ -202,16 +205,18 @@ export function installGlobeInViewRecovery(
|
||||
if (!scene || !camera?.moveEnd || !camera?.moveStart)
|
||||
throw new TypeError('A complete Cesium viewer is required');
|
||||
|
||||
// Returns false while a flight or a paused scene defers the check, so the
|
||||
// caller can try again once it ends.
|
||||
const recover = () => {
|
||||
if (!isFreeGlobeCamera(viewer)) return;
|
||||
if (!isFreeGlobeCamera(viewer)) return true;
|
||||
// Cesium has no public running-flight flag.
|
||||
if (camera._currentFlight || paused()) return;
|
||||
if (camera._currentFlight || paused()) return false;
|
||||
const height = camera.positionCartographic?.height;
|
||||
if (
|
||||
!(height > minHeight) ||
|
||||
!globeOutOfFrame(camera, { keyholeRadius: keyholeRadius() })
|
||||
)
|
||||
return;
|
||||
return true;
|
||||
camera.setView({
|
||||
orientation: {
|
||||
heading: camera.heading,
|
||||
@@ -220,6 +225,7 @@ export function installGlobeInViewRecovery(
|
||||
},
|
||||
});
|
||||
scene.requestRender?.();
|
||||
return true;
|
||||
};
|
||||
|
||||
const lastPosition = new Cesium.Cartesian3();
|
||||
@@ -255,10 +261,8 @@ export function installGlobeInViewRecovery(
|
||||
}
|
||||
// Two quiet samples in a row after a move: at rest for half a second, as
|
||||
// for moveEnd.
|
||||
if (restingSamples >= 2 && movedSinceCheck) {
|
||||
if (restingSamples >= 2 && movedSinceCheck && recover())
|
||||
movedSinceCheck = false;
|
||||
recover();
|
||||
}
|
||||
if (settleElapsed >= SETTLE_GIVE_UP_MS) return;
|
||||
Cesium.Cartesian3.clone(camera.positionWC, lastPosition);
|
||||
Cesium.Cartesian3.clone(camera.directionWC, lastDirection);
|
||||
@@ -274,8 +278,9 @@ export function installGlobeInViewRecovery(
|
||||
settleTimer = schedule(sample, SETTLE_SAMPLE_MS);
|
||||
};
|
||||
const removeMoveEnd = camera.moveEnd.addEventListener(() => {
|
||||
stopSettling();
|
||||
recover();
|
||||
if (recover()) stopSettling();
|
||||
// Deferred: keep sampling so the check runs once the flight or scene ends.
|
||||
else if (settleTimer === null) startSettling();
|
||||
});
|
||||
const removeMoveStart = camera.moveStart.addEventListener(startSettling);
|
||||
|
||||
|
||||
Reference in new issue
Block a user