@esotericsoftware/spine-pixi-v8
Version:
The official Spine Runtimes for PixiJS v8.
314 lines (313 loc) • 14.3 kB
TypeScript
/** ****************************************************************************
* 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;
}