288 lines
8.9 KiB
TypeScript
288 lines
8.9 KiB
TypeScript
import { _decorator, Component, Enum, Node, setPropertyEnumType, sp } from 'cc';
|
|
|
|
const { ccclass, property, type } = _decorator;
|
|
|
|
export enum SocketPath {}
|
|
Enum(SocketPath);
|
|
|
|
export enum SpineAnimation {}
|
|
Enum(SpineAnimation);
|
|
|
|
export enum SpineSkin {}
|
|
Enum(SpineSkin);
|
|
|
|
@ccclass('SpineAnimationHandler')
|
|
export default class SpineAnimationHandler extends Component {
|
|
@property(sp.Skeleton)
|
|
private skeleton: sp.Skeleton;
|
|
@property({ visible: true })
|
|
private _flipX: boolean = false;
|
|
@property({ visible: true })
|
|
private _flipY: boolean = false;
|
|
|
|
public get flipX() {
|
|
return this._flipX;
|
|
}
|
|
public set flipX(value: boolean) {
|
|
if (value) {
|
|
this.skeleton._skeleton.scaleX = -Math.abs(this.skeleton._skeleton.scaleX);
|
|
} else {
|
|
this.skeleton._skeleton.scaleX = Math.abs(this.skeleton._skeleton.scaleX);
|
|
}
|
|
|
|
this._flipX = value;
|
|
}
|
|
public get flipY() {
|
|
return this._flipY;
|
|
}
|
|
public set flipY(value: boolean) {
|
|
if (value) {
|
|
this.skeleton._skeleton.scaleY = -Math.abs(this.skeleton._skeleton.scaleY);
|
|
} else {
|
|
this.skeleton._skeleton.scaleY = Math.abs(this.skeleton._skeleton.scaleY);
|
|
}
|
|
|
|
this._flipX = value;
|
|
}
|
|
|
|
private _enumSocketPath = Enum({});
|
|
private _enumAnimation = Enum({});
|
|
private _enumSkin = Enum({});
|
|
|
|
onFocusInEditor(): void {
|
|
this.setPropertySocketPath(this, '');
|
|
}
|
|
|
|
protected onLoad(): void {
|
|
this.skeleton._skeleton.scaleX = this._flipX ? -this.skeleton._skeleton.scaleX : this.skeleton._skeleton.scaleX;
|
|
this.skeleton._skeleton.scaleY = this._flipY ? -this.skeleton._skeleton.scaleY : this.skeleton._skeleton.scaleY;
|
|
}
|
|
|
|
public setPropertySocketPath(object: object, propertyName: string) {
|
|
//update enum SocketPath
|
|
let pathEnum = {};
|
|
this.skeleton.querySockets().forEach((path, i) => {
|
|
pathEnum[path] = i;
|
|
});
|
|
this._enumSocketPath = Enum({});
|
|
Object.assign(this._enumSocketPath, pathEnum);
|
|
Enum.update(this._enumSocketPath);
|
|
setPropertyEnumType(object, propertyName, this._enumSocketPath);
|
|
}
|
|
|
|
public setPropertySpineAnimation(object: object, propertyName: string) {
|
|
//update enum Animations
|
|
let animEnum = this.skeleton.skeletonData.getAnimsEnum();
|
|
this._enumAnimation = Enum({});
|
|
Object.assign(this._enumAnimation, animEnum);
|
|
Enum.update(this._enumAnimation);
|
|
setPropertyEnumType(object, propertyName, this._enumAnimation);
|
|
}
|
|
|
|
public setPropertySpineSkin(object: object, propertyName: string) {
|
|
//update enum Skin
|
|
let skinEnum = this.skeleton.skeletonData.getSkinsEnum();
|
|
this._enumSkin = Enum({});
|
|
Object.assign(this._enumSkin, skinEnum);
|
|
Enum.update(this._enumSkin);
|
|
setPropertyEnumType(object, propertyName, this._enumSkin);
|
|
}
|
|
|
|
public setAnimation(
|
|
animName: string,
|
|
options?: {
|
|
loop?: boolean;
|
|
trackIndex?: number;
|
|
ignoreAnimationRunning?: boolean;
|
|
onComplete?: (entry: sp.spine.TrackEntry) => void;
|
|
},
|
|
): sp.spine.TrackEntry {
|
|
if (!this.skeleton) return null;
|
|
const opts = {
|
|
trackIndex: 0,
|
|
loop: false,
|
|
...options,
|
|
};
|
|
|
|
if (opts.ignoreAnimationRunning) {
|
|
const trackEntry = this.skeleton.getCurrent(opts.trackIndex);
|
|
const animRunning = trackEntry?.animation?.name;
|
|
if (animRunning && animRunning == animName) return trackEntry;
|
|
}
|
|
|
|
this.skeleton.setCompleteListener(null);
|
|
const trackEntry = this.skeleton.setAnimation(opts?.trackIndex || 0, animName, opts?.loop);
|
|
if (opts.onComplete) {
|
|
this.skeleton.setCompleteListener(opts.onComplete);
|
|
}
|
|
|
|
return trackEntry;
|
|
}
|
|
|
|
public setListener(listener: (entry: sp.spine.TrackEntry, e: sp.spine.Event) => void) {
|
|
this.skeleton.setEventListener(listener);
|
|
}
|
|
|
|
public setAnimationAsync(
|
|
animName: string,
|
|
options?: {
|
|
loop?: boolean;
|
|
trackIndex?: number;
|
|
ignoreAnimationRunning?: boolean;
|
|
},
|
|
): Promise<sp.spine.TrackEntry> {
|
|
return new Promise((resolve) => {
|
|
this.setAnimation(animName, {
|
|
...options,
|
|
onComplete(entry) {
|
|
resolve(entry);
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
public addAnimation(
|
|
animName: string,
|
|
options?: {
|
|
loop?: boolean;
|
|
trackIndex?: number;
|
|
mixDuration?: number;
|
|
delay?: number;
|
|
onComplete?: (entry: sp.spine.TrackEntry) => void;
|
|
},
|
|
): sp.spine.TrackEntry {
|
|
if (!this.skeleton) return null;
|
|
const opts = {
|
|
trackIndex: 0,
|
|
loop: false,
|
|
...options,
|
|
};
|
|
|
|
this.skeleton.setCompleteListener(null);
|
|
const trackEntry = this.skeleton.addAnimation(opts?.trackIndex || 0, animName, opts?.loop, opts?.delay);
|
|
|
|
if (opts?.mixDuration) {
|
|
trackEntry.mixDuration = opts.mixDuration;
|
|
}
|
|
|
|
if (opts.onComplete) {
|
|
this.skeleton.setCompleteListener(opts.onComplete);
|
|
}
|
|
|
|
return trackEntry;
|
|
}
|
|
|
|
public addAnimationAsync(
|
|
animName: string,
|
|
options?: {
|
|
loop?: boolean;
|
|
trackIndex?: number;
|
|
mixDuration?: number;
|
|
delay?: number;
|
|
},
|
|
): Promise<sp.spine.TrackEntry> {
|
|
return new Promise((resolve) => {
|
|
this.addAnimation(animName, {
|
|
...options,
|
|
onComplete(entry) {
|
|
resolve(entry);
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
public addEmptyAnimation(options?: {
|
|
trackIndex?: number;
|
|
mixDuration?: number;
|
|
delay?: number;
|
|
onComplete?: (entry: sp.spine.TrackEntry) => void;
|
|
}): sp.spine.TrackEntry {
|
|
if (!this.skeleton) return;
|
|
const opts = {
|
|
trackIndex: 0,
|
|
mixDuration: 0.2,
|
|
delay: 0.2,
|
|
...options,
|
|
};
|
|
|
|
const trackEntry = this.skeleton.getState().addEmptyAnimation(opts.trackIndex, opts.mixDuration, opts.delay);
|
|
|
|
if (opts.onComplete) {
|
|
this.skeleton.setTrackCompleteListener(trackEntry, opts.onComplete);
|
|
}
|
|
return trackEntry;
|
|
}
|
|
|
|
public addEmptyAnimationAsync(options?: {
|
|
trackIndex?: number;
|
|
mixDuration?: number;
|
|
delay?: number;
|
|
}): Promise<sp.spine.TrackEntry> {
|
|
return new Promise((resolve) => {
|
|
this.addEmptyAnimation({
|
|
...options,
|
|
onComplete(entry) {
|
|
resolve(entry);
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
public clearTrack(trackIndex: number = 0): void {
|
|
if (!this.skeleton) return;
|
|
this.skeleton.clearTrack(trackIndex);
|
|
}
|
|
|
|
public clearTracks(): void {
|
|
if (!this.skeleton) return;
|
|
this.skeleton.clearTracks();
|
|
}
|
|
|
|
public findBone(boneName: string): sp.spine.Bone {
|
|
return this.skeleton.findBone(boneName);
|
|
}
|
|
|
|
public socketPathToString(socketPath: SocketPath): string {
|
|
return this.skeleton.querySockets()[socketPath];
|
|
}
|
|
|
|
public SpineAnimationToString(animationName: SpineAnimation): string {
|
|
return this.skeleton._skeleton.data.animations[animationName].name;
|
|
}
|
|
|
|
public SpineAnimationToAnimation(animationName: SpineAnimation): sp.spine.Animation {
|
|
return this.skeleton._skeleton.data.animations[animationName];
|
|
}
|
|
|
|
public addSocket(socketPath: SocketPath | string, target: Node): sp.SpineSocket {
|
|
let socket: sp.SpineSocket;
|
|
if (typeof socketPath === 'string') {
|
|
socket = new sp.SpineSocket(socketPath, target);
|
|
} else {
|
|
socket = new sp.SpineSocket(this.socketPathToString(socketPath), target);
|
|
}
|
|
this.skeleton.sockets.push(socket);
|
|
this.skeleton!.sockets = this.skeleton!.sockets;
|
|
return socket;
|
|
}
|
|
|
|
public updateSocketPath(socket: sp.SpineSocket, socketPath: SocketPath | string): sp.SpineSocket {
|
|
let newSocket: sp.SpineSocket;
|
|
if (typeof socketPath === 'string') {
|
|
newSocket = new sp.SpineSocket(socketPath, socket.target);
|
|
} else {
|
|
newSocket = new sp.SpineSocket(this.socketPathToString(socketPath), socket.target);
|
|
}
|
|
const index = this.skeleton.sockets.indexOf(socket);
|
|
this.skeleton.sockets[index] = newSocket;
|
|
this.skeleton!.sockets = this.skeleton!.sockets;
|
|
return newSocket;
|
|
}
|
|
|
|
public removeSocket(socket: sp.SpineSocket): void {
|
|
const index = this.skeleton.sockets.indexOf(socket);
|
|
this.skeleton.sockets.splice(index, 1);
|
|
this.skeleton!.sockets = this.skeleton!.sockets;
|
|
}
|
|
}
|