fix(camera): read zoom input at the ceiling when the scene is idle

The guard reads its input in preRender, which Cesium only fires on frames
that draw. In request-render mode, wheel input at the ceiling doesn't move
the camera, so nothing drew and the input was applied later by an
unrelated frame. The guard now requests a frame through the render
governor whenever it has unread input.
This commit is contained in:
Sameh Khamis committed 2026-11-03 09:10:30 -08:00
1 parent 08ff7f3e9d
commit e4b3933166
2 files changed
+32 -3

No files matched your search

+20 -1
View File
@@ -130,9 +130,13 @@ function guardFixture({ maximumZoomDistance = Infinity } = {}) {
requestRender: (reason) => renders.push(reason),
},
);
// A frame Cesium skips drawing in request-render mode: no preRender.
const idleFrame = () => {
for (const handler of postUpdate) handler();
};
const frame = (height = camera.height) => {
camera.height = height;
for (const handler of postUpdate) handler();
idleFrame();
for (const handler of preRender) handler();
};
const movement = (type, deltaY, { modifier, tiltDeltaY = 0 } = {}) => {
@@ -179,6 +183,7 @@ function guardFixture({ maximumZoomDistance = Infinity } = {}) {
renders,
dispose,
frame,
idleFrame,
movement,
};
}
@@ -454,6 +459,20 @@ test('outward input at the ceiling reframes a deliberately tilted camera', () =>
f.dispose();
});
test('input that leaves the camera still requests a frame to read it', () => {
const f = guardFixture();
f.frame(MAXIMUM_ZOOM_DISTANCE_M);
f.idleFrame();
assert.deepEqual(f.renders, [], 'an idle scene stays idle');
// At the ceiling Cesium doesn't move the camera, so nothing would draw.
f.movement(WHEEL, -10);
f.idleFrame();
assert.deepEqual(f.renders, ['zoom-out-guard']);
f.frame();
assert.ok(f.camera.pitch < Cesium.Math.toRadians(-25), 'read that frame');
f.dispose();
});
test('equivalent heading and roll wraps do not cancel stationary settling', () => {
const f = guardFixture();
f.frame(500_000);