/******************************************************************************
 * Spine Runtimes License Agreement
 * Last updated April 5, 2025. Replaces all prior versions.
 *
 * Copyright (c) 2013-2025, 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 { AnimationState, type Bone, Color, MeshAttachment, RegionAttachment, Skeleton, SkeletonBounds, SkeletonData, type Slot, type TrackEntry } from '@esotericsoftware/spine-core';
import { type Bounds, Container, type ContainerOptions, type DestroyOptions, type PointData, Texture, Ticker, ViewContainer } from 'pixi.js';
import type { ISpineDebugRenderer } from './SpineDebugRenderer.js';
/**
 * 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;
    /** Set {@link AtlasAttachmentLoader.allowMissingRegions} property on the AtlasAttachmentLoader. */
    allowMissingRegions?: boolean;
    /** The ticker to use when {@link autoUpdate} is `true`. Defaults to {@link Ticker.shared}. */
    ticker?: Ticker;
}
/** 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;
    /** See {@link SpineFromOptions.ticker}. */
    ticker?: Ticker;
}
/**
 * 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 ClippedData {
    vertices: Float32Array;
    uvs: Float32Array;
    indices: Uint16Array;
    vertexCount: number;
    indicesCount: number;
}
export interface AttachmentCacheData {
    id: string;
    clipped: boolean;
    vertices: Float32Array;
    uvs: Float32Array;
    indices: number[];
    color: Color;
    darkColor: Color;
    darkTint: boolean;
    skipRender: boolean;
    texture: Texture;
    clippedData?: ClippedData;
}
/**
 * The class to instantiate a {@link Spine} game object in Pixi.
 * Create and customize the default configuration using the static method {@link Spine.createOptions},
 * then pass it to the constructor.
 */
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;
        followSlotColor: 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;
    private _ticker;
    get autoUpdate(): boolean;
    /** When `true`, the Spine AnimationState and the Skeleton will be automatically updated using the {@link ticker}. */
    set autoUpdate(value: boolean);
    /** The ticker to use when {@link autoUpdate} is `true`. Defaults to {@link Ticker.shared}. */
    get ticker(): Ticker;
    /** Sets the ticker to use when {@link autoUpdate} is `true`. If `autoUpdate` is already `true`, the update callback will be moved from the old ticker to the new one. */
    set ticker(value: Ticker);
    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;
    private _physicsPositionInheritanceFactorX;
    private _physicsPositionInheritanceFactorY;
    private _physicsRotationInheritanceFactor;
    private hasLastPhysicsTransform;
    private lastPhysicsX;
    private lastPhysicsY;
    private lastPhysicsRotation;
    private readonly currentPhysicsPosition;
    private readonly lastPhysicsPosition;
    /** Scales how much horizontal translation of this Pixi container is inherited by skeleton physics constraints. */
    get physicsPositionInheritanceFactorX(): number;
    /** Scales how much vertical translation of this Pixi container is inherited by skeleton physics constraints. */
    get physicsPositionInheritanceFactorY(): number;
    /**
     * Sets how much translation of this Pixi container is inherited by skeleton physics constraints.
     * The default is (1, 1), which applies container translation normally. Use (0, 0)
     * to prevent container translation from affecting physics constraints.
     */
    setPhysicsPositionInheritanceFactor(x: number, y: number): void;
    /**
     * Scales how much rotation of this Pixi container is inherited by skeleton physics constraints.
     * The default is `1`, which applies container rotation normally. Use `0` to prevent container
     * rotation from affecting physics constraints.
     */
    get physicsRotationInheritanceFactor(): number;
    set physicsRotationInheritanceFactor(value: number);
    constructor(options: SkeletonData | SpineOptions | SpineFromOptions);
    /** 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(ticker?: Ticker, deltaSeconds?: number): void;
    /** Resets the position used for calculating inherited physics translation. */
    resetPhysicsPosition(): void;
    /** Resets the rotation used for calculating inherited physics rotation. */
    resetPhysicsRotation(): void;
    /** Resets the transform used for calculating inherited physics translation and rotation. */
    resetPhysicsTransform(): void;
    private applyTransformMovementToPhysics;
    private applyPositionMovementToPhysics;
    private applyRotationMovementToPhysics;
    private setLastPhysicsTransform;
    private getPhysicsRotation;
    private getRotationDelta;
    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.
     * @param options.followSlotColor - If true, the container tint will follow the skeleton and slot colors.
     */
    addSlotObject(slot: number | string | Slot, container: Container, options?: {
        followAttachmentTimeline?: boolean;
        followSlotColor?: 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;
    /**
     * Get a convenient initialization configuration for your Spine game object.
     * Before instantiating a Spine game object, the skeleton (`.skel` or `.json`) and the atlas text files must be loaded into the {@link 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 {SpineOptions} The configuration ready to be passed to the Spine constructor
     */
    static createOptions({ skeleton, atlas, scale, darkTint, autoUpdate, boundsProvider, allowMissingRegions, ticker }: SpineFromOptions): SpineOptions;
    /**
     * @deprecated Use directly the Spine constructor or {@link createOptions} to make options and customize it to pass to the constructor
     * 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(options: SpineFromOptions): Spine;
}
