/** ****************************************************************************
 * Spine Runtimes License Agreement
 * Last updated July 28, 2023. Replaces all prior versions.
 *
 * Copyright (c) 2013-2023, Esoteric Software LLC
 *
 * Integration of the Spine Runtimes into software or otherwise creating
 * derivative works of the Spine Runtimes is permitted under the terms and
 * conditions of Section 2 of the Spine Editor License Agreement:
 * http://esotericsoftware.com/spine-editor-license
 *
 * Otherwise, it is permitted to integrate the Spine Runtimes into software or
 * otherwise create derivative works of the Spine Runtimes (collectively,
 * "Products"), provided that each user of the Products must obtain their own
 * Spine Editor license and redistribution of the Products in any form must
 * include this license and copyright notice.
 *
 * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
 * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
 * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *****************************************************************************/
import { Bounds, Container, ContainerOptions, DestroyOptions, PointData, Texture, ViewContainer } from 'pixi.js';
import { ISpineDebugRenderer } from './SpineDebugRenderer.js';
import { AnimationState, Bone, Color, MeshAttachment, RegionAttachment, Skeleton, SkeletonBounds, SkeletonData, Slot, TrackEntry } from '@esotericsoftware/spine-core';
/**
 * Options to create a {@link Spine} using {@link Spine.from}.
 */
export interface SpineFromOptions {
    /** the asset name for the skeleton `.skel` or `.json` file previously loaded into the Assets */
    skeleton: string;
    /** the asset name for the atlas file previously loaded into the Assets */
    atlas: string;
    /**  The value passed to the skeleton reader. If omitted, 1 is passed. See {@link SkeletonBinary.scale} for details. */
    scale?: number;
    /**  Set the {@link Spine.autoUpdate} value. If omitted, it is set to `true`. */
    autoUpdate?: boolean;
    /**
     * If `true`, use the dark tint renderer to render the skeleton
     * If `false`, use the default pixi renderer to render the skeleton
     * If `undefined`, use the dark tint renderer if at least one slot has tint black
     */
    darkTint?: boolean;
    /** The bounds provider to use. If undefined the bounds will be dynamic, calculated when requested and based on the current frame. */
    boundsProvider?: SpineBoundsProvider;
}
/** A bounds provider calculates the bounding box for a skeleton, which is then assigned as the size of the SpineGameObject. */
export interface SpineBoundsProvider {
    /** Returns the bounding box for the skeleton, in skeleton space. */
    calculateBounds(gameObject: Spine): {
        x: number;
        y: number;
        width: number;
        height: number;
    };
}
/** A bounds provider that provides a fixed size given by the user. */
export declare class AABBRectangleBoundsProvider implements SpineBoundsProvider {
    private x;
    private y;
    private width;
    private height;
    constructor(x: number, y: number, width: number, height: number);
    calculateBounds(): {
        x: number;
        y: number;
        width: number;
        height: number;
    };
}
/** A bounds provider that calculates the bounding box from the setup pose. */
export declare class SetupPoseBoundsProvider implements SpineBoundsProvider {
    private clipping;
    /**
     * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.
     */
    constructor(clipping?: boolean);
    calculateBounds(gameObject: Spine): {
        x: number;
        y: number;
        width: number;
        height: number;
    };
}
/** A bounds provider that calculates the bounding box by taking the maximumg bounding box for a combination of skins and specific animation. */
export declare class SkinsAndAnimationBoundsProvider implements SpineBoundsProvider {
    private animation;
    private skins;
    private timeStep;
    private clipping;
    /**
     * @param animation The animation to use for calculating the bounds. If null, the setup pose is used.
     * @param skins The skins to use for calculating the bounds. If empty, the default skin is used.
     * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.
     * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.
     */
    constructor(animation: string | null, skins?: string[], timeStep?: number, clipping?: boolean);
    calculateBounds(gameObject: Spine): {
        x: number;
        y: number;
        width: number;
        height: number;
    };
}
export interface SpineOptions extends ContainerOptions {
    /** the {@link SkeletonData} used to instantiate the skeleton */
    skeletonData: SkeletonData;
    /**  See {@link SpineFromOptions.autoUpdate}. */
    autoUpdate?: boolean;
    /**  See {@link SpineFromOptions.darkTint}. */
    darkTint?: boolean;
    /**  See {@link SpineFromOptions.boundsProvider}. */
    boundsProvider?: SpineBoundsProvider;
}
/**
 * AnimationStateListener {@link https://en.esotericsoftware.com/spine-api-reference#AnimationStateListener events} exposed for Pixi.
 */
