cocoCreator 远程spine加载

import { ResV1RoleGameAvgDetailRoleGame } from '../netController/CXResponse';

const { ccclass } = cc._decorator;
export type SkeletonDataType = { imageUrl: string; skeJsonUrl: string; atlasUrl: string };
export type SkeletonMapType = {
    name: string;
    skeData: sp.SkeletonData;
    image: cc.Texture2D;
    skeJson: string | null;
    atlas: string | null;
};
export type TSpineResData = NonNullable<
    NonNullable<ResV1RoleGameAvgDetailRoleGame>['data']
>['spineFiles']['0'];

@ccclass
export default class SpineController {
    private map: { [key: string]: { res: SkeletonMapType; tag: Array<number> } } = {};
    // eslint-disable-next-line no-use-before-define
    private static P: SpineController;

    static get instance() {
        if (!SpineController.P) {
            SpineController.P = new SpineController();
        }
        return SpineController.P;
    }

    public async loadStorySpineAssets(storyId: number, dataList: TSpineResData[]) {
        if (!dataList || dataList.length === 0) return Promise.resolve();
        const promiseArray: Array<Promise<SkeletonMapType>> = [];
        for (let i = 0, len = dataList.length; i < len; i++) {
            const tmpValue = dataList[i];
            const param: SkeletonDataType = {
                imageUrl: '',
                skeJsonUrl: '',
                atlasUrl: '',
            };
            tmpValue.files?.forEach((value) => {
                switch (value.name.split('.').pop()) {
                    case 'png':
                        param.imageUrl = value.key || '';
                        break;
                    case 'json':
                        param.skeJsonUrl = value.key || '';
                        break;
                    case 'atlas':
                        param.atlasUrl = value.key || '';
                        break;
                }
            });
            if (param.imageUrl && param.skeJsonUrl && param.atlasUrl) {
                promiseArray.push(this.load(param, tmpValue.spineName || ''));
            } else {
                console.error(storyId, ' spine资源缺失 :', tmpValue.spineName);
            }
        }
        const resources = await Promise.all(promiseArray);
        resources.forEach((res, index) => {
            if (this.map[res.name]) {
                this.map[res.name].tag.includes(storyId)
                    ? null
                    : this.map[dataList[index].spineName].tag.push(storyId);
            } else {
                this.map[res.name] = {
                    res: res,
                    tag: [storyId],
                };
            }
        });
    }

    public releaseStorySpineAssets(storyId: number) {
        // release all spine  by storyId
        Object.keys(this.map).forEach((key) => {
            const value = this.map[key];
            const storyIndex = value.tag.indexOf(storyId);
            if (storyIndex !== -1) {
                value.tag.splice(storyIndex, 1);
                if (value.tag.length === 0) {
                    this.releaseSkeletonData(key);
                }
            }
        });
    }

    private load(data: SkeletonDataType, name: string): Promise<SkeletonMapType> {
        const { imageUrl, skeJsonUrl, atlasUrl } = data;
        return new Promise((resolve, reject) => {
            if (this.map[name]) {
                resolve(this.map[name].res);
                return;
            }
            cc.assetManager.loadAny(
                [
                    { url: atlasUrl, ext: '.txt' },
                    { url: skeJsonUrl, ext: '.txt' },
                ],
                (error, assets: Array<string>) => {
                    if (error) {
                        reject(error);
                    } else {
                        cc.assetManager.loadRemote(imageUrl, (error, img: cc.Texture2D) => {
                            if (error) {
                                reject(error);
                            } else {
                                const skeData = new sp.SkeletonData();
                                skeData.skeletonJson = assets[1];
                                skeData.atlasText = assets[0].toString();
                                skeData.textures = [img];
                                img.genMipmaps = true;
                                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                                //@ts-ignore
                                const s = imageUrl.split('/').pop().split('?').shift();
                                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                                //@ts-ignore
                                skeData.textureNames = [s];
                                const uuid = new Date().getTime().toString();
                                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                                //@ts-ignore
                                skeData._uuid = uuid;
                                resolve({
                                    name: name,
                                    skeData: skeData,
                                    skeJson: assets[1],
                                    atlas: assets[0],
                                    image: img,
                                });
                            }
                        });
                    }
                }
            );
        });
    }

    private releaseSkeletonData(name: string) {
        const deleteItem = this.map[name];
        deleteItem.res.skeData.destroy();
        cc.assetManager.releaseAsset(deleteItem.res.image);
        deleteItem.res.atlas = null;
        deleteItem.res.skeJson = null;
        delete this.map[name];
    }

    getSpineData(name: string) {
        return this.map[name].res.skeData;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值