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.
193 lines
6.0 KiB
193 lines
6.0 KiB
|
3 weeks ago
|
|
||
|
|
import { _decorator, Component, Node, Sprite, director, SpriteFrame, sp, AssetManager, Asset, assetManager, isValid } from 'cc';
|
||
|
|
import { GBundle } from '../game/ConfigRes';
|
||
|
|
|
||
|
|
const { ccclass, property } = _decorator;
|
||
|
|
|
||
|
|
/**加载 加载动画 皮肤的组件*/
|
||
|
|
@ccclass('lLoadSpine')
|
||
|
|
export class lLoadSpine extends Component {
|
||
|
|
@property(sp.Skeleton)
|
||
|
|
kaichangSpine: sp.Skeleton = null;
|
||
|
|
@property(sp.Skeleton)
|
||
|
|
zhuizhuSpine: sp.Skeleton = null;
|
||
|
|
|
||
|
|
path: string = "";
|
||
|
|
|
||
|
|
key: string = "";
|
||
|
|
|
||
|
|
|
||
|
|
animation: string = "开场动画";
|
||
|
|
skinName: string = "默认皮肤";
|
||
|
|
|
||
|
|
langSp: sp.Skeleton = null;
|
||
|
|
curentSpineData: sp.SkeletonData = null;
|
||
|
|
/** 已成功加载并挂上的资源路径,用于同皮肤重复进入时跳过后台 load */
|
||
|
|
private _lastLoadedAssetPath: string = '';
|
||
|
|
private isLoading: boolean = false; // ✅ 添加加载锁
|
||
|
|
private abortController: { aborted: boolean } = null; // ✅ 添加取消机制
|
||
|
|
|
||
|
|
onLoad() {
|
||
|
|
this.langSp = this.getComponent(sp.Skeleton);
|
||
|
|
}
|
||
|
|
|
||
|
|
onEnable() {
|
||
|
|
this.updateLang();
|
||
|
|
}
|
||
|
|
|
||
|
|
onDisable() {
|
||
|
|
if (this.abortController) {
|
||
|
|
this.abortController.aborted = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
onDestroy() {
|
||
|
|
if (this.abortController) {
|
||
|
|
this.abortController.aborted = true;
|
||
|
|
}
|
||
|
|
if (this.curentSpineData && isValid(this.curentSpineData)) {
|
||
|
|
this.curentSpineData.decRef();
|
||
|
|
this.curentSpineData = null;
|
||
|
|
}
|
||
|
|
this._lastLoadedAssetPath = '';
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 与 load 时一致的 Spine 资源相对路径(不含扩展名) */
|
||
|
|
private getAssetPath(): string {
|
||
|
|
const k = this.key || this.node.name;
|
||
|
|
return `${k}/${this.path}`;
|
||
|
|
}
|
||
|
|
|
||
|
|
updateLang() {
|
||
|
|
if (!this.node.isValid || this.langSp == null) return;
|
||
|
|
|
||
|
|
const assetPath = this.getAssetPath();
|
||
|
|
if (
|
||
|
|
this._lastLoadedAssetPath === assetPath &&
|
||
|
|
this.curentSpineData &&
|
||
|
|
isValid(this.curentSpineData) &&
|
||
|
|
this.langSp.skeletonData === this.curentSpineData
|
||
|
|
) {
|
||
|
|
// console.log("spineAsset 已加载", this.path, this.key);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (this.abortController) {
|
||
|
|
this.abortController.aborted = true;
|
||
|
|
}
|
||
|
|
this.abortController = { aborted: false };
|
||
|
|
|
||
|
|
if (this.isLoading) return;
|
||
|
|
this.isLoading = true;
|
||
|
|
|
||
|
|
const currentAbort = this.abortController;
|
||
|
|
const bundleName = GBundle.Comm;
|
||
|
|
const loop = this.langSp.loop;
|
||
|
|
|
||
|
|
// console.log("更新 lLoadSpine 组件", this.path, this.key);
|
||
|
|
|
||
|
|
this.loadBundle(bundleName).then((bundle) => {
|
||
|
|
if (currentAbort.aborted || !this.node.isValid) {
|
||
|
|
this.isLoading = false;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
if (!bundle) {
|
||
|
|
this.isLoading = false;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return this.loadRes(bundle, assetPath, sp.SkeletonData);
|
||
|
|
}).then((spineAsset) => {
|
||
|
|
if (!spineAsset) return;
|
||
|
|
if (currentAbort.aborted || !this.node.isValid) {
|
||
|
|
this._releaseOrphanSpineAsset(spineAsset as sp.SkeletonData);
|
||
|
|
this.isLoading = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const data = spineAsset as sp.SkeletonData;
|
||
|
|
if (this.curentSpineData == data) {
|
||
|
|
assetManager.releaseAsset(data);
|
||
|
|
this._lastLoadedAssetPath = assetPath;
|
||
|
|
this.isLoading = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const oldres = this.curentSpineData;
|
||
|
|
this.curentSpineData = data;
|
||
|
|
data.addRef();
|
||
|
|
this._lastLoadedAssetPath = assetPath;
|
||
|
|
|
||
|
|
// console.log("spineAsset 加载完成", this.path, this.key);
|
||
|
|
|
||
|
|
this.langSp.clearTrack(0);
|
||
|
|
this.langSp.skeletonData = data;
|
||
|
|
|
||
|
|
if (this.node.isValid && this.animation) {
|
||
|
|
this.langSp.setSkin(this.skinName);
|
||
|
|
this.langSp.setAnimation(0, this.animation, loop);
|
||
|
|
this.kaichangSpine.setAnimation(0, '开场动画', loop);
|
||
|
|
this.zhuizhuSpine.setAnimation(0, '怪物追逐', loop);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (oldres && oldres != data) {
|
||
|
|
this.scheduleOnce(() => {
|
||
|
|
if (oldres.refCount > 0) {
|
||
|
|
oldres.decRef();
|
||
|
|
}
|
||
|
|
}, 0.1);
|
||
|
|
}
|
||
|
|
this.isLoading = false;
|
||
|
|
}).catch((error) => {
|
||
|
|
// console.log("更新 lLoadSpine 组件失败", error);
|
||
|
|
this.isLoading = false;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
setKey(key: string) {
|
||
|
|
this.key = key;
|
||
|
|
this.updateLang();
|
||
|
|
}
|
||
|
|
|
||
|
|
setPath(path: string) {
|
||
|
|
this.path = path;
|
||
|
|
this.updateLang();
|
||
|
|
}
|
||
|
|
|
||
|
|
private _releaseOrphanSpineAsset(spineAsset: sp.SkeletonData | null): void {
|
||
|
|
if (!spineAsset || spineAsset === this.curentSpineData) return;
|
||
|
|
assetManager.releaseAsset(spineAsset);
|
||
|
|
}
|
||
|
|
|
||
|
|
private loadBundle(bundleName) {
|
||
|
|
return new Promise<AssetManager.Bundle>((resolve, reject) => {
|
||
|
|
let bundle = assetManager.getBundle(bundleName);
|
||
|
|
if (bundle) {
|
||
|
|
resolve(bundle);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
assetManager.loadBundle(bundleName, (err, bundle) => {
|
||
|
|
if (err) {
|
||
|
|
// console.log(`加载Bundle:${bundleName}错误`, err);
|
||
|
|
resolve(null);
|
||
|
|
} else {
|
||
|
|
resolve(bundle);
|
||
|
|
}
|
||
|
|
})
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
private loadRes(bundle: AssetManager.Bundle, assetPath, type = Asset) {
|
||
|
|
return new Promise<Asset>((resolve, reject) => {
|
||
|
|
bundle.load(assetPath, type, (err, asset) => {
|
||
|
|
if (err) {
|
||
|
|
// console.log(`加载Bundle:${bundle.name},path:${assetPath}资源错误`, err);
|
||
|
|
resolve(null);
|
||
|
|
} else {
|
||
|
|
resolve(asset);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|