/** * Unified hover cursor — one primitive that paints a hovered tile across * the three boards (sol, liquid, atmo). * * Two independently-togglable visual primitives share the same dispatch: * * - **Ring** : pre-allocated quad-strip border tracing the tile's * boundary; placed on the layer's cap top, plus an * optional seabed twin (`floorRing`) on liquid hovers. * - **Emissive** : `THREE.PointLight` repositioned at mid-prism so the * glow reaches a few neighbour rings without baking * shadows. Single light, reused across hovers. * * The geometry per layer comes from caller-provided ports — the cursor * itself never reads sim state nor hexasphere caches, so the primitive * stays decoupled from the orchestrator's internals. */ import * as THREE from 'three'; import type { Tile } from '../../geometry/hexasphere.types'; import type { HoverCursorConfig } from '../types/hoverCursor.types'; import type { BoardTileRef, HoverPlacementOptions } from '../types/bodyHandle.types'; import type { HoverChannel } from '../state/hoverState'; import type { HoverListener } from '../hex/hexMeshShared'; /** Per-layer geometry resolver — caller-side, no sim coupling. */ export interface LayerCursorPort { /** Tile lookup on the layer's hexasphere. Returns `null` for unknown ids. */ getTile(tileId: number): Tile | null; /** * World radius of the tile's visible top (sol cap, waterline, atmo cap). * Drives ring placement. */ getCapRadius(tileId: number): number; /** * World radius of the prism floor (sol: core, liquid: seabed, atmo: * solOuter). Drives the light position (mid-prism) and the floor * ring's seabed placement on liquid hovers. Falls back to the cap * when omitted — the light then sits flush on the cap top. */ getFloorRadius?(tileId: number): number; } /** * Liquid layer carries a "core window" guard so the floor ring can be * tinted red when the underlying sol has been mined to the core (the * ocean tile has no solid floor at this spot). */ export interface LiquidCursorPort extends LayerCursorPort { /** True when the underlying sol is dug to the core (no seabed prism). */ isCoreWindow(tileId: number): boolean; } /** Construction-time ports shared by every primitive. */ export interface HoverCursorPorts { /** Body root group — the cursor primitives mount here. */ group: THREE.Group; /** World-space body radius — used as default scale for `emissive.size`. */ bodyRadius: number; /** Hover-channel slot publication consumed by ``. */ hoverChannel: HoverChannel; /** Sol layer port — always present. */ sol: LayerCursorPort; /** Liquid layer port — `null` on dry / frozen bodies. */ liquid: LiquidCursorPort | null; /** Atmo layer port — `null` on bodies without an atmo board. */ atmo: LayerCursorPort | null; } /** Public surface of the unified hover cursor. */ export interface HoverCursorHandle { /** * Routes a hover update to the right layer. `null` clears every * primitive (rings hidden, light off) and resets the hover channel * slot. */ setBoardTile(ref: BoardTileRef | null, options?: HoverPlacementOptions): void; /** * Re-applies the current hover (re-reads cap / floor / sea level via * the ports). Call after a tile mutation that changed the hovered * tile's geometry — e.g. a sol-height dig. */ refresh(): void; /** * Live mutation of the cursor visuals. Only primitives that were * constructed (i.e. not `false` at build time) can be tuned this way; * passing values for disabled primitives is silently ignored. * * Color / intensity changes apply immediately. Size changes (ring, * emissive distance) take effect on the next `apply` — calling * {@link refresh} replays the current hover so a slider drag updates * the live ring shape. */ updateConfig(partial: HoverCursorConfig): void; /** * Subscribes to hovered sol-tile id changes. Atmo / liquid hovers fire * `null` (the listener watches the sol board only). Returns an * unsubscribe. */ onHoverChange(listener: HoverListener): () => void; /** Current hovered sol tile id — `null` outside of sol hovers. */ getHoverId(): number | null; /** * Live snapshot of every Three.js object the cursor owns (cap ring, * floor ring, emissive light). Excludes primitives that were disabled * at build time (no GPU resource allocated). Used by the body's * `warmup` to compile cursor shaders into a dedicated phase rather * than mixing them with the rest of the body group. */ objects(): readonly THREE.Object3D[]; /** Releases GPU resources. Idempotent. */ dispose(): void; } /** * Builds the unified hover cursor from a {@link HoverCursorConfig} and * the per-layer ports. The returned handle drives all three primitives * through a single `setBoardTile` entry point — the orchestrator routes * raycaster hits in, the cursor renders the right visuals out. */ export declare function buildHoverCursor(config: HoverCursorConfig | undefined, ports: HoverCursorPorts): HoverCursorHandle; //# sourceMappingURL=buildHoverCursor.d.ts.map