import { vec3, quat2, quat } from 'gl-matrix';
import { Component, Emitter, Object3D, WonderlandEngine } from '@wonderlandengine/api';
import { Interactor } from './interactor.js';
import { GrabPoint, InteractorVisualState } from './grab-point.js';
export declare enum GrabTransformType {
    Hand = 0,
    AroundPivot = 1
}
export declare enum PivotAxis {
    X = 0,
    Y = 1,
    Z = 2
}
/** List of string keys for {@link PivotAxis}. */
export declare const PivotAxisNames: ("X" | "Y" | "Z")[];
/** Temporaries associated to a grab point upon interaction. */
interface GrabData {
    interactor: Interactor;
    handleId: number;
    /** Local grab anchor position */
    localAnchor: vec3;
}
/**
 * Enables objects to be interactively grabbed and manipulated in a virtual environment.
 *
 * The `Grabbable` class extends the basic functionality provided by the {@link Interactable}
 * component to allow objects to be picked up, held, and potentially thrown by the user. It
 * facilitates the creation of immersive and interactive experiences by providing an intuitive
 * interface for object manipulation within a 3D scene.
 */
export declare class Grabbable extends Component {
    static TypeName: string;
    /** @override */
    static onRegister(engine: WonderlandEngine): void;
    /** Properties */
    /**
     * List of objects to use as grab points.
     *
     * @note If no object is provided, the grabbable is treated as its own grab point.
     * @note Objects with no {@link GrabPoint} component will have a default one created.
     */
    handleObjects: Object3D[];
    /**
     * Whether the object can be thrown with physics or not.
     *
     * When the interactor releases this grabbable, it will be thrown based on
     * the velocity the interactor had.
     */
    canThrow: boolean;
    /**
     * Linear multiplier for the throwing speed.
     *
     * By default, throws at the controller speed.
     */
    throwLinearIntensity: number;
    /**
     * Linear multiplier for the throwing angular  speed.
     *
     * By default, throws at the controller speed.
     */
    throwAngularIntensity: number;
    /**
     * If `true`, the grabbable will be updated based on the controller
     * velocity data, if available.
     *
     * When `false`, the linear and angular velocities will be emulated based on
     * the grabbable previous orientation and position.
     *
     * For more information, have a look at:
     * - [linearVelocity](https://developer.mozilla.org/en-US/docs/Web/API/XRPose/linearVelocity)
     * - [angularVelocity](https://developer.mozilla.org/en-US/docs/Web/API/XRPose/angularVelocity)
     */
    useControllerVelocityData: boolean;
    /**
     * Max distance to automatically stop grabbing.
     *
     * @note Set a negative value to disable.
     */
    releaseDistance: number;
    /**
     * The distance marker to use when distance-grabbed.
     */
    distanceMarker: Object3D | null;
    /**
     * The index of the handle to use when distance-grabbed.
     *
     * Use `0` for {@link handle} and `1` for {@link handleSecondary}.
     */
    distanceHandle: number;
    transformType: GrabTransformType;
    /** Pivot axis used when {@link transformType} is set to {@link GrabRotationType.AroundPivot} */
    pivotAxis: PivotAxis;
    secondaryPivot: Object3D | null;
    /** Pivot axis used when {@link transformType} is set to {@link GrabRotationType.AroundPivot} */
    secondaryPivotAxis: PivotAxis;
    /**
     * Visual state to apply to the interactor once interaction occurs.
     *
     * @note Behavior overriden by {@link GrabPoint.interactorVisualState} if set.
     */
    interactorVisualState: InteractorVisualState;
    /** Public Attributes */
    grabPoints: GrabPoint[];
    /** Notifies once a grab point is selected for interaction. */
    onGrabPointSelect: Emitter<[this, GrabPoint]>;
    /** Notifies once a grab point is released. */
    onGrabPointRelease: Emitter<[this, GrabPoint]>;
    /**
     * Notifies once this object is grabbed.
     *
     * @note The notification only occurs when first grabbed.
     */
    onGrabStart: Emitter<[this]>;
    /**
     * Notifies once this object is released.
     *
     * @note The notification only occurs when both grip point are free.
     */
    onGrabEnd: Emitter<[this]>;
    /** Private Attributes. */
    /** Cached currently grabbed data. */
    private _grabData;
    /**
     * Squared distance to automatically stop a grab when:
     * - Using dual grabbing
     * - Moving away from a locked grab
     */
    private _history;
    private _physx;
    /**
     * Relative grab transform to apply every update, used
     * to maintain the object transform when grab starts.
     *
     * @note Can be local or world based on the transformation type.
     */
    private _relativeGrabTransform;
    /**
     * Relative pivot's grab transform to apply every update, used
     * to maintain the object transform when grab starts.
     */
    private _pivotGrabTransform;
    private _useUpOrientation;
    /** `true` if the transform is computed and applied in world space, `false` otherwise. */
    private _computeWorldSpace;
    /** `true` if the grabbable should continue lerping to the target rotation / position. */
    private _lerp;
    init(): void;
    start(): void;
    onActivate(): void;
    update(dt: number): void;
    /**
     * Throws the grabbable.
     */
    throw(interactor: Interactor): void;
    /**
     * Programmatically grab an interactable.
     *
     * @remarks
     * The interactable must be one of {@link Grabbable.handle}
     * or {@link Grabbable.handleSecondary}.
     *
     * This method is useful for grab emulation for non-VR applications.
     * In general, you will not call this method but rather rely on collision
     * checks between the {@link Interactor} and the {@link Interactable}.
     *
     * @param interactor The interactor issuing the interaction.
     * @param interactable The interactable undergoing the action.
     */
    grab(interactor: Interactor, handleId: number): void;
    /**
     * Programmatically release an interactable.
     *
     * @remarks
     * The interactable must be one of {@link Grabbable.handle}
     * or {@link Grabbable.handleSecondary}.
     *
     * This method is useful for grab emulation for non-VR applications.
     * In general, you will not call this method but rather rely on collision
     * checks between the {@link Interactor} and the {@link Interactable}.
     *
     * @param interactor The interactor issuing the interaction.
     * @param interactable The interactable undergoing the action.
     */
    release(interactor: Interactor): void;
    /** `true` is any of the two handles is currently grabbed. */
    get isGrabbed(): boolean;
    /** `true` if the primary handle is grabbed, the object pointer by {@link handle}. */
    get primaryGrab(): GrabData | null;
    /** `true` if the secondary handle is grabbed, the object pointer by {@link handleSecondary}. */
    get secondaryGrab(): GrabData | null;
    protected computeTransform(out: quat2, pivotOut: quat, primary: Object3D, secondary: Object3D | null): void;
    protected transformHand(out: quat2, source: Object3D): quat2;
    /**
     * Compute the transform of this grabbable based on both handles.
     */
    private transformDualHand;
    /**
     * Rotate the grabable around an origin.
     *
     * @param out Destination quaternion
     * @param positionWorld Anchor point, in **world space**.
     */
    protected rotationAroundPivot(out: quat, pivotOut: quat, positionWorld: vec3): void;
    /**
     * Initializes grab state.
     *
     * @note Triggered when single grab occurs, or when second hand is released.
     */
    protected initializeGrab(): void;
    private _setKinematicState;
}
export {};
