Fly the remaining flights through the camera port, on any viewer

The embed view, the celestial-ring focus, the ground-guard lift, the
Bhote Koshi approach and orbit, launch selection and replay flights, and
the cockpit's view and takeover now drive the renderer's camera port.
The contract gains a sineInOut easing, pinned by a conformance trace.

A viewer with no renderer bound, such as one a consumer of a public
export brings, now gets a camera port too, as it already got an input
port: cameraOf builds one over the viewer's own Cesium camera and keeps
it for the viewer's life, until a renderer is bound. The Cesium adapter
provides the factory as it loads; code that reaches Cesium takes cameraOf
from the adapter so the factory comes with it, and findCamera answers
null where a missing camera is not an error (HUD, share link, world
focus, Recent Imagery's ZOOM IN). A test walks every package export and
fails one that can reach the bridge without loading the factory.

A destroyed viewer gets no camera and lets go of a built one, and the
application renderer stays bound until its viewer is destroyed.
This commit is contained in:
Sameh Khamis committed 2026-11-06 08:21:57 -08:00
1 parent e3baeec223
commit 0b1c5d0f23
44 files changed
+1167 -344

No files matched your search

+13 -14
View File
@@ -13,6 +13,7 @@
import * as Cesium from 'cesium';
import { announceNavigationAuthority } from '../navigationPolicy.js';
import { cameraOf } from '../render/cesium/camera.js';
import { annotationsFromParams, createView } from '../view/index.js';
const EMBED_VIEW_MESSAGE = 'gev:view';
@@ -147,21 +148,19 @@ const delay = (ms, signal) =>
function flyTo(viewer, camera) {
announceNavigationAuthority('embed-view');
return new Promise((resolve) => {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
camera.lon,
camera.lat,
camera.altitude_m,
),
orientation: {
heading: Cesium.Math.toRadians(camera.heading_deg),
pitch: Cesium.Math.toRadians(camera.pitch_deg),
roll: 0,
cameraOf(viewer).flyTo(
{ lon: camera.lon, lat: camera.lat, height: camera.altitude_m },
{
orientation: {
heading: Cesium.Math.toRadians(camera.heading_deg),
pitch: Cesium.Math.toRadians(camera.pitch_deg),
roll: 0,
},
durationS: FLIGHT_SECONDS,
onComplete: () => resolve(true),
onCancel: () => resolve(false),
},
duration: FLIGHT_SECONDS,
complete: () => resolve(true),
cancel: () => resolve(false),
});
);
});
}