消消方块阵换皮表情
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.7 KiB

1 week ago
import { Node, assetManager, sp, AssetManager, Vec3 } from 'cc';
import { ensureSpineAssetResetEnums } from '../module/lang/spineRuntimePatch';
/**
* SpineLoader Spine
*/
export class SpineLoader {
/**
* Spine
* @param bundleName - Asset Bundle
* @param spinePath - Spine bundle
* @param parentNode - Spine
* @param animationName -
* @param loop -
* @param onComplete -
* @returns Promise<sp.Skeleton> - Spine Skeleton
*/
public static async loadAndPlaySpine(
bundleName: string,
spinePath: string,
animationName: string,
parentNode: Node,
position: Vec3 = Vec3.ZERO,
loop: boolean = true,
onComplete?: () => void
): Promise<sp.Skeleton> {
return new Promise(async (resolve, reject) => {
try {
// 加载指定的 Asset Bundle
const bundle = await this.loadBundle(bundleName);
// 加载 Spine 资源
const spineAsset = await this.loadSpineAsset(bundle, spinePath);
spineAsset.addRef();
// 创建 Spine 节点
const spineNode = this.createSpineNode(spineAsset);
// 将 Spine 节点添加到父节点
parentNode.addChild(spineNode);
spineNode.setPosition(position);
// 获取 Spine Skeleton 组件
const skeleton = spineNode.getComponent(sp.Skeleton);
if (!skeleton) {
throw new Error("Failed to get Skeleton component from Spine node.");
}
// 播放指定动画
skeleton.setAnimation(0, animationName, loop);
// 如果是非循环模式,监听动画完成事件
if (!loop) {
skeleton.setCompleteListener(() => {
spineAsset.decRef();
spineNode.destroy();
if (onComplete) onComplete();
})
}
resolve(skeleton);
} catch (error) {
reject(error);
}
});
}
/**
* Spine
* @param bundleName - Asset Bundle
* @param spinePath - Spine bundle
* @param animationName -
* @returns Promise<number> -
*/
public static async getAnimationDuration(
bundleName: string,
spinePath: string,
animationName: string
): Promise<number> {
return new Promise(async (resolve, reject) => {
try {
// 加载指定的 Asset Bundle
const bundle = await this.loadBundle(bundleName);
// 加载 Spine 资源
const spineAsset = await this.loadSpineAsset(bundle, spinePath);
// 获取动画数据
const animation = spineAsset.getRuntimeData().findAnimation(animationName);
if (!animation) {
reject(`Animation "${animationName}" not found in Spine asset.`);
} else {
resolve(animation.duration); // 返回动画时长
}
} catch (error) {
reject(error);
}
});
}
/**
* Asset Bundle
* @param bundleName - Asset Bundle
* @returns Promise<AssetManager.Bundle> - Asset Bundle
*/
private static loadBundle(bundleName: string): Promise<AssetManager.Bundle> {
return new Promise((resolve, reject) => {
let bundle = assetManager.getBundle(bundleName);
if (bundle) {
resolve(bundle);
return;
}
assetManager.loadBundle(bundleName, (err, bundle) => {
if (err) {
reject(`Failed to load bundle: ${bundleName}, error: ${err.message}`);
} else {
resolve(bundle);
}
});
});
}
/**
* Spine
* @param bundle - Asset Bundle
* @param spinePath - Spine
* @returns Promise<sp.SkeletonData> - Spine
*/
private static loadSpineAsset(bundle: AssetManager.Bundle, spinePath: string): Promise<sp.SkeletonData> {
return new Promise((resolve, reject) => {
let asset = bundle.get(spinePath, sp.SkeletonData);
if (asset) {
resolve(asset);
return;
}
bundle.load(spinePath, sp.SkeletonData, (err, asset) => {
if (err) {
reject(`Failed to load Spine asset: ${spinePath}, error: ${err.message}`);
} else {
resolve(asset);
}
});
});
}
/**
* Spine
* @param spineAsset - Spine
* @returns Node - Spine
*/
private static createSpineNode(spineAsset: sp.SkeletonData): Node {
ensureSpineAssetResetEnums(spineAsset);
const spineNode = new Node();
const skeleton = spineNode.addComponent(sp.Skeleton);
skeleton.skeletonData = spineAsset;
return spineNode;
}
}