import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { LightingOptions, AnimatedModel, AnimatedModelOptions, PhysicsOptions, PhysicsBodyOptions } from '../types';
import * as THREE from "three";
import type * as CANNON from "cannon-es";
export declare class SceneCreator {
    scene: THREE.Scene;
    renderer: THREE.WebGLRenderer;
    container: HTMLElement | undefined;
    cWidth: number;
    cHeight: number;
    camera: THREE.PerspectiveCamera;
    initialCamPos: THREE.Vector3;
    initialTargetPos: THREE.Vector3;
    prevCamPos: THREE.Vector3;
    controls: OrbitControls | undefined;
    additionalRenderFn: (() => void) | undefined;
    stopLoop: boolean;
    scale: number;
    animating: number;
    private tweens;
    private mixers;
    private lastFrameTime?;
    physicsWorld?: CANNON.World;
    private physicsBodies;
    private physicsFixedStep;
    private physicsMaxSubSteps;
    private cannon?;
    raycaster: THREE.Raycaster;
    mouse: THREE.Vector2;
    selectedObject: THREE.Object3D | null;
    pickingEnabled: boolean;
    onObjectClick: ((obj: THREE.Object3D) => void) | undefined;
    onObjectHover: ((obj: THREE.Object3D | null) => void) | undefined;
    onObjectContextMenu: ((obj: THREE.Object3D) => void) | undefined;
    private gltfLoader?;
    private gltfCache;
    clickDragThreshold: number;
    private pointerDownX;
    private pointerDownY;
    private pointerDragging;
    /**
     * Initialize a 3D scene with Three.js and tween.js
     * @param container - Optional HTML element to attach the renderer to
     * @param scale - Scale factor for the scene (default: 1)
     * @param camPos - Initial camera position (default: 10, 10, 10)
     * @param targetPos - Initial camera target (default: 0, 0, 0)
     */
    constructor(container?: HTMLElement, scale?: number, camPos?: THREE.Vector3, targetPos?: THREE.Vector3);
    /**
     * Add orbit controls to the camera
     * @param overrides - Optional configuration overrides
     * @returns this for method chaining
     */
    addControls(overrides?: {}): this;
    /**
     * Set a callback function to be executed on each render frame
     * @param fn - Callback function to run each frame
     * @returns this for method chaining
     */
    setAdditionalRenderFn(fn: () => void): this;
    resetSizes(): void;
    /**
     * Tween numeric properties of a target object. Durations are given in seconds;
     * the render loop keeps drawing while at least one tween is active, then stops once they complete.
     * @param target - Object whose numeric props are animated
     * @param props - Destination values
     * @param duration - Duration in seconds
     * @param onComplete - Optional callback fired when the tween finishes
     * @returns the created Tween
     */
    private tween;
    /**
     * Animate the color of a 3D model
     * @param name - Name of the object in the scene
     * @param color - Target color (hex, rgb, or color name)
     * @param duration - Animation duration in seconds (default: 2)
     * @returns this for method chaining
     */
    animateModelColor(name: string, color: string | number, duration?: number): this;
    /**
     * Animate the opacity of a 3D model
     * @param name - Name of the object in the scene
     * @param value - Target opacity value (0-1)
     * @param duration - Animation duration in seconds (default: 2)
     * @returns this for method chaining
     */
    animateModelOpacity(name: string, value: number, duration?: number): this;
    /**
     * Animate the position of a 3D model
     * @param name - Name of the object in the scene
     * @param newPosition - Target position vector
     * @param duration - Animation duration in seconds (default: 2)
     * @returns this for method chaining
     */
    animateModelPosition(name: string, newPosition: THREE.Vector3, duration?: number): this;
    /**
     * Attach renderer to a DOM element and start rendering
     * @param container - HTML element to attach the canvas to
     * @returns this for method chaining
     */
    attachRenderer(container: HTMLElement): this;
    /**
     * Add a game-ready lighting rig: a hemisphere fill, a shadow-casting key
     * light, and an opposite fill light, with optional ACES tone mapping.
     * All parts are configurable; sensible defaults are used when omitted.
     * @param options - Lighting configuration overrides
     * @returns this for method chaining
     */
    addLighting(options?: LightingOptions): this;
    /**
     * Enable shadow casting/receiving on every mesh currently in the scene.
     * Call after adding your meshes (and after {@link addLighting} with shadows on).
     * @param cast - Whether meshes cast shadows (default: true)
     * @param receive - Whether meshes receive shadows (default: true)
     * @returns this for method chaining
     */
    applyShadows(cast?: boolean, receive?: boolean): this;
    /**
     * Add a skybox to the scene (360° background)
     * @param url - Optional URL to a 360° image texture
     * @param color - Fallback color if no texture URL provided
     * @param name - Optional name for the skybox object
     * @returns this for method chaining
     */
    addSkybox(url?: string, color?: THREE.ColorRepresentation, name?: string): this;
    resizeListener(): void;
    stopRenderLoop(): this;
    startRenderLoop(): this;
    renderLoop(): void;
    /**
     * Reset camera to initial position with animation
     * @returns this for method chaining
     */
    resetCameraPosition(): this;
    /**
     * Animate camera to a new position
     * @param newPosCam - Target camera position
     * @param newPosTarget - Optional target position for orbit controls
     * @param callback - Optional callback on animation complete
     * @returns this for method chaining
     */
    moveCamera(newPosCam: THREE.Vector3, newPosTarget?: THREE.Vector3, callback?: () => void): this;
    /**
     * Load a 3D model from a URL
     * @param url - URL to the model file
     * @param loader - Optional THREE.js loader (default: ObjectLoader)
     * @returns Promise that resolves with the loaded object
     */
    loadModel(url: string, loader?: THREE.Loader): Promise<THREE.Object3D>;
    /**
     * Load a glTF/glb model and return a fresh clone of its scene (not added to
     * the scene graph). Results are cached per URL, so loading the same model
     * many times only fetches/parses it once. Ideal for instancing buildings,
     * units, props, etc. in a game.
     * @param url - URL to the .glb/.gltf file
     * @returns Promise resolving to a cloneable Group ready to position/add
     */
    loadGLTF(url: string): Promise<THREE.Group>;
    /**
     * Register an AnimationMixer so it's advanced automatically every frame by
     * the render loop. The loop keeps drawing while any mixer is registered.
     * @param mixer - The mixer to drive
     * @returns this for method chaining
     */
    addMixer(mixer: THREE.AnimationMixer): this;
    /**
     * Stop driving a previously-registered AnimationMixer.
     * @param mixer - The mixer to remove
     * @returns this for method chaining
     */
    removeMixer(mixer: THREE.AnimationMixer): this;
    /**
     * Load a rigged glTF/glb model, add it to the scene, and wire its animation
     * clips into the render loop. Unlike {@link loadGLTF} (which returns a clone
     * for static instancing), this keeps the original object so its skeleton
     * animates correctly, and returns a small handle to control playback.
     * @param url - URL to the .glb/.gltf file
     * @param options - Load options (add to scene, shadows, autoplay)
     * @returns Promise resolving to an {@link AnimatedModel} handle
     */
    loadAnimatedModel(url: string, options?: AnimatedModelOptions): Promise<AnimatedModel>;
    /**
     * Enable rigid-body physics (powered by cannon-es). The world is stepped every
     * frame and each body added with {@link addBody} keeps its mesh in sync.
     *
     * cannon-es is imported lazily here, so projects that never call this method
     * don't bundle it. This makes the method asynchronous: `await` it before
     * calling {@link addBody} or {@link addGround}.
     * @param options - Gravity and default contact material settings
     * @returns Promise resolving to this (for chaining)
     */
    enablePhysics(options?: PhysicsOptions): Promise<this>;
    /**
     * Give a mesh a rigid body and keep the two in sync each frame. The collision
     * shape is derived from the mesh's bounding box (or sphere) and its scale.
     * Requires {@link enablePhysics} to have been called first.
     * @param mesh - The mesh to simulate (its transform is driven by the body)
     * @param options - Mass, shape and damping
     * @returns The created cannon-es Body
     */
    addBody(mesh: THREE.Object3D, options?: PhysicsBodyOptions): CANNON.Body;
    /**
     * Add a static, infinite ground plane at the given height (default y = 0).
     * @param y - Height of the ground plane
     * @returns The created cannon-es Body
     */
    addGround(y?: number): CANNON.Body;
    /**
     * Remove a body from the physics world and stop syncing its mesh.
     * @param body - The body returned by {@link addBody} / {@link addGround}
     * @returns this for method chaining
     */
    removeBody(body: CANNON.Body): this;
    /** Build a cannon-es collision shape from a mesh's geometry and scale. */
    private shapeFromMesh;
    /**   * Enable interactive object picking with mouse events
     * @param onClickCallback - Callback when object is clicked
     * @param onContextMenuCallback - Callback when object is right-clicked
     * @returns this for method chaining
     */
    enablePicking(onClickCallback?: (object: THREE.Object3D) => void, onHoverCallback?: (object: THREE.Object3D | null) => void, onContextMenuCallback?: (object: THREE.Object3D) => void): this;
    /**
     * Disable interactive object picking
     * @returns this for method chaining
     */
    disablePicking(): this;
    /**
     * Get currently hovered/selected object
     * @returns The selected object or null
     */
    getSelectedObject(): THREE.Object3D | null;
    /**
     * Pick object at specific mouse position
     * @param mouseX - Normalized X coordinate (-1 to 1)
     * @param mouseY - Normalized Y coordinate (-1 to 1)
     * @returns PickingResult if object found, null otherwise
     */
    pickAt(mouseX: number, mouseY: number): {
        object: any;
        distance: any;
        point: any;
        normal: any;
        uv: any;
    } | null;
    /**   * Clean up scene resources and stop rendering
     * Call this when you're done with the scene to prevent memory leaks
     */
    dispose(): void;
}
