/// <reference types="webxr" />
import { EffectComposer } from "postprocessing";
import { BufferGeometry, Camera, DepthTexture, Group, Material, Object3D, PerspectiveCamera, Scene, Texture, WebGLRenderer, type WebGLRendererParameters, type WebXRArrayCamera } from 'three';
import { Addressables } from './engine_addressables.js';
import { AnimationsRegistry } from './engine_animation.js';
import { Application } from './engine_application.js';
import { AssetDatabase } from './engine_assetdatabase.js';
import { Input } from './engine_input.js';
import { type ILightDataRegistry } from './engine_lightdata.js';
import { LODsManager } from "./engine_lods.js";
import { NetworkConnection } from './engine_networking.js';
import { Physics } from './engine_physics.js';
import { PlayerViewManager } from './engine_playerview.js';
import { RendererData as SceneLighting } from './engine_scenelighting.js';
import { Time } from './engine_time.js';
import type { CoroutineData, ICamera, IComponent, IContext, ILight, Model, Vec2 } from "./engine_types.js";
import type { INeedleXRSessionEventReceiver, NeedleXRSession } from './engine_xr.js';
import { NeedleMenu } from './webcomponents/needle menu/needle-menu.js';
export declare const build_scene_functions: {
    [name: string]: (context: Context) => Promise<void>;
};
export declare class LoadingProgressArgs {
    /** the name or URL of the loaded file */
    name: string;
    /** the loading progress event from the loader */
    progress: ProgressEvent;
    /** the index of the loaded file */
    index: number;
    /** the total number of files to load */
    count: number;
}
export declare class ContextCreateArgs {
    /** list of glTF or GLB files to load */
    files: Array<string>;
    abortSignal?: AbortSignal;
    /** called when loading a provided glTF file started */
    onLoadingStart?: (index: number, file: string) => void;
    /** called on update for each loaded glTF file */
    onLoadingProgress?: (args: LoadingProgressArgs) => void;
    /** Called after a gLTF file has finished loading */
    onLoadingFinished?: (index: number, file: string, glTF: Model | null) => void;
}
export declare class ContextArgs {
    name?: string;
    /** for debugging only */
    alias?: string;
    /** the hash is used as a seed when initially loading the scene files */
    hash?: string;
    /** when true the context will not check if it's visible in the viewport and always update and render */
    runInBackground?: boolean;
    /** the DOM element the context belongs to or is inside of (this does not have to be the canvas. use renderer.domElement if you want to access the dom canvas) */
    domElement?: HTMLElement | null;
    /** externally owned renderer */
    renderer?: WebGLRenderer;
    /** externally owned camera */
    camera?: Camera;
    /** externally owned scene */
    scene?: Scene;
}
export declare enum FrameEvent {
    Start = -1,
    EarlyUpdate = 0,
    Update = 1,
    LateUpdate = 2,
    OnBeforeRender = 3,
    OnAfterRender = 4,
    PrePhysicsStep = 9,
    PostPhysicsStep = 10,
    Undefined = -1
}
/** threejs callback event signature */
export declare type OnRenderCallback = (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group) => void;
export declare function registerComponent(script: IComponent, context?: Context): void;
/**
 * The context is the main object that holds all the data and state of the Needle Engine.
 * It can be used to access the scene, renderer, camera, input, physics, networking, and more.
 * @example
 * ```typescript
 * import { Behaviour } from "@needle-tools/engine";
 * import { Mesh, BoxGeometry, MeshBasicMaterial } from "three";
 * export class MyScript extends Behaviour {
 *   start() {
 *     console.log("Hello from MyScript");
 *     this.context.scene.add(new Mesh(new BoxGeometry(), new MeshBasicMaterial()));
 *   }
 * }
 * ```
 */