export interface SpineEvents {
    complete: [trackEntry: TrackEntry];
    dispose: [trackEntry: TrackEntry];
    end: [trackEntry: TrackEntry];
    event: [trackEntry: TrackEntry, event: Event];
    interrupt: [trackEntry: TrackEntry];
    start: [trackEntry: TrackEntry];
}
export interface AttachmentCacheData {
    id: string;
    clipped: boolean;
    vertices: Float32Array;
    uvs: Float32Array;
    indices: number[];
    color: Color;
    darkColor: Color;
    darkTint: boolean;
    skipRender: boolean;
    texture: Texture;
    clippedData?: {
        vertices: Float32Array;
        uvs: Float32Array;
        indices: Uint16Array;
        vertexCount: number;
        indicesCount: number;
    };
}
/**
 * The class to instantiate a {@link Spine} game object in Pixi.
 * The static method {@link Spine.from} should be used to instantiate a Spine game object.
 */
export declare class Spine extends ViewContainer {
    batched: boolean;
    buildId: number;
    readonly renderPipeId = "spine";
    _didSpineUpdate: boolean;
    beforeUpdateWorldTransforms: (object: Spine) => void;
    afterUpdateWorldTransforms: (object: Spine) => void;
    /** The skeleton for this Spine game object. */
    skeleton: Skeleton;
    /** The animation state for this Spine game object. */
    state: AnimationState;
    skeletonBounds?: SkeletonBounds;
    private darkTint;
    private _debug?;
    readonly _slotsObject: Record<string, {
        slot: Slot;
        container: Container;
        followAttachmentTimeline: boolean;
    } | null>;
    private clippingSlotToPixiMasks;
    private getSlotFromRef;
    spineAttachmentsDirty: boolean;
    spineTexturesDirty: boolean;
    private _lastAttachments;
    private _stateChanged;
    private attachmentCacheData;
    get debug(): ISpineDebugRenderer | undefined;
    /** Pass a {@link SpineDebugRenderer} or create your own {@link ISpineDebugRenderer} to render bones, meshes, ...
     * @example spineGO.debug = new SpineDebugRenderer();
     */
    set debug(value: ISpineDebugRenderer | undefined);
    private _autoUpdate;
    get autoUpdate(): boolean;
    /** When `true`, the Spine AnimationState and the Skeleton will be automatically updated using the {@link Ticker.shared} instance. */
    set autoUpdate(value: boolean);
    private _boundsProvider?;
    /** The bounds provider to use. If undefined the bounds will be dynamic, calculated when requested and based on the current frame. */
    get boundsProvider(): SpineBoundsProvider | undefined;
    set boundsProvider(value: SpineBoundsProvider | undefined);
    private hasNeverUpdated;
    constructor(options: SpineOptions | SkeletonData);
    /** If {@link Spine.autoUpdate} is `false`, this method allows to update the AnimationState and the Skeleton with the given delta. */
    update(dt: number): void;
    protected internalUpdate(_deltaFrame: any, deltaSeconds?: number): void;
    get bounds(): Bounds;
    /**
     * Set the position of the bone given in input through a {@link IPointData}.
     * @param bone: the bone name or the bone instance to set the position
     * @param outPos: the new position of the bone.
     * @throws {Error}: if the given bone is not found in the skeleton, an error is thrown
     */
    setBonePosition(bone: string | Bone, position: PointData): void;
    /**
     * Return the position of the bone given in input into an {@link IPointData}.
     * @param bone: the bone name or the bone instance to get the position from
     * @param outPos: an optional {@link IPointData} to use to return the bone position, rathern than instantiating a new object.
     * @returns {IPointData | undefined}: the position of the bone, or undefined if no matching bone is found in the skeleton
     */
    getBonePosition(bone: string | Bone, outPos?: PointData): PointData | undefined;
    /**
     * Advance the state and skeleton by the given time, then update slot objects too.
     * The container transform is not updated.
     *
     * @param time the time at which to set the state
     */
    private _updateAndApplyState;
    /**
     * - validates the attachments - to flag if the attachments have changed this state
     * - transforms the attachments - to update the vertices of the attachments based on the new positions
     * @internal
     */
    _validateAndTransformAttachments(): void;
    private validateAttachments;
    private currentClippingSlot;
    private updateAndSetPixiMask;
    private transformAttachments;
    private updateClippingData;
    /**
     * ensure that attached containers map correctly to their slots
     * along with their position, rotation, scale, and visibility.
     */
    private updateSlotObjects;
    private updateSlotObject;
    /** @internal */
    _getCachedData(slot: Slot, attachment: RegionAttachment | MeshAttachment): AttachmentCacheData;
    private initCachedData;
    protected onViewUpdate(): void;
    /**
     * Attaches a PixiJS container to a specified slot. This will map the world transform of the slots bone
     * to the attached container. A container can only be attached to one slot at a time.
     *
     * @param container - The container to attach to the slot
     * @param slotRef - The slot id or  slot to attach to
     * @param options - Optional settings for the attachment.
     * @param options.followAttachmentTimeline - If true, the attachment will follow the slot's attachment timeline.
     */
    addSlotObject(slot: number | string | Slot, container: Container, options?: {
        followAttachmentTimeline?: boolean;
    }): void;
    /**
     * Removes a PixiJS container from the slot it is attached to.
     *
     * @param container - The container to detach from the slot
     * @param slotOrContainer - The container, slot id or slot to detach from
     */
    removeSlotObject(slotOrContainer: number | string | Slot | Container): void;
    /**
     * Removes all PixiJS containers attached to any slot.
     */
    removeSlotObjects(): void;
    /**
     * Returns a container attached to a slot, or undefined if no container is attached.
     *
     * @param slotRef - The slot id or slot to get the attachment from
     * @returns - The container attached to the slot
     */
    getSlotObject(slot: number | string | Slot): Container<import("pixi.js").ContainerChild> | undefined;
    protected updateBounds(): void;
    /** @internal */
    addBounds(bounds: Bounds): void;
    /**
     * Destroys this sprite renderable and optionally its texture.
     * @param options - Options parameter. A boolean will act as if all options
     *  have been set to that value
     * @param {boolean} [options.texture=false] - Should it destroy the current texture of the renderable as well
     * @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the renderable as well
     */
    destroy(options?: DestroyOptions): void;
    /** Converts a point from the skeleton coordinate system to the Pixi world coordinate system. */
    skeletonToPixiWorldCoordinates(point: {
        x: number;
        y: number;
    }): void;
    /** Converts a point from the Pixi world coordinate system to the skeleton coordinate system. */
    pixiWorldCoordinatesToSkeleton(point: {
        x: number;
        y: number;
    }): void;
    /** Converts a point from the Pixi world coordinate system to the bone's local coordinate system. */
    pixiWorldCoordinatesToBone(point: {
        x: number;
        y: number;
    }, bone: Bone): void;
    /**
     * Use this method to instantiate a Spine game object.
     * Before instantiating a Spine game object, the skeleton (`.skel` or `.json`) and the atlas text files must be loaded into the Assets. For example:
     * ```
     * PIXI.Assets.add("sackData", "./assets/sack-pro.skel");
     * PIXI.Assets.add("sackAtlas", "./assets/sack-pma.atlas");
     * await PIXI.Assets.load(["sackData", "sackAtlas"]);
     * ```
     * Once a Spine game object is created, its skeleton data is cached into {@link Cache} using the key:
     * `${skeletonAssetName}-${atlasAssetName}-${options?.scale ?? 1}`
     *
     * @param options - Options to configure the Spine game object. See {@link SpineFromOptions}
     * @returns {Spine} The Spine game object instantiated
     */
    static from({ skeleton, atlas, scale, darkTint, autoUpdate, boundsProvider }: SpineFromOptions): Spine;
}
