Skip to content

Commit

Permalink
[pixi] Clean-up and improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
badlogic committed Jun 27, 2023
1 parent 7698f5f commit 8fb691c
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 92 deletions.
5 changes: 5 additions & 0 deletions examples/export/runtimes.sh
Expand Up @@ -341,6 +341,11 @@ cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-player/example/
cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-player/example/assets/"
cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-player/example/assets/"

cp -f ../spineboy/export/spineboy-pro.json "$ROOT/spine-ts/spine-pixi/example/assets/"
cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-pixi/example/assets/"
cp -f ../spineboy/export/spineboy.atlas "$ROOT/spine-ts/spine-pixi/example/assets/"
cp -f ../spineboy/export/spineboy.png "$ROOT/spine-ts/spine-pixi/example/assets/"

rm "$ROOT/spine-ts/spine-phaser/example/assets/"*
cp -f ../raptor/export/raptor-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../raptor/export/raptor-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
Expand Down
2 changes: 1 addition & 1 deletion spine-ts/spine-pixi/example/index.html
Expand Up @@ -54,7 +54,7 @@
]);

// Create the spine display object
const spineBoy = spine.Spine.from("spineboySkeletonJson", "spineboyAtlasPolypack", { scale: 0.5 });
const spineBoy = spine.Spine.from("spineboySkeletonJson", "spineboyAtlas", { scale: 0.5 });

