Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/packages/firebird-ng/api/src/lib/tokens.ts is written in an unsupported language. File is not indexed.

0001 /**
0002  * The DI tokens of the Firebird extension system.
0003  *
0004  * Every extensible surface follows one pattern: contributions are declared in
0005  * DI as multi-providers (via the `with*()` features in firebird-features.ts),
0006  * collected by core services, and called through narrow lifecycle interfaces.
0007  * Nothing registers itself via import side effects.
0008  *
0009  * Built-ins are first consumers: Firebird's own factories, painters, loaders
0010  * and command handlers ride these same tokens (see with-firebird-builtins.ts).
0011  *
0012  * Precedence, the same for every registry: contributions keep registration
0013  * order (the order of the `provideFirebird()` arguments, depth first, after
0014  * Firebird's built-ins). A later contribution with the id of an earlier one
0015  * replaces it at the earlier one's position. Where one entry is picked among
0016  * several, the earliest wins: the first loader that claims a source loads
0017  * it, the first painter registered for a piece type is its default. The ids:
0018  * feature ids, `DataLoaderMeta.id`, `CommandHandler.type`,
0019  * `EventPieceFactory.type`, `PainterMeta.id`, and the `id` or `name` of tabs,
0020  * themes, post-processors, camera presets and toolbar actions. To take over
0021  * a built-in, register under its id or remove it with `withoutFeatures()`.
0022  *
0023  * The generic tokens (COMMAND_HANDLERS, CONFIG_DEFAULTS, URL_ALIASES,
0024  * URL_SHORTHANDS) come from `@dexvis/app-features`; `@dexvis/firebird-ng`
0025  * re-exports them.
0026  *
0027  * Token descriptions exist in development builds only (the Angular idiom):
0028  * this file is in the initial bundle, and production builds define
0029  * `ngDevMode` as false and drop the strings.
0030  */
0031 
0032 import { InjectionToken, Type, inject } from '@angular/core';
0033 import { type AppCommand, resolveRegistry } from '@dexvis/app-features';
0034 import type {
0035   EventPieceFactory,
0036   PiecePainterConstructor,
0037   GeometryDataLoader,
0038   EventDataLoader,
0039   DataCatalog,
0040 } from '@dexvis/firebird-core';
0041 import type { Object3D } from 'three';
0042 import type { ThreeExtension, LazyThreeExtensionLoader } from './three-extension';
0043 import type {
0044   GeometryPostProcessorRegistration,
0045   GeometryThemeRegistration,
0046   RootGeometryRulesSource,
0047 } from './geometry-pipeline';
0048 
0049 /**
0050  * One painter registration: which piece type it paints and with what class.
0051  * Either `painterClass` (eager) or `load` (lazy — keeps heavy painter code
0052  * out of the initial bundle; resolved before the first event is painted).
0053  */
0054 export interface PainterRegistration {
0055   forPieceType: string;
0056   painterClass?: PiecePainterConstructor;
0057   load?: () => Promise<PiecePainterConstructor>;
0058 }
0059 
0060 /**
0061  * One tab of the data selector (the "open data" control shown in the display
0062  * toolbar panel and on the config page). The component loads lazily so tab UI
0063  * code (Material, forms) stays out of the initial bundle. Tabs sort by
0064  * `order`, then registration order.
0065  */
0066 export interface DataSelectorTabRegistration {
0067   /** Stable id, e.g. 'presets', 'physics', 'manual'. A later tab with the same id replaces this one. */
0068   id: string;
0069   /** Tab caption. */
0070   label: string;
0071   /** Sort key; built-ins use 10, 20, 30. */
0072   order?: number;
0073   /** Resolves the tab component. It reads and writes `DataSelectionService.draft`. */
0074   load: () => Promise<Type<unknown>>;
0075   /**
0076    * When false, the tab is offered even with an empty catalog. Default true:
0077    * a tab that only lists catalog content hides itself when there is none.
0078    */
0079   needsCatalog?: boolean;
0080 }
0081 
0082 /** Event piece factories (DEX type string -> model object decoder). */
0083 export const EVENT_PIECE_FACTORIES = new InjectionToken<EventPieceFactory[]>(
0084   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.event-piece-factories' : '');
0085 
0086 /** Painter registrations consumed by EventDisplayService's DataModelPainter. */
0087 export const PAINTERS = new InjectionToken<PainterRegistration[]>(
0088   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.painters' : '');
0089 
0090 /** Rendering-machinery extensions, instantiated eagerly through DI. */
0091 export const THREE_EXTENSIONS = new InjectionToken<ThreeExtension[]>(
0092   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.three-extensions' : '');
0093 
0094 /** Lazily-loaded extensions: resolved after init, off the critical path. */
0095 export const LAZY_THREE_EXTENSIONS = new InjectionToken<LazyThreeExtensionLoader[]>(
0096   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.lazy-three-extensions' : '');
0097 
0098 /** Geometry format/scheme loaders. Read them through `injectGeometryLoaders()`. */
0099 export const GEOMETRY_LOADERS = new InjectionToken<GeometryDataLoader[]>(
0100   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.geometry-loaders' : '');
0101 
0102 /** Event data format loaders. Read them through `injectEventLoaders()`. */
0103 export const EVENT_LOADERS = new InjectionToken<EventDataLoader[]>(
0104   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.event-loaders' : '');
0105 
0106 /** Data catalogs: datasets an installation offers (presets, tags, URL lists). Merged in order. */
0107 export const DATA_CATALOGS = new InjectionToken<DataCatalog[]>(
0108   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.data-catalogs' : '');
0109 
0110 /** Tabs of the data selector control. */
0111 export const DATA_SELECTOR_TABS = new InjectionToken<DataSelectorTabRegistration[]>(
0112   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.data-selector-tabs' : '');
0113 
0114 /** Pre-build TGeo rules, posted to the geometry worker with each load (see geometry-pipeline.ts). */
0115 export const ROOT_GEOMETRY_RULES = new InjectionToken<RootGeometryRulesSource[]>(
0116   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.root-geometry-rules' : '');
0117 
0118 /** Geometry themes, selected by config `geometry.themeName`. */
0119 export const GEOMETRY_THEMES = new InjectionToken<GeometryThemeRegistration[]>(
0120   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.geometry-themes' : '');
0121 
0122 /** Main-thread geometry post-processors, run after each geometry load. */
0123 export const GEOMETRY_POST_PROCESSORS = new InjectionToken<GeometryPostProcessorRegistration[]>(
0124   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.geometry-post-processors' : '');
0125 
0126 // ---------------------------------------------------------------------------
0127 // Camera
0128 // ---------------------------------------------------------------------------
0129 
0130 /** An [x, y, z] triple in world coordinates (mm). */
0131 export type Vec3Tuple = [number, number, number];
0132 
0133 /**
0134  * A named camera view for the `camera-preset` command, the navigation
0135  * cube's home button and the camera debug panel. Two shapes:
0136  *
0137  * - a fixed pose: `position`, `target` and optionally `up`;
0138  * - a view direction: the camera looks along `-direction` with `up` as the
0139  *   screen up. It keeps the current orbit target and distance, unless
0140  *   `fitGeometry` is set: then it centers the loaded geometry's bounding
0141  *   sphere and backs off until the sphere fits the view.
0142  */
0143 export type CameraPreset =
0144   | { name: string; label?: string; position: Vec3Tuple; target: Vec3Tuple; up?: Vec3Tuple }
0145   | { name: string; label?: string; direction: Vec3Tuple; up: Vec3Tuple; fitGeometry?: boolean };
0146 
0147 /** Camera presets. A later preset with the same name replaces the earlier one. */
0148 export const CAMERA_PRESETS = new InjectionToken<CameraPreset[]>(
0149   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.camera-presets' : '');
0150 
0151 /** The registered camera presets, after the registry rule (same name: later replaces in place). */
0152 export function injectCameraPresets(): CameraPreset[] {
0153   return resolveRegistry(inject(CAMERA_PRESETS, { optional: true }) ?? [], preset => preset.name);
0154 }
0155 
0156 /**
0157  * Orbit distance limits [mm] of every view. Without them, each geometry load
0158  * derives them from the geometry's bounding sphere (radius r): 0.05 r to 5 r.
0159  */
0160 export interface CameraLimits {
0161   minDistance: number;
0162   maxDistance: number;
0163 }
0164 
0165 /** Pinned camera limits (`withCameraLimits`); absent means derived from the geometry. */
0166 export const CAMERA_LIMITS = new InjectionToken<CameraLimits>(
0167   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.camera-limits' : '');
0168 
0169 // ---------------------------------------------------------------------------
0170 // Collision intro
0171 // ---------------------------------------------------------------------------
0172 
0173 /**
0174  * A short animation played before an event's time animation, typically the
0175  * beams flying in and colliding. One instance per playback. The display
0176  * drives it: live from the render loop, frame by frame in offline
0177  * recordings, so `update()` must depend on `elapsedMs` alone.
0178  */
0179 export interface CollisionIntro {
0180   /** Length of the intro [ms]. */
0181   readonly durationMs: number;
0182   /** Builds the intro objects under `parent`, part of the event data (never clipped). */
0183   begin(parent: Object3D): void;
0184   /** Shows the state `elapsedMs` after the start, 0 to `durationMs`. */
0185   update(elapsedMs: number): void;
0186   /** Removes and disposes everything `begin()` built. */
0187   end(): void;
0188 }
0189 
0190 /** Resolves the intro class through a dynamic import (intros pull three.js). */
0191 export type CollisionIntroLoader = () => Promise<new () => CollisionIntro>;
0192 
0193 /** The collision intro (`withCollisionIntro`); absent means none. */
0194 export const COLLISION_INTRO = new InjectionToken<CollisionIntroLoader>(
0195   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.collision-intro' : '');
0196 
0197 // ---------------------------------------------------------------------------
0198 // UI contributions
0199 // ---------------------------------------------------------------------------
0200 
0201 /**
0202  * A button in the display's time toolbar (the playback controls under the
0203  * scene), placed after the rewind button. A click dispatches `command`
0204  * through the command bus with source 'ui', so the same action is
0205  * reachable from deep links and batch.
0206  */
0207 export interface ToolbarActionRegistration {
0208   /** Identity: a later action with the same id replaces this one. */
0209   id: string;
0210   /** Material Symbols icon name. */
0211   icon: string;
0212   /** Accessible name of the button. */
0213   label: string;
0214   tooltip?: string;
0215   command: AppCommand;
0216 }
0217 
0218 /** Toolbar actions, in registration order. */
0219 export const TOOLBAR_ACTIONS = new InjectionToken<ToolbarActionRegistration[]>(
0220   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.toolbar-actions' : '');
0221 
0222 /** The registered toolbar actions, after the registry rule (same id: later replaces in place). */
0223 export function injectToolbarActions(): ToolbarActionRegistration[] {
0224   return resolveRegistry(inject(TOOLBAR_ACTIONS, { optional: true }) ?? [], action => action.id);
0225 }
0226 
0227 // ---------------------------------------------------------------------------
0228 // Web workers
0229 // ---------------------------------------------------------------------------
0230 
0231 /**
0232  * Starts the application's web workers. Each factory creates a worker from
0233  * an entry module the application owns, so that its bundler builds the
0234  * worker: a `new Worker(new URL(...))` inside a prebuilt library is not
0235  * bundled and fails with a 404 at runtime. The entry modules call the run
0236  * functions of `@dexvis/firebird-ng/workers/geometry` and
0237  * `@dexvis/firebird-ng/workers/root-file`.
0238  */
0239 export interface FirebirdWorkers {
0240   /** The ROOT geometry worker (entry: `runGeometryWorker(self)`). */
0241   geometry: () => Worker;
0242   /** The ROOT file worker: probing and in-browser conversion (entry: `runRootFileWorker(self)`). */
0243   rootFile: () => Worker;
0244 }
0245 
0246 /** The worker factories (`withWorkers`); without them ROOT geometry and in-browser conversion fail with a message naming the feature. */
0247 export const FIREBIRD_WORKERS = new InjectionToken<FirebirdWorkers>(
0248   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.workers' : '');
0249 
0250 /**
0251  * The application's version, shown in the logo menu of the display chrome
0252  * (`withAppVersion`); absent means the menu shows none.
0253  */
0254 export const APP_VERSION = new InjectionToken<string>(
0255   typeof ngDevMode !== 'undefined' && ngDevMode ? 'firebird.app-version' : '');
0256 
0257 // ---------------------------------------------------------------------------
0258 // Registry access with the precedence rule applied
0259 // ---------------------------------------------------------------------------
0260 
0261 /**
0262  * The registered event loaders, in the order they are asked: registration
0263  * order, a later loader with the same `meta.id` replacing an earlier one in
0264  * place. The first loader whose `canLoad()` accepts a source loads it.
0265  */
0266 export function injectEventLoaders(): EventDataLoader[] {
0267   return resolveRegistry(inject(EVENT_LOADERS, { optional: true }) ?? [], loader => loader.meta.id);
0268 }
0269 
0270 /** The registered geometry loaders; same rule as `injectEventLoaders()`. */
0271 export function injectGeometryLoaders(): GeometryDataLoader[] {
0272   return resolveRegistry(inject(GEOMETRY_LOADERS, { optional: true }) ?? [], loader => loader.meta.id);
0273 }