import * as THREE from "three"; import { CollapseState, type Theme, type ThemeInput, type ControlType, type UpDirection, type AnimationMode, type ActiveTab, type ZebraColorScheme, type ZebraMappingMode, type StudioBackground, type StudioToneMapping, type StudioTextureMapping, type Keymap, type StateChange, type StateSubscriber, type GlobalStateSubscriber, type SubscribeOptions, type RenderOptions, type ViewerOptions, type StudioOptions } from "./types"; /** * Display configuration defaults */ interface DisplayDefaults { theme: Theme; cadWidth: number; treeWidth: number; treeHeight: number; height: number; pinning: boolean; glass: boolean; tools: boolean; keymap: Keymap; newTreeBehavior: boolean; measureTools: boolean; selectTool: boolean; explodeTool: boolean; zscaleTool: boolean; zebraTool: boolean; studioTool: boolean; measurementDebug: boolean; } /** * Render configuration defaults */ interface RenderDefaults { ambientIntensity: number; directIntensity: number; metalness: number; roughness: number; defaultOpacity: number; edgeColor: number; normalLen: number; } /** * Viewer/view configuration defaults */ interface ViewerDefaults { axes: boolean; axes0: boolean; grid: [boolean, boolean, boolean]; ortho: boolean; transparent: boolean; blackEdges: boolean; collapse: CollapseState; clipIntersection: boolean; clipPlaneHelpers: boolean; clipObjectColors: boolean; clipNormal0: THREE.Vector3; clipNormal1: THREE.Vector3; clipNormal2: THREE.Vector3; clipSlider0: number; clipSlider1: number; clipSlider2: number; control: ControlType; holroyd: boolean; up: UpDirection; ticks: number; gridFontSize: number; centerGrid: boolean; position: THREE.Vector3 | null; quaternion: THREE.Quaternion | null; target: THREE.Vector3 | null; zoom: number; panSpeed: number; rotateSpeed: number; zoomSpeed: number; timeit: boolean; } /** * Zebra tool defaults */ interface ZebraDefaults { zebraCount: number; zebraOpacity: number; zebraDirection: number; zebraColorScheme: ZebraColorScheme; zebraMappingMode: ZebraMappingMode; } /** * Studio mode defaults */ interface StudioModeDefaults { studioEnvironment: string; studioEnvIntensity: number; studioBackground: StudioBackground; studioToneMapping: StudioToneMapping; studioExposure: number; studio4kEnvMaps: boolean; studioTextureMapping: StudioTextureMapping; studioEnvRotation: number; studioShadowIntensity: number; studioShadowSoftness: number; studioAOIntensity: number; } /** * Runtime state defaults */ interface RuntimeDefaults { activeTool: string | null; animationMode: AnimationMode; animationSliderValue: number; zscaleActive: boolean; highlightedButton: string | null; activeTab: ActiveTab; } /** * Complete state shape */ type StateShape = DisplayDefaults & RenderDefaults & ViewerDefaults & ZebraDefaults & StudioModeDefaults & RuntimeDefaults; /** * Keys of the state shape */ type StateKey = keyof StateShape; /** * Options that can be passed to ViewerState constructor. * Accepts StateShape properties plus an index signature for runtime validation. */ type ViewerStateOptions = Partial & { theme?: ThemeInput; } & { [key: string]: unknown; }; /** * External notification payload - single key/change pair */ type ExternalNotification = { key: string; change: StateChange; }; /** * Centralized state management for the viewer. * * ViewerState is the single source of truth for all viewer configuration: * - Display settings (theme, dimensions, tools enabled) * - Render settings (lighting, materials) * - View settings (camera, clipping, grid) * - Runtime state (active tool, animation) * * ## Observable Pattern * State changes can be observed via `subscribe()`: * ```typescript * const unsubscribe = state.subscribe("axes", (change) => { * console.log(`axes changed from ${change.old} to ${change.new}`); * }); * ``` * * ## Key Methods * - `get(key)`: Get current value * - `set(key, value)`: Set value (triggers subscribers) * - `subscribe(key, callback)`: Subscribe to changes * - `subscribeAll(callback)`: Subscribe to all changes * * ## Default Values * - `DISPLAY_DEFAULTS`: Theme, dimensions, tools * - `RENDER_DEFAULTS`: Lighting, materials * - `VIEWER_DEFAULTS`: Camera, clipping, grid * * @internal - This is an internal class used by Viewer */ declare class ViewerState { /** * Default values for display configuration */ static DISPLAY_DEFAULTS: DisplayDefaults; /** * Default values for render configuration */ static RENDER_DEFAULTS: RenderDefaults; /** * Default values for viewer/view configuration */ static VIEWER_DEFAULTS: ViewerDefaults; /** * Zebra tool settings */ static ZEBRA_DEFAULTS: ZebraDefaults; /** * Studio mode settings */ static STUDIO_MODE_DEFAULTS: StudioModeDefaults; /** * Runtime state (not from options, changes during execution) */ static RUNTIME_DEFAULTS: RuntimeDefaults; private _state; private _listeners; private _globalListeners; private _externalNotifyCallback; /** * Create a ViewerState instance */ constructor(options?: ViewerStateOptions); /** * Apply options to state, validating keys */ private _applyOptions; /** * Get a state value */ get(key: K): StateShape[K]; /** * Set a state value and notify listeners */ set(key: K, value: StateShape[K], notify?: boolean): void; /** * Update multiple state values at once */ private _update; /** * Update render state from RenderOptions. * RenderOptions types are directly compatible with StateShape. */ updateRenderState(options: RenderOptions, notify?: boolean): void; /** * Update viewer state from ViewerOptions. * Converts Vector3Tuple/QuaternionTuple to THREE objects. */ updateViewerState(options: ViewerOptions, notify?: boolean): void; /** * Update studio state from StudioOptions (shapes.studioOptions). * Maps short field names to prefixed state keys. */ updateStudioState(options: StudioOptions): void; /** * Get all state as a plain object (for serialization) */ getAll(): StateShape; /** * Subscribe to changes for a specific state key */ subscribe(key: K, listener: StateSubscriber, options?: SubscribeOptions): () => void; /** * Subscribe to all state changes */ subscribeAll(listener: GlobalStateSubscriber): () => void; /** * Set a callback for external notifications (e.g., to notify external clients). * The callback receives the notification key (snake_case) and the change object. */ setExternalNotifyCallback(callback: ((input: ExternalNotification | ExternalNotification[]) => void) | null): void; /** * Get all notifiable state values in external format. * Returns a dictionary with snake_case keys and StateChange values. * Used for initial config sync to external clients. */ getAllNotifiable(): Record>; private _notify; /** * Reset state to default values */ reset(options?: ViewerStateOptions): void; /** * Get all default values (useful for documentation/debugging) */ static getDefaults(): StateShape; /** * Dump all state values to console, organized by category */ dump(): void; } export { ViewerState }; export type { StateShape, StateKey, ViewerStateOptions };