import { type HelixSceneV2, type SceneBounds, type SceneQuaternion, type SceneShadow, type SceneVec3 } from '@hypersoniclabs/helix-manifest'; export interface ComposeMountEntry { /** Document-local mount id, e.g. `mount.exterior`. */ id: string; /** The child's published entry URL (`.../scene-v2//scene.helix-scene.json`). */ entryUrl?: string; /** Path to a `scene-source publish` receipt; its `receipt.scene.entryUrl` is used. */ receipt?: string; /** Path to a local child document. Offline authoring; publication is NOT proven. */ document?: string; /** Which of the child's profiles to instantiate. Defaults to the parent's profile id. */ profile?: string; position?: SceneVec3; rotation?: SceneQuaternion; /** Uniform positive scale. A mount transform may not be non-uniform or mirrored. */ scale?: number; mode?: 'eager' | 'distance'; priority?: number; /** Override the activation volume. Defaults to the child's own composed footprint. */ bounds?: SceneBounds; /** Metres of slack added around the derived footprint. Default 2. */ padM?: number; /** Free-form label carried into the receipt. SceneNode has no name field. */ name?: string; } export interface ComposeMountsPlan { sceneId: string; revision: string; title: string; profile?: string; memoryBudgetMiB?: number; streamRadiusM?: number; environment?: Partial; /** Optional immutable Vault sky descriptor owned by this root composition. */ environmentResource?: { assetId: string; revision: number; integritySha256: string; bytes?: number; mimeType?: string; required?: boolean; /** Proof source for the immutable Vault revision written into the package receipt. */ confirmation?: { apiUrl: string; visibility: string; confirmedAt: string; }; }; /** Root/global physical lights. Mounted children keep only resident practicals. */ lights?: ComposeLightEntry[]; /** Renderer hints for the composed world. Defaults to the first child's. */ runtimeExtensions?: HelixSceneV2['runtimeExtensions']; spawn?: { position: SceneVec3; rotation?: SceneQuaternion; clearanceRadiusM?: number; clearanceHeightM?: number; }; attribution: { license: string; licenseUrl: string; creator: string; title?: string; url: string; }; mounts: ComposeMountEntry[]; } type ComposeLightBase = { id: string; position?: SceneVec3; rotation?: SceneQuaternion; color: string; shadow?: SceneShadow; required?: boolean; }; export type ComposeLightEntry = ComposeLightBase & ({ type: 'directional'; illuminanceLux: number; } | { type: 'point'; luminousIntensityCandela: number; rangeM: number; } | { type: 'spot'; luminousIntensityCandela: number; rangeM: number; innerConeDeg: number; outerConeDeg: number; }); export interface ResolvedChild { entry: ComposeMountEntry; /** Where the bytes came from, verbatim, for the receipt. */ origin: string; /** True only when the bytes were read back over the network from the lane. */ published: boolean; scene: HelixSceneV2; sha256: string; profileId: string; budgetMiB: number; depth: number; /** The child's own footprint, in child space, before the mount transform. */ childBounds: SceneBounds; } export interface ComposeMountsResult { scene: HelixSceneV2; sceneBytes: number; mounts: Array<{ id: string; scene: string; revision: string; sha256: string; budgetMiB: number; depth: number; published: boolean; bounds: SceneBounds; mode: string; }>; mountDepth: number; memoryBudgetMiB: number; streamRadiusM: number; bounds: SceneBounds; warnings: string[]; } type Fetcher = (url: string) => Promise<{ ok: boolean; status: number; bytes: Buffer; }>; /** * Read one child's bytes and answer every question the backend's `resolveMount` * will ask, before a single byte of the parent is written. * * The child is addressed by its own document digest, which is also its storage * address, so a fetched document that hashes to something else is not a stale * mirror to tolerate — it is a different document, and the pin would be a lie. */ export declare function resolveChildScene(entry: ComposeMountEntry, options: { defaultProfile: string; fetchImpl?: Fetcher; }): Promise; /** * A child's footprint, taken from the activation volumes it already authored. * * Stream-cell bounds are the child compiler's own measurement of where its * geometry is; node transforms are pivots and would under-report a mesh that * extends away from its origin. Cells outside the mounted profile's root are * not loaded, so they are not part of the footprint either. */ export declare function sceneFootprint(scene: HelixSceneV2, profileId: string): SceneBounds; /** Rotate/scale/translate an AABB's eight corners and re-fit an AABB to them. */ export declare function transformBounds(bounds: SceneBounds, position: SceneVec3, rotation: SceneQuaternion, scale: number): SceneBounds; /** * Build the parent document. * * One mount = one node = one stream group = one cell. A mount node's TRANSFORM * places the child's geometry; the CELL's bounds decide when it activates, and * the two are independent on purpose: children cut out of one shared coordinate * space are mounted at identity and would otherwise all sit in one cell at the * origin and stream as a single unit. */ export declare function composeMountedScene(plan: ComposeMountsPlan, children: ResolvedChild[]): ComposeMountsResult; /** * Resolve every child, compose the parent, and write a package directory that * `scene-source publish` accepts as-is. */ export declare function composeMountsPackage(input: { plan: ComposeMountsPlan; outputDir: string; fetchImpl?: Fetcher; }): Promise; export declare function readComposePlan(path: string): Promise; export {};