mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
refactor(app): share application components and request services
This commit is contained in:
1 parent
a0a0128a59
commit
a67bc60a29
84 files changed
+2798
-1731
No files matched your search
Vendored
+1
-36
@@ -1,36 +1 @@
|
||||
import { StyleManager } from '../ui.js';
|
||||
import { flyToAustin } from '../camera.js';
|
||||
import { initCockpitCloudEffects } from '../cockpitCloudEffects.js';
|
||||
|
||||
/** Construct the existing controls and camera presentation. */
|
||||
export function createStandaloneControls({
|
||||
scene: { viewer, mapStackController },
|
||||
loaderStatus,
|
||||
placeSearch,
|
||||
defer,
|
||||
}) {
|
||||
// Initialize the style manager (post-processing, HUD, locations, share links)
|
||||
const styleManager = new StyleManager(viewer, {
|
||||
mapStackController,
|
||||
placeSearch,
|
||||
});
|
||||
defer(() => styleManager.orbitController.stop());
|
||||
defer(() => styleManager.hud.destroy());
|
||||
defer(() => styleManager.dispose());
|
||||
// The previous multi-canvas weather compositor remains disabled. Cockpit
|
||||
// clouds use a separate, capped low-resolution GPU pass that never attaches
|
||||
// Cesium fog or post-process stages and is fully stopped in map mode.
|
||||
const weatherEffects = null;
|
||||
const cockpitCloudEffects = initCockpitCloudEffects(viewer);
|
||||
defer(() => cockpitCloudEffects?.destroy());
|
||||
|
||||
// If no share link state, do default fly-to Austin
|
||||
if (!styleManager.hasShareState) {
|
||||
loaderStatus.textContent = 'Flying to Austin, TX...';
|
||||
defer(flyToAustin(viewer));
|
||||
} else {
|
||||
loaderStatus.textContent = 'Restoring shared view...';
|
||||
}
|
||||
|
||||
return { styleManager, weatherEffects, cockpitCloudEffects };
|
||||
}
|
||||
export { createApplicationControls as createStandaloneControls } from '../app/controls.js';
|
||||
+1
-80
@@ -1,80 +1 @@
|
||||
import { DataLayerManager } from '../data/manager.js';
|
||||
import flightsLayer from '../data/flights.js';
|
||||
import militaryFlightsLayer from '../data/militaryFlights.js';
|
||||
import alprCamerasLayer from '../data/alprCameras.js';
|
||||
import earthquakesLayer from '../data/earthquakes.js';
|
||||
import satellitesLayer from '../data/satellites.js';
|
||||
import rocketLaunchesLayer from '../data/rocketLaunches.js';
|
||||
import trafficLayer from '../data/traffic.js';
|
||||
import cctvLayer from '../data/cctv.js';
|
||||
import radioLayer from '../data/radio.js';
|
||||
import bikeshareLayer from '../data/bikeshare.js';
|
||||
import aisLiveVesselsLayer from '../data/aisLiveVessels.js';
|
||||
import militaryInstallationsLayer from '../data/militaryInstallations.js';
|
||||
import militaryAwarenessLayer from '../data/militaryAwareness.js';
|
||||
import localDataLayers from '../data/localLayers.js';
|
||||
import { LAYER_STATE_REGISTRY } from '../data/layerState.js';
|
||||
|
||||
/** Register the standalone layer catalog before allowing state restoration. */
|
||||
export function createStandaloneData({
|
||||
scene: { viewer },
|
||||
controls: { styleManager },
|
||||
allowQaRegistration,
|
||||
defer,
|
||||
}) {
|
||||
// Initialize data layer manager
|
||||
const dataManager = new DataLayerManager(viewer, {
|
||||
allowQaRegistration,
|
||||
});
|
||||
defer(async () => {
|
||||
await dataManager.destroyAll();
|
||||
if (dataManager.layers.size)
|
||||
throw new Error(
|
||||
`Data layers could not be destroyed: ${[...dataManager.layers.keys()].join(', ')}`,
|
||||
);
|
||||
});
|
||||
dataManager.register(flightsLayer);
|
||||
dataManager.register(militaryFlightsLayer);
|
||||
dataManager.register(earthquakesLayer);
|
||||
dataManager.register(alprCamerasLayer);
|
||||
dataManager.register(satellitesLayer);
|
||||
dataManager.register(rocketLaunchesLayer);
|
||||
rocketLaunchesLayer.attachDataManager(dataManager);
|
||||
dataManager.register(trafficLayer);
|
||||
dataManager.register(cctvLayer);
|
||||
dataManager.register(radioLayer);
|
||||
dataManager.register(bikeshareLayer);
|
||||
dataManager.register(aisLiveVesselsLayer);
|
||||
dataManager.register(militaryInstallationsLayer);
|
||||
dataManager.register(militaryAwarenessLayer);
|
||||
militaryAwarenessLayer.attachDataManager(dataManager);
|
||||
for (const layer of localDataLayers) {
|
||||
dataManager.register(layer);
|
||||
}
|
||||
// Restoration starts only after the complete production registry is sealed.
|
||||
dataManager.finalizeRegistrations(LAYER_STATE_REGISTRY);
|
||||
if (allowQaRegistration) {
|
||||
window.__gevQaRegisterLayer = (targetManager, layerModule) => {
|
||||
if (targetManager !== dataManager)
|
||||
throw new Error('QA layer manager mismatch');
|
||||
return dataManager.registerForQa(layerModule);
|
||||
};
|
||||
window.__gevQaUnregisterLayer = (targetManager, layerId) => {
|
||||
if (targetManager !== dataManager)
|
||||
throw new Error('QA layer manager mismatch');
|
||||
return dataManager.unregisterForQa(layerId);
|
||||
};
|
||||
const register = window.__gevQaRegisterLayer;
|
||||
const unregister = window.__gevQaUnregisterLayer;
|
||||
defer(() => {
|
||||
if (window.__gevQaRegisterLayer === register)
|
||||
delete window.__gevQaRegisterLayer;
|
||||
if (window.__gevQaUnregisterLayer === unregister)
|
||||
delete window.__gevQaUnregisterLayer;
|
||||
});
|
||||
}
|
||||
dataManager.buildTogglePanel(document.getElementById('data-toggles'));
|
||||
styleManager.attachDataManager(dataManager);
|
||||
|
||||
return { dataManager };
|
||||
}
|
||||
export { createApplicationData as createStandaloneData } from '../app/data.js';
|
||||
@@ -1,25 +1 @@
|
||||
/**
|
||||
* Extract a human-readable error message from any thrown value.
|
||||
* Handles Error objects, strings, and plain objects with message/error fields.
|
||||
* @param {*} error — caught exception value
|
||||
* @returns {string} best-effort error description
|
||||
*/
|
||||
export function describeError(error) {
|
||||
if (!error) return 'Unknown initialization error';
|
||||
if (error instanceof Error) {
|
||||
if (error.message && error.message.trim()) return error.message.trim();
|
||||
return error.name || 'Initialization error';
|
||||
}
|
||||
if (typeof error === 'string' && error.trim()) return error.trim();
|
||||
if (typeof error === 'object') {
|
||||
const maybeMessage = String(error.message || error.error || '').trim();
|
||||
if (maybeMessage) return maybeMessage;
|
||||
try {
|
||||
const serialized = JSON.stringify(error);
|
||||
if (serialized && serialized !== '{}') return serialized;
|
||||
} catch {
|
||||
// ignore serialization error
|
||||
}
|
||||
}
|
||||
return String(error);
|
||||
}
|
||||
export { describeError } from '../app/errors.js';
|
||||
+1
-105
@@ -1,105 +1 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { createApplicationViewer } from '../app/viewer.js';
|
||||
import { registerDataCredits } from '../data/dataCredits.js';
|
||||
import { configureCreditKeyboardAccess } from '../creditKeyboard.js';
|
||||
import { MapStackController } from '../mapStackController.js';
|
||||
import { loadPhotorealisticTileset } from '../mapStartup.js';
|
||||
import { initLogoGaze } from '../logoGaze.js';
|
||||
import { uninstallRenderGovernor } from '../renderGovernor.js';
|
||||
import { describeError } from './errors.js';
|
||||
|
||||
/** Construct the standalone globe using the caller's local configuration. */
|
||||
export async function createStandaloneScene({
|
||||
googleApiKey,
|
||||
cesiumToken,
|
||||
loaderStatus,
|
||||
signal,
|
||||
defer,
|
||||
}) {
|
||||
defer(initLogoGaze());
|
||||
const previousKey = window.__GOOGLE_MAPS_API_KEY__;
|
||||
if (googleApiKey) {
|
||||
window.__GOOGLE_MAPS_API_KEY__ = googleApiKey;
|
||||
defer(() => {
|
||||
if (window.__GOOGLE_MAPS_API_KEY__ !== googleApiKey) return;
|
||||
if (previousKey === undefined) delete window.__GOOGLE_MAPS_API_KEY__;
|
||||
else window.__GOOGLE_MAPS_API_KEY__ = previousKey;
|
||||
});
|
||||
}
|
||||
loaderStatus.textContent = 'Configuring viewer...';
|
||||
// Provider attribution stays visible, including clean-view and recording.
|
||||
const creditContainer = document.createElement('div');
|
||||
creditContainer.id = 'cesium-credits';
|
||||
document.body.appendChild(creditContainer);
|
||||
defer(() => creditContainer.remove());
|
||||
const viewer = createApplicationViewer({
|
||||
container: 'cesiumContainer',
|
||||
creditContainer,
|
||||
});
|
||||
defer(() => {
|
||||
uninstallRenderGovernor(viewer);
|
||||
if (!viewer.isDestroyed()) viewer.destroy();
|
||||
});
|
||||
registerDataCredits(viewer);
|
||||
configureCreditKeyboardAccess(document);
|
||||
loaderStatus.textContent =
|
||||
googleApiKey || cesiumToken
|
||||
? 'Loading Google 3D Tiles...'
|
||||
: 'Loading the keyless globe...';
|
||||
const photoreal = await loadPhotorealisticTileset(Cesium, {
|
||||
googleApiKey,
|
||||
cesiumToken,
|
||||
});
|
||||
const tileset = photoreal.tileset;
|
||||
// A provider can finish after cancellation; retain ownership of its result.
|
||||
defer(() => {
|
||||
if (tileset && !tileset.isDestroyed()) {
|
||||
if (!viewer.scene.primitives.remove(tileset)) tileset.destroy();
|
||||
}
|
||||
});
|
||||
signal.throwIfAborted();
|
||||
if (tileset) {
|
||||
viewer.scene.primitives.add(tileset);
|
||||
// NOTE: Cesium World Terrain intentionally disabled — conflicts with Google 3D Tiles at high zoom.
|
||||
// Google Photorealistic 3D Tiles provide their own terrain/elevation.
|
||||
viewer.scene.globe.show = false;
|
||||
console.info(`[Init] Google 3D Tiles loaded via ${photoreal.route}.`);
|
||||
} else {
|
||||
if (photoreal.errors.length) {
|
||||
const tileError = photoreal.errors.at(-1);
|
||||
console.warn(
|
||||
'[Init] Google 3D Tiles unavailable, using the keyless globe:',
|
||||
tileError,
|
||||
);
|
||||
const tileErrorDetail = describeError(tileError);
|
||||
loaderStatus.textContent = `Google 3D Tiles unavailable (${tileErrorDetail}). Loading the keyless globe...`;
|
||||
}
|
||||
viewer.scene.globe.show = true;
|
||||
}
|
||||
|
||||
loaderStatus.textContent = 'Initializing systems...';
|
||||
|
||||
const mapStackController = new MapStackController(viewer, {
|
||||
googleTileset: tileset,
|
||||
cesiumToken,
|
||||
initialStack: tileset ? 'photoreal' : 'esri-imagery',
|
||||
// Task 5 (height-datum fix): rebroadcast stack changes as a window
|
||||
// CustomEvent so data layers (CCTV per-regime ground resolution) can
|
||||
// react without coupling MapStackController to layer modules. Fires on
|
||||
// 'switching'/'ready'/'error'; listeners derive the surface regime from
|
||||
// live scene state, so intermediate emissions are harmless.
|
||||
onChange: (state) => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('gev:map-stack-changed', { detail: state }),
|
||||
);
|
||||
},
|
||||
onError: (message) => console.warn('[MapStack]', message),
|
||||
});
|
||||
defer(() => mapStackController.destroy());
|
||||
await mapStackController.setStack(tileset ? 'photoreal' : 'esri-imagery', {
|
||||
silent: true,
|
||||
});
|
||||
|
||||
signal.throwIfAborted();
|
||||
return { viewer, tileset, mapStackController };
|
||||
}
|
||||
export { createApplicationScene as createStandaloneScene } from '../app/scene.js';
|
||||
@@ -1,51 +1,8 @@
|
||||
import { initFirstRunExperience } from '../firstRunExperience.js';
|
||||
import { startApplicationChrome } from '../app/startupChrome.js';
|
||||
import { initKeySetup } from '../keySetup.js';
|
||||
|
||||
/** Reveal welcome controls only after restoration and the loading transition. */
|
||||
export function startStandaloneChrome({
|
||||
loadingScreen,
|
||||
styleManager,
|
||||
dataManager,
|
||||
signal,
|
||||
}) {
|
||||
let disposed = false;
|
||||
let firstRun;
|
||||
let revealTimer;
|
||||
let resolveDelay;
|
||||
const minimumDelay = new Promise((resolve) => {
|
||||
resolveDelay = resolve;
|
||||
export function startStandaloneChrome(options) {
|
||||
return startApplicationChrome({
|
||||
initializeSettings: initKeySetup,
|
||||
...options,
|
||||
});
|
||||
const delayTimer = setTimeout(resolveDelay, 1000);
|
||||
const revealFirstRun = () => {
|
||||
if (disposed || signal.aborted || firstRun) return;
|
||||
firstRun = initFirstRunExperience({ styleManager, dataManager });
|
||||
clearTimeout(revealTimer);
|
||||
loadingScreen.removeEventListener('transitionend', revealFirstRun);
|
||||
};
|
||||
void Promise.all([styleManager.initialRestorePromise, minimumDelay])
|
||||
.catch(() => {
|
||||
/* Restoration reports its own outcome through the controls. */
|
||||
})
|
||||
.then(() => {
|
||||
if (disposed || signal.aborted) return;
|
||||
loadingScreen.classList.add('hidden');
|
||||
loadingScreen.addEventListener('transitionend', revealFirstRun, {
|
||||
once: true,
|
||||
});
|
||||
revealTimer = setTimeout(revealFirstRun, 900);
|
||||
});
|
||||
const keySetup = initKeySetup({ signal });
|
||||
// Own the pending initializer too; it must not reveal a dialog after abort.
|
||||
void keySetup.catch(() =>
|
||||
console.error('Provider settings initialization failed'),
|
||||
);
|
||||
return async () => {
|
||||
disposed = true;
|
||||
clearTimeout(delayTimer);
|
||||
clearTimeout(revealTimer);
|
||||
resolveDelay();
|
||||
loadingScreen.removeEventListener('transitionend', revealFirstRun);
|
||||
firstRun?.destroy();
|
||||
(await keySetup.catch(() => null))?.destroy();
|
||||
};
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { readFileSync } from 'node:fs';
|
||||
import vm from 'node:vm';
|
||||
|
||||
const source = readFileSync(
|
||||
new URL('./startupChrome.js', import.meta.url),
|
||||
new URL('../app/startupChrome.js', import.meta.url),
|
||||
'utf8',
|
||||
)
|
||||
.replace(/^import .*;\n/gm, '')
|
||||
@@ -37,7 +37,8 @@ function fixture() {
|
||||
};
|
||||
vm.createContext(context);
|
||||
vm.runInContext(source, context);
|
||||
const stop = context.startStandaloneChrome({
|
||||
const stop = context.startApplicationChrome({
|
||||
initializeSettings: context.initKeySetup,
|
||||
loadingScreen: {
|
||||
classList: { add: (value) => events.push(value) },
|
||||
addEventListener: (type, listener) => listeners.set(type, listener),
|
||||
|
||||
+5
-117
@@ -1,120 +1,8 @@
|
||||
import { SceneDirector } from '../scenes/director.js';
|
||||
import { initAnnotations } from '../annotations/index.js';
|
||||
import { initGevVoiceCommands } from '../voice/gevRealtime.js';
|
||||
import { installScopeMask, destroyScopeMask } from '../scopeMask.js';
|
||||
import {
|
||||
installRenderGovernor,
|
||||
getRenderGovernorDiagnostics,
|
||||
governorRequestRender,
|
||||
holdContinuousRender,
|
||||
releaseContinuousRender,
|
||||
} from '../renderGovernor.js';
|
||||
import { createApplicationTools } from '../app/tools.js';
|
||||
import { startStandaloneChrome } from './startupChrome.js';
|
||||
|
||||
/** Attach scene tools, rendering listeners and the standalone debug handle. */
|
||||
export function createStandaloneTools({
|
||||
scene,
|
||||
controls,
|
||||
data,
|
||||
loadingScreen,
|
||||
placeSearch,
|
||||
voice = {},
|
||||
signal,
|
||||
defer,
|
||||
}) {
|
||||
const { viewer, tileset, mapStackController } = scene;
|
||||
const { styleManager, weatherEffects, cockpitCloudEffects } = controls;
|
||||
const { dataManager } = data;
|
||||
const sceneDirector = new SceneDirector(viewer, styleManager, dataManager);
|
||||
defer(() => sceneDirector.destroy());
|
||||
const annotations = initAnnotations({ viewer, tileset, placeSearch });
|
||||
defer(() => {
|
||||
if (window.__gevAnnotations === annotations) delete window.__gevAnnotations;
|
||||
annotations.destroy();
|
||||
export function createStandaloneTools(options) {
|
||||
return createApplicationTools({
|
||||
startChrome: startStandaloneChrome,
|
||||
...options,
|
||||
});
|
||||
defer(
|
||||
startStandaloneChrome({ loadingScreen, styleManager, dataManager, signal }),
|
||||
);
|
||||
// Idle render governor: flips the scene into requestRenderMode whenever
|
||||
// nothing animates per frame. Installed AFTER every module above has had
|
||||
// its chance to register pre-install holds. (perf wave 2)
|
||||
installRenderGovernor(viewer);
|
||||
|
||||
// Install the explicit scope mask used by the DISPLAY controls.
|
||||
installScopeMask(viewer);
|
||||
defer(() => destroyScopeMask());
|
||||
|
||||
// The follow camera recomputes the tracked target's dead-reckon position
|
||||
// every frame — tracking anything is a per-frame animation. (perf wave 2)
|
||||
const removeTrackingListener = viewer.trackedEntityChanged.addEventListener(
|
||||
() => {
|
||||
if (viewer.trackedEntity) holdContinuousRender('tracked-entity');
|
||||
else releaseContinuousRender('tracked-entity');
|
||||
},
|
||||
);
|
||||
|
||||
// Hidden-state suspension (perf wave 2): when the window/tab is hidden,
|
||||
// stop the default render loop outright — a hidden canvas repaints for
|
||||
// nobody, and browser rAF throttling still lets throttled frames burn
|
||||
// GPU. Holder/data state is untouched, so return is seamless: restore
|
||||
// the loop, refresh the one DOM surface we gated, render a frame.
|
||||
const syncVisibilitySuspension = () => {
|
||||
const hidden = document.hidden;
|
||||
viewer.useDefaultRenderLoop = !hidden;
|
||||
cockpitCloudEffects?.setSuspended?.(hidden);
|
||||
if (!hidden) {
|
||||
if (dataManager._panelRefreshPendingOnVisible) {
|
||||
dataManager._panelRefreshPendingOnVisible = false;
|
||||
dataManager._refreshTogglePanel();
|
||||
}
|
||||
governorRequestRender('visibility-restore');
|
||||
}
|
||||
};
|
||||
document.addEventListener('visibilitychange', syncVisibilitySuspension);
|
||||
defer(() =>
|
||||
document.removeEventListener('visibilitychange', syncVisibilitySuspension),
|
||||
);
|
||||
defer(() => {
|
||||
removeTrackingListener();
|
||||
releaseContinuousRender('tracked-entity');
|
||||
});
|
||||
// Apply the CURRENT state too — bootstrap can complete while the tab is
|
||||
// already hidden, and waiting for the next transition would leave the
|
||||
// loop burning behind a hidden tab. (perf wave 2 fix)
|
||||
syncVisibilitySuspension();
|
||||
|
||||
window.__godsEyeView = {
|
||||
viewer,
|
||||
styleManager,
|
||||
tileset,
|
||||
dataManager,
|
||||
sceneDirector,
|
||||
mapStackController,
|
||||
annotations,
|
||||
weatherEffects,
|
||||
cockpitCloudEffects,
|
||||
getRenderGovernorDiagnostics,
|
||||
requestRender: governorRequestRender,
|
||||
};
|
||||
const debug = window.__godsEyeView;
|
||||
defer(() => {
|
||||
if (window.__godsEyeView === debug) delete window.__godsEyeView;
|
||||
});
|
||||
const voiceCommands = initGevVoiceCommands({
|
||||
...voice,
|
||||
signal,
|
||||
placeSearch,
|
||||
viewer,
|
||||
styleManager,
|
||||
dataManager,
|
||||
sceneDirector,
|
||||
annotations,
|
||||
});
|
||||
defer(() => {
|
||||
voiceCommands.stop({ removeUi: true });
|
||||
if (window.__gevVoiceCommands === voiceCommands)
|
||||
delete window.__gevVoiceCommands;
|
||||
});
|
||||
debug.voiceCommands = voiceCommands;
|
||||
return { sceneDirector, annotations, voiceCommands };
|
||||
}
|
||||
+1
-153
@@ -1,153 +1 @@
|
||||
/** Compose UI controls with the application's existing engines and layer instances. */
|
||||
import { StyleManager as ApplicationShell } from '../ui/applicationShell.js';
|
||||
import { LocationSearch } from '../ui/location.js';
|
||||
import {
|
||||
CITY_POIS,
|
||||
GLOBE_VIEW,
|
||||
flyToGlobeView,
|
||||
flyToPresetLocation,
|
||||
flyToPOI,
|
||||
searchAndFlyTo,
|
||||
} from '../locations.js';
|
||||
import { interruptCameraMotion } from '../cameraVerbs.js';
|
||||
import { IntelHUD } from '../hud.js';
|
||||
import { ShareLinkManager } from '../sharelink.js';
|
||||
import { OrbitController } from '../orbit.js';
|
||||
import {
|
||||
CelestialRing,
|
||||
getKeyholeFadeTuning,
|
||||
isCelestialRingStyleSupported,
|
||||
setKeyholeFadeTuning,
|
||||
} from '../celestialRing.js';
|
||||
import {
|
||||
destroyTrackedReadout,
|
||||
initTrackedReadout,
|
||||
} from '../data/trackedReadout.js';
|
||||
import {
|
||||
destroyWorldOverlay,
|
||||
initWorldOverlay,
|
||||
} from '../overlays/worldOverlay.js';
|
||||
import {
|
||||
destroyDetection,
|
||||
initDetection,
|
||||
cycleMode as cycleDetectionMode,
|
||||
getDetectionDiagnostics as readDetectionDiagnostics,
|
||||
getDetectionTuning,
|
||||
getMode as getDetectionMode,
|
||||
setMode as setDetectionModeByLabel,
|
||||
suspendDetection,
|
||||
resumeDetection,
|
||||
setDetectionStyle,
|
||||
setDetectionTuning,
|
||||
} from '../data/detection.js';
|
||||
import trafficLayer from '../data/traffic.js';
|
||||
import flightsLayer from '../data/flights.js';
|
||||
import militaryFlightsLayer from '../data/militaryFlights.js';
|
||||
import { isTr3b, toggleTr3b } from '../data/tr3bRegistry.js';
|
||||
import satellitesLayer from '../data/satellites.js';
|
||||
import cctvLayer from '../data/cctv.js';
|
||||
import radioLayer from '../data/radio.js';
|
||||
import bikeshareLayer from '../data/bikeshare.js';
|
||||
import aisLiveVesselsLayer from '../data/aisLiveVessels.js';
|
||||
import militaryAwarenessLayer from '../data/militaryAwareness.js';
|
||||
import militaryInstallationsLayer from '../data/militaryInstallations.js';
|
||||
import rocketLaunchesLayer from '../data/rocketLaunches.js';
|
||||
import {
|
||||
cachedGroundFloor,
|
||||
cachedMeshFloor,
|
||||
GROUND_FLOOR_LIFT_M,
|
||||
meshFloorPreferred,
|
||||
warmGroundFloor,
|
||||
} from '../data/groundFloor.js';
|
||||
import { sampleMeshFloorCells } from '../data/meshFloorSampler.js';
|
||||
import {
|
||||
holdContinuousRender,
|
||||
releaseContinuousRender,
|
||||
governorRequestRender,
|
||||
} from '../renderGovernor.js';
|
||||
import {
|
||||
setScopeMaskEnabled,
|
||||
isScopeMaskEnabled,
|
||||
setScopeMaskFeather,
|
||||
getScopeMaskFeather,
|
||||
setScopeTerminusOverride,
|
||||
getScopeTerminusOverride,
|
||||
clampScopeTerminusPct,
|
||||
} from '../scopeMask.js';
|
||||
import {
|
||||
fetchRegionalBrief,
|
||||
regionalDistanceM,
|
||||
weatherCodeLabel,
|
||||
} from '../data/regionalBrief.js';
|
||||
|
||||
export class StyleManager extends ApplicationShell {
|
||||
constructor(viewer, options = {}) {
|
||||
super(viewer, {
|
||||
...options,
|
||||
services: {
|
||||
CITY_POIS,
|
||||
GLOBE_VIEW,
|
||||
flyToGlobeView,
|
||||
flyToPresetLocation,
|
||||
flyToPOI,
|
||||
searchAndFlyTo,
|
||||
interruptCameraMotion,
|
||||
IntelHUD,
|
||||
ShareLinkManager,
|
||||
OrbitController,
|
||||
CelestialRing,
|
||||
getKeyholeFadeTuning,
|
||||
isCelestialRingStyleSupported,
|
||||
setKeyholeFadeTuning,
|
||||
destroyTrackedReadout,
|
||||
initTrackedReadout,
|
||||
destroyWorldOverlay,
|
||||
initWorldOverlay,
|
||||
destroyDetection,
|
||||
initDetection,
|
||||
cycleDetectionMode,
|
||||
readDetectionDiagnostics,
|
||||
getDetectionTuning,
|
||||
getDetectionMode,
|
||||
setDetectionModeByLabel,
|
||||
suspendDetection,
|
||||
resumeDetection,
|
||||
setDetectionStyle,
|
||||
setDetectionTuning,
|
||||
trafficLayer,
|
||||
flightsLayer,
|
||||
militaryFlightsLayer,
|
||||
isTr3b,
|
||||
toggleTr3b,
|
||||
satellitesLayer,
|
||||
cctvLayer,
|
||||
radioLayer,
|
||||
bikeshareLayer,
|
||||
aisLiveVesselsLayer,
|
||||
militaryAwarenessLayer,
|
||||
militaryInstallationsLayer,
|
||||
rocketLaunchesLayer,
|
||||
cachedGroundFloor,
|
||||
cachedMeshFloor,
|
||||
GROUND_FLOOR_LIFT_M,
|
||||
meshFloorPreferred,
|
||||
warmGroundFloor,
|
||||
sampleMeshFloorCells,
|
||||
holdContinuousRender,
|
||||
releaseContinuousRender,
|
||||
governorRequestRender,
|
||||
setScopeMaskEnabled,
|
||||
isScopeMaskEnabled,
|
||||
setScopeMaskFeather,
|
||||
getScopeMaskFeather,
|
||||
setScopeTerminusOverride,
|
||||
getScopeTerminusOverride,
|
||||
clampScopeTerminusPct,
|
||||
fetchRegionalBrief,
|
||||
regionalDistanceM,
|
||||
weatherCodeLabel,
|
||||
LocationSearch,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
export { StyleManager } from '../ui/composition.js';
|
||||
Reference in new issue
Block a user