// .from(...) is a shortcut + cache for creating the skeleton data at a certain scale
// Here would be the "long way" of doing it (without cache):
Expand Down
4 changes: 2 additions & 2 deletions spine-ts/spine-pixi/src/DarkSlotMesh.ts
Expand Up @@ -8,10 +8,10 @@ export class DarkSlotMesh extends DarkTintMesh implements ISlotMesh {

private static auxColor = [0, 0, 0, 0];

constructor() {
constructor () {
super();
}
public updateFromSpineData(
public updateFromSpineData (
slotTexture: SpineTexture,
slotBlendMode: BlendMode,
slotName: string,
Expand Down
4 changes: 2 additions & 2 deletions spine-ts/spine-pixi/src/SlotMesh.ts
Expand Up @@ -10,7 +10,7 @@ export class SlotMesh extends Mesh implements ISlotMesh {
private static readonly auxColor = [0, 0, 0, 0];
private warnedTwoTint: boolean = false;

constructor() {
constructor () {
const geometry = new MeshGeometry();

geometry.getBuffer("aVertexPosition").static = false;
Expand All @@ -19,7 +19,7 @@ export class SlotMesh extends Mesh implements ISlotMesh {
const meshMaterial = new MeshMaterial(Texture.EMPTY);
super(geometry, meshMaterial);
}
public updateFromSpineData(
public updateFromSpineData (
slotTexture: SpineTexture,
slotBlendMode: BlendMode,
slotName: string,
Expand Down
86 changes: 22 additions & 64 deletions spine-ts/spine-pixi/src/Spine.ts
Expand Up @@ -24,7 +24,6 @@ import type { IDestroyOptions, DisplayObject } from "@pixi/display";
import { Container } from "@pixi/display";

export interface ISpineOptions {
removeUnusedSlots?: boolean;
autoUpdate?: boolean;
slotMeshFactory?: () => ISlotMesh;
}
Expand All @@ -43,10 +42,10 @@ export class Spine extends Container {
public state: AnimationState;

private _debug?: ISpineDebugRenderer | undefined = undefined;
public get debug(): ISpineDebugRenderer | undefined {
public get debug (): ISpineDebugRenderer | undefined {
return this._debug;
}
public set debug(value: ISpineDebugRenderer | undefined) {
public set debug (value: ISpineDebugRenderer | undefined) {
if (this._debug) {
this._debug.unregisterSpine(this);
}
Expand All @@ -56,16 +55,14 @@ export class Spine extends Container {
this._debug = value;
}

// Each slot is a pixi mesh, by default we just visible=false the ones we don't need. This forces a removeChild and addChild every time we need to show a slot.
public removeUnusedSlots: boolean;
protected slotMeshFactory: () => ISlotMesh;

private autoUpdateWarned: boolean = false;
private _autoUpdate: boolean = true;
public get autoUpdate(): boolean {
public get autoUpdate (): boolean {
return this._autoUpdate;
}
public set autoUpdate(value: boolean) {
public set autoUpdate (value: boolean) {
if (value) {
Ticker.shared.add(this.internalUpdate, this);
this.autoUpdateWarned = false;
Expand All @@ -88,13 +85,12 @@ export class Spine extends Container {
private darkColor = new Color();


constructor(skeletonData: SkeletonData, options?: ISpineOptions) {
constructor (skeletonData: SkeletonData, options?: ISpineOptions) {
super();

this.skeleton = new Skeleton(skeletonData);
const animData = new AnimationStateData(skeletonData);
this.state = new AnimationState(animData);
this.removeUnusedSlots = options?.removeUnusedSlots ?? false;
this.autoUpdate = options?.autoUpdate ?? true;
this.slotMeshFactory = options?.slotMeshFactory ?? ((): ISlotMesh => new SlotMesh());

Expand All @@ -116,26 +112,26 @@ export class Spine extends Container {
*/
}

public update(deltaSeconds: number): void {
public update (deltaSeconds: number): void {
if (this.autoUpdate && !this.autoUpdateWarned) {
console.warn("You are calling update on a Spine instance that has autoUpdate set to true. This is probably not what you want.");
this.autoUpdateWarned = true;
}
this.internalUpdate(0, deltaSeconds);
}

protected internalUpdate(_deltaFrame: number, deltaSeconds?: number): void {
protected internalUpdate (_deltaFrame: number, deltaSeconds?: number): void {
// Because reasons, pixi uses deltaFrames at 60fps. We ignore the default deltaFrames and use the deltaSeconds from pixi ticker.
this.state.update(deltaSeconds ?? Ticker.shared.deltaMS / 1000);
}

public override updateTransform(): void {
public override updateTransform (): void {
this.updateSpineTransform();
this.debug?.renderDebug(this);
super.updateTransform();
}

protected updateSpineTransform(): void {
protected updateSpineTransform (): void {
// if I ever create the linked spines, this will be useful.

this.state.apply(this.skeleton);
Expand All @@ -144,7 +140,7 @@ export class Spine extends Container {
this.sortChildren();
}

public override destroy(options?: boolean | IDestroyOptions | undefined): void {
public override destroy (options?: boolean | IDestroyOptions | undefined): void {
for (const [, mesh] of this.meshesCache) {
mesh?.destroy();
}
Expand All @@ -154,11 +150,8 @@ export class Spine extends Container {
super.destroy(options);
}

private recycleMeshes(): void {
private resetMeshes (): void {
for (const [, mesh] of this.meshesCache) {
if (this.removeUnusedSlots) {
mesh.parent?.removeChild(mesh);
}
mesh.zIndex = -1;
mesh.visible = false;
}
Expand All @@ -167,27 +160,23 @@ export class Spine extends Container {
/**
* If you want to manually handle which meshes go on which slot and how you cache, overwrite this method.
*/
protected getMeshForSlot(slot: Slot): ISlotMesh {
protected getMeshForSlot (slot: Slot): ISlotMesh {
if (!this.meshesCache.has(slot)) {
let mesh = this.slotMeshFactory();
this.addChild(mesh);
this.meshesCache.set(slot, mesh);
return mesh;
} else {
let mesh = this.meshesCache.get(slot)!;

if (this.removeUnusedSlots) {
this.addChild(mesh);
}
mesh.visible = true;
return mesh;
}
}

private verticesCache: NumberArrayLike = Utils.newFloatArray(1024);

private updateGeometry(): void {
this.recycleMeshes();
private updateGeometry (): void {
this.resetMeshes();

let triangles: Array<number> | null = null;
let uvs: NumberArrayLike | null = null;
Expand Down Expand Up @@ -300,46 +289,30 @@ export class Spine extends Container {
Spine.clipper.clipEnd();
}

public setBonePosition(bone: string | Bone, position: IPointData): void {
public setBonePosition (bone: string | Bone, position: IPointData): void {
const boneAux = bone;
if (typeof bone === "string") {
bone = this.skeleton.findBone(bone)!;
this.skeleton.findBone;
this.skeleton.findIkConstraint;
this.skeleton.findPathConstraint;
this.skeleton.findSlot;
this.skeleton.findTransformConstraint;
}

if (!bone) {
console.error(`Cant set bone position! Bone ${String(boneAux)} not found`);
return;
}

if (!bone) throw Error(`Cant set bone position, bone ${String(boneAux)} not found`);
Spine.vectorAux.set(position.x, position.y);

if (bone.parent)
{
if (bone.parent) {
const aux = bone.parent.worldToLocal(Spine.vectorAux);
bone.x = aux.x;
bone.y = aux.y;
}
else
{
else {
bone.x = Spine.vectorAux.x;
bone.y = Spine.vectorAux.y;
}
}

public getBonePosition(bone: string | Bone, outPos?: IPointData): IPointData | undefined {
public getBonePosition (bone: string | Bone, outPos?: IPointData): IPointData | undefined {
const boneAux = bone;
if (typeof bone === "string") {
bone = this.skeleton.findBone(bone)!;
this.skeleton.findBone;
this.skeleton.findIkConstraint;
this.skeleton.findPathConstraint;
this.skeleton.findSlot;
this.skeleton.findTransformConstraint;
}

if (!bone) {
Expand All @@ -358,34 +331,19 @@ export class Spine extends Container {

public static readonly skeletonCache: Record<string, SkeletonData> = Object.create(null);

public static from(skeletonAssetName: string, atlasAssetName: string, options?: ISpineOptions & { scale?: number }): Spine {
public static from (skeletonAssetName: string, atlasAssetName: string, options?: ISpineOptions & { scale?: number }): Spine {
const cacheKey = `${skeletonAssetName}-${atlasAssetName}-${options?.scale ?? 1}`;

let skeletonData = Spine.skeletonCache[cacheKey];
if (skeletonData) {
return new Spine(skeletonData, options);
}

const skeletonAsset = Assets.get<any | Uint8Array>(skeletonAssetName);

const atlasAsset = Assets.get<TextureAtlas>(atlasAssetName);

// If you want a custom attachment laoder, you don't use .from(...)
const attachmentLoader = new AtlasAttachmentLoader(atlasAsset);

// What parser do we need?
let parser: SkeletonBinary | SkeletonJson;
if (skeletonAsset instanceof Uint8Array) {
parser = new SkeletonBinary(attachmentLoader);
} else {
parser = new SkeletonJson(attachmentLoader);
}
let parser = skeletonAsset instanceof Uint8Array ? new SkeletonBinary(attachmentLoader) : new SkeletonJson(attachmentLoader);
parser.scale = options?.scale ?? 1;

skeletonData = parser.readSkeletonData(skeletonAsset);

Spine.skeletonCache[cacheKey] = skeletonData;

return new this(skeletonData, options);
}
}
Expand All @@ -394,7 +352,7 @@ Skeleton.yDown = true;

export interface ISlotMesh extends DisplayObject {
name: string;
updateFromSpineData(
updateFromSpineData (
slotTexture: SpineTexture,
slotBlendMode: BlendMode,
slotName: string,
Expand Down

0 comments on commit 8fb691c

Please sign in to comment.