Files
gods-eye-view/src/layers/submarineCables/interaction.js
T
Bilawal Sidhu 9fc8d1966b feat(annotations): draw on the world by hand (#547)
Supersedes #235 by @cora-fresh-labs, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Future work (not in this PR): hand-drawn marks do not persist across a reload today, and neither do spoken annotations; there is no storage layer for marks. The natural home is Scenes: a drawing that belongs to a shot and persists per shot, so a scene animation can carry its own marks. Needs an owner.
Co-authored-by: Clint Borle <[email protected]>
2026-09-14 19:59:26 -05:00

79 lines
2.3 KiB
JavaScript

import * as Cesium from 'cesium';
import { isPointerFree } from '../../data/inputOwnership.js';
export function createInteraction({ state, screenSpaceEventHandlerFactory }) {
function registerPickEntity(entity, info) {
entity.__gevTeleGeography = info;
state._pickByEntity.set(entity, info);
}
function beginInteraction(viewer) {
if (state._clickHandler) return;
state._clickHandler = screenSpaceEventHandlerFactory(viewer.scene.canvas);
state._clickHandler.setInputAction((click) => {
// A tool owns the pointer (src/data/inputOwnership.js): yield the click.
if (!isPointerFree()) return;
if (!state._enabled) return;
const picked = viewer.scene.pick(click.position);
const record = resolvePickRecord(picked);
if (!record?.reference) return;
flyToReference(viewer, record.reference);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
function resolvePickRecord(picked) {
if (!picked) return null;
const primitive = picked.primitive;
if (primitive) {
const primitiveInfo = state._pickByEntity.get(primitive);
if (primitiveInfo) return primitiveInfo;
if (primitive.__gevTeleGeography) return primitive.__gevTeleGeography;
if (
primitive.id &&
typeof primitive.id === 'object' &&
primitive.id.reference
) {
return primitive.id;
}
}
const entity = picked.id;
if (entity) {
const entityInfo = state._pickByEntity.get(entity);
if (entityInfo) return entityInfo;
if (entity.__gevTeleGeography) return entity.__gevTeleGeography;
if (entity.id && typeof entity.id === 'object' && entity.id.reference) {
return entity.id;
}
}
return null;
}
function flyToReference(viewer, reference) {
if (!viewer || !reference) return;
const destination = Cesium.Cartesian3.fromDegrees(
reference.lon,
reference.lat,
6500,
);
viewer.camera.cancelFlight();
viewer.camera.flyTo({
destination,
orientation: {
heading: viewer.camera.heading || 0,
pitch: Cesium.Math.toRadians(-52),
roll: 0,
},
duration: 1.35,
easingFunction: Cesium.EasingFunction.CUBIC_IN_OUT,
});
}
return {
registerPickEntity,
beginInteraction,
resolvePickRecord,
flyToReference,
};
}