import * as THREE from 'three'; import { Behaviour } from '@needle-tools/engine'; import { MultisetClient, IXRSessionOptions, IXRFrameEvent, ILocalizeAndMapDetails, XRSessionManager, IObjectTrackingResponse } from '../core/index.js'; interface INeedleAdapterOptions { client: MultisetClient; /** * Options forwarded directly to XRSessionManager (everything except `client`). * Includes all session callbacks: onSessionStart, onSessionEnd, onLocalizationResult, * onObjectTrackingSuccess, onError, autoLocalize, backgroundLocalization, etc. */ sessionOptions?: Omit; /** Show the map mesh after a successful localization. Default false. */ showMesh?: boolean; /** Show the transform gizmo after a successful localization. Default false. */ showGizmo?: boolean; /** * Mount the built-in START AR / STOP AR button. Default true. * Set to false to drive the session via startSession() / stopSession(). * NOTE: startSession() must be called from within a user gesture. */ useDefaultButton?: boolean; onButtonCreated?: (button: HTMLButtonElement) => void; buttonContainer?: HTMLElement; /** * Called every XR frame after camera matrices are synced and the world is * updated, but before the scene is rendered. */ onXRFrame?: (event: IXRFrameEvent) => void; /** * Called after a successful localization. * * `worldFromMap` transforms any point from VPS map space into Needle/Three.js * world space (the XR reference space): * * ```ts * onLocalizationSuccess: (result, worldFromMap) => { * const marker = new THREE.Mesh(geometry, material); * const mapPoint = new THREE.Vector3(1.5, 0, -2.0); * marker.position.copy(mapPoint.applyMatrix4(worldFromMap)); * context.scene.add(marker); * } * ``` */ onLocalizationSuccess?: (result: ILocalizeAndMapDetails, worldFromMap: THREE.Matrix4) => void; /** Load and display a 3D outline mesh for each detected object. Default false. */ showObjectMeshes?: boolean; /** Called when a detected object's 3D mesh has been loaded and placed in the scene. */ onObjectMeshLoaded?: (objectCode: string) => void; } /** * Needle Engine adapter for the Multiset VPS SDK. * * Add this component to a GameObject via `addNewComponent()`. The built-in * START AR / STOP AR button is mounted automatically in `awake()` unless * `useDefaultButton: false` is set, in which case drive the session via * `startSession()` / `stopSession()` from your own button handler. * * IMPORTANT: Do NOT add a Needle `WebXR` component to the same scene — * NeedleAdapter owns the WebXR session. Two concurrent session managers * will conflict. */ /** Minimal interface for objects that can be anchored to the VPS map. Avoids circular import with MapAnchor. */ interface IMapAnchor { connectAdapter(adapter: NeedleAdapter): void; applyLocalization(result: ILocalizeAndMapDetails, worldFromMap: THREE.Matrix4): void; } declare class NeedleAdapter extends Behaviour { private _opts; private _session; private _world; private _xrRenderTarget; private _camera; private _renderer; private _savedBackground; private _savedEnvironment; private _savedFog; private _savedClearColor; private _savedClearAlpha; private _localizationListeners; private _sessionStartListeners; private _sessionEndListeners; private _lastLocalization; constructor(options: INeedleAdapterOptions); /** Returns true if the browser supports immersive-ar WebXR sessions. */ static isSupported(): Promise; awake(): void; onDestroy(): void; /** * Register a callback that fires after every successful VPS localization. * Use this from other Needle components instead of passing `onLocalizationSuccess` * in the constructor options — it supports multiple subscribers. * Remove the listener in your component's `onDestroy` via `removeLocalizationListener`. */ addLocalizationListener(fn: (result: ILocalizeAndMapDetails, worldFromMap: THREE.Matrix4) => void): void; removeLocalizationListener(fn: (result: ILocalizeAndMapDetails, worldFromMap: THREE.Matrix4) => void): void; /** * Register a callback that fires when the AR session ends. * Useful for hiding anchored content until the next localization. */ addSessionStartListener(fn: () => void): void; removeSessionStartListener(fn: () => void): void; addSessionEndListener(fn: () => void): void; removeSessionEndListener(fn: () => void): void; /** * Register a dynamically created MapAnchor so it responds to localization. * * Call this after instantiating a MapAnchor at runtime (e.g. spawned from a prefab, * created from API data, or added mid-session). If localization has already succeeded * in the current session the anchor is placed immediately. */ registerAnchor(anchor: IMapAnchor): void; /** * Access the underlying XRSessionManager after `awake()` has been called. * Useful for registering additional callbacks or calling session methods directly. */ getSession(): XRSessionManager; isActive(): boolean; get isLocalizing(): boolean; startSession(): Promise; stopSession(): void; localizeFrame(): Promise; trackObjects(): Promise; clearObjectMeshes(): void; private _onXRFrame; private _syncCameraMatrices; private _handleLocalizationResult; } export { type INeedleAdapterOptions, NeedleAdapter };