refactor(transit): isolate native rendering from playback

This commit is contained in:
German Khokhlov committed 2026-10-29 17:12:18 +04:00
1 parent 694616d5c2
commit b8560e5b26
21 files changed
+465 -256

No files matched your search

+45 -53
View File
@@ -1,13 +1,5 @@
import { destroyTrack } from '../../data/contactPlayback.js';
import * as Cesium from 'cesium';
import {
claimCameraSensitivity,
releaseCameraSensitivity,
} from '../../data/cameraSensitivity.js';
import {
CAMERA_PERCENTAGE_CHANGED,
TRANSIT_SELECTED_OVERLAY_SOURCE_ID,
} from './policy.js';
import { TRANSIT_SELECTED_OVERLAY_SOURCE_ID } from './policy.js';
import { TRANSIT_ENABLED_FEEDS } from '../../data/transitFeeds.js';
/**
@@ -18,12 +10,13 @@ import { TRANSIT_ENABLED_FEEDS } from '../../data/transitFeeds.js';
* @param {object} context
* @returns {object}
*/
export function createLifecycle({ state, services, parts }) {
const {
registerSpriteCollection,
unregisterSpriteCollection,
restoreSpriteOrder,
} = services.sprites;
export function createLifecycle({
state,
services,
parts,
source,
rendererFactory,
}) {
const { registerPickOwner, unregisterPickOwner } = services.picking;
const { releaseContinuousRender } = services.render;
@@ -38,17 +31,13 @@ export function createLifecycle({ state, services, parts }) {
* default while Bikeshare was still relying on a fine one was exactly the
* bug that produced.
*/
function borrowCameraSensitivity(viewer) {
claimCameraSensitivity(
viewer?.camera,
'transit',
CAMERA_PERCENTAGE_CHANGED,
);
function borrowCameraSensitivity() {
parts.renderer.claimCamera();
}
/** Give the claim up. The camera keeps whatever anyone else still asks for. */
function returnCameraSensitivity(viewer) {
releaseCameraSensitivity(viewer?.camera, 'transit');
function returnCameraSensitivity() {
parts.renderer?.releaseCamera();
}
/**
@@ -124,20 +113,29 @@ export function createLifecycle({ state, services, parts }) {
* Create the point collection. Called once at bootstrap.
* @param {Cesium.Viewer} viewer
*/
init(viewer) {
init(viewer, options = {}) {
if (parts.renderer)
throw new Error('Transit layer is already initialized');
if (typeof rendererFactory !== 'function')
throw new TypeError('A transit renderer factory is required');
const renderer = rendererFactory({
state,
services,
parts,
source,
engine: options.engine,
});
state._viewer = viewer;
state._markers = new Cesium.BillboardCollection({
blendOption: Cesium.BlendOption.TRANSLUCENT,
});
viewer.scene.primitives.add(state._markers);
registerSpriteCollection('transit', state._markers);
state._animatedMarkers = new Cesium.BillboardCollection({
blendOption: Cesium.BlendOption.TRANSLUCENT,
});
viewer.scene.primitives.add(state._animatedMarkers);
registerSpriteCollection('transit-motion', state._animatedMarkers);
state._animatedMarkers.show = false;
state._markers.show = false;
parts.renderer = renderer;
try {
renderer.attach(viewer);
[state._markers, state._animatedMarkers] = renderer.createMarkers();
} catch (error) {
renderer.destroy();
parts.renderer = null;
state._viewer = null;
throw error;
}
state._enabled = false;
state._activeFeeds.clear();
state._feedStatus.clear();
@@ -159,7 +157,7 @@ export function createLifecycle({ state, services, parts }) {
state._rotationPose = null;
state._rotationDirty = false;
state._overlayHost.setVisible(TRANSIT_SELECTED_OVERLAY_SOURCE_ID, false);
restoreSpriteOrder(viewer);
parts.renderer.restoreOrder();
bindStyleEvents();
console.log(
`[Data:Transit] Initialized with ${TRANSIT_ENABLED_FEEDS.length} GTFS-RT feeds`,
@@ -185,17 +183,19 @@ export function createLifecycle({ state, services, parts }) {
parts.selection.installClickHandler(viewer);
registerPickOwner('transit', (pickedId) => state._vehicles.has(pickedId));
if (!state._cameraChangedAttached) {
viewer.camera.changed.addEventListener(parts.viewport.onCameraChanged);
state._cameraChangedRemove = parts.renderer.onCameraChanged(
parts.viewport.onCameraChanged,
);
borrowCameraSensitivity(viewer);
state._cameraChangedAttached = true;
}
if (!state._preRenderRemove) {
state._preRenderRemove = viewer.scene.preRender.addEventListener(
state._preRenderRemove = parts.renderer.onPreRender(
parts.rendering.onPreRender,
);
}
parts.viewport.runProximityCheck();
restoreSpriteOrder(viewer);
parts.renderer.restoreOrder();
},
/**
@@ -222,9 +222,8 @@ export function createLifecycle({ state, services, parts }) {
parts.selection.removeClickHandler();
unregisterPickOwner('transit');
if (state._cameraChangedAttached) {
viewer.camera.changed.removeEventListener(
parts.viewport.onCameraChanged,
);
state._cameraChangedRemove?.();
state._cameraChangedRemove = null;
returnCameraSensitivity(viewer);
state._cameraChangedAttached = false;
}
@@ -281,16 +280,9 @@ export function createLifecycle({ state, services, parts }) {
*/
destroy(viewer) {
this.disable(viewer);
if (state._markers) {
unregisterSpriteCollection('transit', state._markers);
viewer?.scene?.primitives?.remove(state._markers);
state._markers = null;
}
if (state._animatedMarkers) {
unregisterSpriteCollection('transit-motion', state._animatedMarkers);
viewer?.scene?.primitives?.remove(state._animatedMarkers);
state._animatedMarkers = null;
}
parts.renderer?.destroy();
parts.renderer = null;
state._markers = state._animatedMarkers = null;
state._overlayHost.clearSource(TRANSIT_SELECTED_OVERLAY_SOURCE_ID);
parts.height.clear();
unbindStyleEvents();