export declare class Context implements IContext {
    private static _defaultTargetFramerate;
    /** When a new context is created this is the framerate that will be used by default */
    static get DefaultTargetFrameRate(): number | undefined;
    /** When a new context is created this is the framerate that will be used by default */
    static set DefaultTargetFrameRate(val: number | undefined);
    private static _defaultWebglRendererParameters;
    /** The default parameters that will be used when creating a new WebGLRenderer.
     * Modify in global context to change the default parameters for all new contexts.
     * @example
     * ```typescript
     * import { Context } from "@needle-tools/engine";
     * Context.DefaultWebGLRendererParameters.antialias = false;
     * ```
     */
    static get DefaultWebGLRendererParameters(): WebGLRendererParameters;
    /** The needle engine version */
    get version(): string;
    /** The currently active context. Only set during the update loops */
    static get Current(): Context;
    /** @internal this property should not be set by user code */
    static set Current(context: Context);
    /** The name of the context */
    name: string;
    /** An alias for the context */
    alias: string | undefined | null;
    /** When the renderer or camera are managed by an external process (e.g. when running in r3f context).
     * When this is false you are responsible to call update(timestamp, xframe.
     * It is also currently assumed that rendering is handled performed by an external process
     * */
    isManagedExternally: boolean;
    /** set to true to pause the update loop. You can receive an event for it in your components.
     * Note that script updates will not be called when paused */
    isPaused: boolean;
    /** When enabled the application will run while not visible on the page */
    runInBackground: boolean;
    /**
     * Set to the target framerate you want your application to run in (you can use ?stats to check the fps)
     * Set to undefined if you want to run at the maximum framerate
     */
    targetFrameRate?: number | {
        value?: number;
    };
    /** Use a higher number for more accurate physics simulation.
     * When undefined physics steps will be 1 for mobile devices and 5 for desktop devices
     * Set to 0 to disable physics updates
     * TODO: changing physics steps is currently not supported because then forces that we get from the character controller and rigidbody et al are not correct anymore - this needs to be properly tested before making this configureable
    */
    private physicsSteps?;
    /** used to append to loaded assets */
    hash?: string;
    /** The `<needle-engine>` web component */
    domElement: HTMLElement;
    appendHTMLElement(element: HTMLElement): HTMLElement;
    get resolutionScaleFactor(): number;
    /** use to scale the resolution up or down of the renderer. default is 1 */
    set resolutionScaleFactor(val: number);
    private _resolutionScaleFactor;
    private _boundingClientRectFrame;
    private _boundingClientRect;
    private _domX;
    private _domY;
    /** update bounding rects + domX, domY */
    private calculateBoundingClientRect;
    /** The width of the `<needle-engine>` element on the website */
    get domWidth(): number;
    /** The height of the `<needle-engine>` element on the website */
    get domHeight(): number;
    /** the X position of the Needle Engine element on the website */
    get domX(): number;
    /** the Y position of the Needlee Engine element on the website */
    get domY(): number;
    get isInXR(): boolean;
    /** shorthand for `NeedleXRSession.active`
     * Automatically set by NeedleXRSession when a XR session is active
     * @returns the active XR session or null if no session is active
     * */
    xr: NeedleXRSession | null;
    get xrSessionMode(): XRSessionMode | undefined;
    get isInVR(): boolean;
    get isInAR(): boolean;
    /** If a XR session is active and in pass through mode (immersive-ar on e.g. Quest) */
    get isInPassThrough(): boolean;
    /** access the raw `XRSession` object (shorthand for `context.renderer.xr.getSession()`). For more control use `NeedleXRSession.active` */
    get xrSession(): XRSession | null;
    /** @returns the latest XRFrame (if a XRSession is currently active)
     * @link https://developer.mozilla.org/en-US/docs/Web/API/XRFrame
     */
    get xrFrame(): XRFrame | null;
    /** @returns the current WebXR camera while the WebXRManager is active (shorthand for `context.renderer.xr.getCamera()`) */
    get xrCamera(): WebXRArrayCamera | undefined;
    private _xrFrame;
    get arOverlayElement(): HTMLElement;
    /** Current event of the update cycle */
    get currentFrameEvent(): FrameEvent;
    private _currentFrameEvent;
    scene: Scene;
    renderer: WebGLRenderer;
    composer: EffectComposer | null;
    readonly scripts: IComponent[];
    readonly scripts_pausedChanged: IComponent[];
    readonly scripts_earlyUpdate: IComponent[];
    readonly scripts_update: IComponent[];
    readonly scripts_lateUpdate: IComponent[];
    readonly scripts_onBeforeRender: IComponent[];
    readonly scripts_onAfterRender: IComponent[];
    readonly scripts_WithCorroutines: IComponent[];
    readonly scripts_immersive_vr: INeedleXRSessionEventReceiver[];
    readonly scripts_immersive_ar: INeedleXRSessionEventReceiver[];
    readonly coroutines: {
        [FrameEvent: number]: Array<CoroutineData>;
    };
    /** callbacks called once after the context has been created */
    readonly post_setup_callbacks: Function[];
    /** called every frame at the beginning of the frame (after component start events and before earlyUpdate) */
    readonly pre_update_callbacks: Function[];
    /** called every frame before rendering (after all component events) */
    readonly pre_render_callbacks: Array<(frame: XRFrame | null) => void>;
    /** called every frame after rendering (after all component events) */
    readonly post_render_callbacks: Function[];
    /** called every frame befroe update (this list is emptied every frame) */
    readonly pre_update_oneshot_callbacks: Function[];
    readonly new_scripts: IComponent[];
    readonly new_script_start: IComponent[];
    readonly new_scripts_pre_setup_callbacks: Function[];
    readonly new_scripts_post_setup_callbacks: Function[];
    readonly new_scripts_xr: INeedleXRSessionEventReceiver[];
    /** The main camera component of the scene - this camera is used for rendering */
    mainCameraComponent: ICamera | undefined;
    /** The main camera of the scene - this camera is used for rendering */
    get mainCamera(): Camera;
    /** Set the main camera of the scene. If set to null the camera of the {@link mainCameraComponent} will be used - this camera is used for rendering */
    set mainCamera(cam: Camera | null);
    private _mainCamera;
    private _fallbackCamera;
    application: Application;
    /** access animation mixer used by components in the scene */
    animations: AnimationsRegistry;
    /** access timings (current frame number, deltaTime, timeScale, ...) */
    time: Time;
    input: Input;
    /** access physics related methods (e.g. raycasting). To access the phyiscs engine use `context.physics.engine` */
    physics: Physics;
    /** access networking methods (use it to send or listen to messages or join a networking backend) */
    connection: NetworkConnection;
    /**
     * @deprecated AssetDataBase is deprecated
     */
    assets: AssetDatabase;
    mainLight: ILight | null;
    /** @deprecated Use sceneLighting */
    get rendererData(): SceneLighting;
    sceneLighting: SceneLighting;
    addressables: Addressables;
    lightmaps: ILightDataRegistry;
    players: PlayerViewManager;
    readonly lodsManager: LODsManager;
    readonly menu: NeedleMenu;
    get isCreated(): boolean;
    private _sizeChanged;
    private _isCreated;
    private _isCreating;
    private _isVisible;
    private _stats;
    constructor(args?: ContextArgs);
    /** calling this function will dispose the current renderer and create a new one */
    createNewRenderer(params?: WebGLRendererParameters): void;
    private _intersectionObserver;
    private internalOnUpdateVisible;
    private _disposeCallbacks;
    /** will request a renderer size update the next render call (will call updateSize the next update) */
    requestSizeUpdate(): void;
    /** Clamps the renderer max resolution. If undefined the max resolution is not clamped. Default is undefined */
    maxRenderResolution?: Vec2;
    /** update the renderer and canvas size */
    updateSize(force?: boolean): void;
    updateAspect(camera: PerspectiveCamera, width?: number, height?: number): void;
    /** This will recreate the whole needle engine context and dispose the whole scene content
     * All content will be reloaded (loading times might be faster due to browser caches)
     * All scripts will be recreated */
    recreate(): void;
    private _originalCreationArgs?;
    /** @deprecated use create. This method will be removed in a future version */
    onCreate(opts?: ContextCreateArgs): Promise<boolean>;
    create(opts?: ContextCreateArgs): Promise<boolean>;
    private onUnhandledRejection;
    /** Dispatches an error */
    private onError;
    /** Will destroy all scenes and objects in the scene
     */
    clear(): void;
    dispose(): void;
    /**@deprecated use dispose()  */
    onDestroy(): void;
    private internalOnDestroy;
    registerCoroutineUpdate(script: IComponent, coroutine: Generator, evt: FrameEvent): Generator;
    unregisterCoroutineUpdate(coroutine: Generator, evt: FrameEvent): void;
    stopAllCoroutinesFrom(script: IComponent): void;
    private _cameraStack;
    setCurrentCamera(cam: ICamera): void;
    removeCamera(cam?: ICamera | null): void;
    private _onBeforeRenderListeners;
    private _onAfterRenderListeners;
    /** use this to subscribe to onBeforeRender events on threejs objects */
    addBeforeRenderListener(target: Object3D, callback: OnRenderCallback): void;
    removeBeforeRenderListener(target: Object3D, callback: OnRenderCallback): void;
    /** use this to subscribe to onAfterRender events on threejs objects */
    addAfterRenderListener(target: Object3D, callback: OnRenderCallback): void;
    removeAfterRenderListener(target: Object3D, callback: OnRenderCallback): void;
    private _createRenderCallbackWrapper;
    private _requireDepthTexture;
    private _requireColorTexture;
    private _renderTarget?;
    private _isRendering;
    get isRendering(): boolean;
    setRequireDepth(val: boolean): void;
    setRequireColor(val: boolean): void;
    get depthTexture(): DepthTexture | null;
    get opaqueColorTexture(): Texture | null;
    /** returns true if the dom element is visible on screen */
    get isVisibleToUser(): boolean;
    private _createId;
    private internalOnCreate;
    private internalLoadInitialContent;
    /** Sets the animation loop.
     * Can not be done while creating the context or when disposed
     **/
    restartRenderLoop(): boolean;
    private _renderlooperrors;
    /** Performs a full update step including script callbacks, rendering (unless isManagedExternally is set to false) and post render callbacks */
    update(timestamp: DOMHighResTimeStamp, frame?: XRFrame | null): void;
    /** Call to **manually** perform physics steps.
     * By default the context uses the `physicsSteps` property to perform steps during the update loop
     * If you just want to increase the accuracy of physics you can instead set the `physicsSteps` property to a higher value
     * */
    updatePhysics(steps: number): void;
    private _lastTimestamp;
    private _accumulatedTime;
    private _dispatchReadyAfterFrame;
    private internalStep;
    private internalOnBeforeRender;
    private internalUpdatePhysics;
    private internalOnRender;
    private internalOnAfterRender;
    renderNow(camera?: Camera): boolean;
    private handleRendererContextLost;
    /** returns true if we should return out of the frame loop */
    private _wasPaused;
    private onHandlePaused;
    private evaluatePaused;
    private renderRequiredTextures;
    private executeCoroutines;
}
