import { AssetManager, assetManager, resources, Prefab, sp, SpriteFrame, TiledMapAsset, Asset, instantiate, Node, AudioClip, VideoClip, SpriteAtlas, TextAsset, BufferAsset, __private } from "cc"; import { PREVIEW } from "cc/env"; import { EResUrls } from "./EResUrls"; import ResourceMemoryChecker from "../CComEx/ResourceMemoryChecker"; import { EBundleName } from "../const/GameEnum"; import { Utils } from "../ExUtils/Utils"; import CocosUtils from "../ExCUtils/CocosUtils"; import { TDAnalyticsMgr } from "../Mgr_Ge/TDAnalyticsMgr"; import { GEData } from "../Mgr_Ge/GeDifine"; type _types_globals__Constructor = new (...args: any[]) => T; export type CCAssetType = _types_globals__Constructor; /**函数类型 */ type BackBundleType = (err: Error | null, res: AssetManager.Bundle) => void; /**加载资源 返回函数类型 */ type LoadType = (err: Error | null, res: T | T[]) => void; /**预加载 返回函数类型 */ type preLoadType = (res: boolean) => void; /**预加载定义 */ interface preLoadInfo { bundle: string | EBundleName, preUIPrefab?: boolean, preDir?: string[], Dir?: string[], ui?: string[], pres?: string[], Atlas?: string[], AtlasAll?: boolean, Spine?: string[], SpineAll?: boolean, } /** * 资源加载类 */ export default class ResLoad { private static _ins: ResLoad = null; public static allDoen = false; public static get Ins(): ResLoad { if (!this._ins) { this._ins = new ResLoad(); } return this._ins; } /**常驻Bundle 不可释放*/ private PBundles: EBundleName | string[] = [ EBundleName.Presets, EBundleName.resources, EBundleName.General, ]; /**预加载Bundle */ private preLoadBundlelist: preLoadInfo[] = []; private preSecondBundlelist: preLoadInfo[] = []; /**预加载Bundle的数量 */ private preLoadBundleCount: number = 0; /**预加载Bundle完毕回调 */ private preLoadBundleComplete: () => void; /**加载bundle */ async loadBundle(BundleName: EBundleName | string, onComplete?: BackBundleType) { const res = await this.loadBundleAsync(BundleName); onComplete && onComplete(null, res); } async loadBundleAsync(BundleName: EBundleName | string) { return new Promise((resolve, reject) => { let bundle = assetManager.getBundle(BundleName); if (bundle) { resolve(bundle); } else { let tempTime = performance.now(); assetManager.loadBundle(BundleName, (err, bundle: AssetManager.Bundle) => { if (err) { resolve(null); } else { let offsetTime = performance.now() - tempTime; ConsoleEx.Warn(`${BundleName} 包加载耗时`, offsetTime); // TDAnalyticsMgr.ins.TrySendtrack(GEData.GEeventName.load_bundle, { bundle: BundleName, duration: Utils.MathUtils.MsToFloat(offsetTime) }) resolve(bundle); } }) } }); } ReleaseAll(list: string[]) { assetManager.bundles.forEach((value, key) => { if (!list.includes(key) && !this.PBundles.includes(key)) { value.releaseAll(); } }); } /**释放bundle资源 */ Release(name: EBundleName | string) { if (assetManager.bundles.has(name) && !this.PBundles.includes(name)) { assetManager.bundles.get(name).releaseAll(); } } InitLoadBundleList() { this.preLoadBundlelist = []; this.preSecondBundlelist = []; let _keys: string[] = Object.keys(EBundleName); for (let _key of _keys) { //先删除ts枚举自带的反向映射 if (/^[0-9]+$/.test(_key)) { } else { if (_key == EBundleName.resources) { continue; } let tData: preLoadInfo = { bundle: _key, preUIPrefab: true }; // tData.preDir = ["Texture"]; // tData.preUIPrefab = false; if(_key == EBundleName.Presets || _key == EBundleName.General || _key == EBundleName.Game){ this.preLoadBundlelist.push(tData); }else{ this.preSecondBundlelist.push(tData); } // this.preLoadBundlelist.push(tData); } } // this.preLoadBundleCount = this.preLoadBundlelist.length; // this.startLoadBundleList(this.preLoadBundlelist); } // preLoadSpineAsset(urls: string[]){ // let loadtime = Date.now(); // let assets: string[] = []; // for (let i = 0; i < urls.length; i++) { // assets.push(EResUrls.Spine(`${urls[i]}/${urls[i]}`)); // } // if(assets.length > 0){ // this.loadBundleAsync(EBundleName.Spine).then((bundle) => { // bundle.preload(urls, (e2, res) => {ConsoleEx.Com("Spine资源预加载成功:", urls, " 耗时:",Date.now() - loadtime)}); // }); // } // } InitFirstBundleList(compallcallback) { this.preLoadBundleComplete = compallcallback; this.preLoadBundleCount = this.preLoadBundlelist.length; this.startLoadBundleList(this.preLoadBundlelist); } InitSecendBundleList() { this.preLoadBundleCount = this.preSecondBundlelist.length; this.startLoadBundleList(this.preSecondBundlelist); ResLoad.allDoen = true; } startLoadBundleList(preBundlelist) { // this.preLoadBundleComplete = compallcallback; // while (preBundlelist.length > 0) { this.LoadBundleList(preBundlelist); // } } private async LoadBundleList(preBundlelist) { if (preBundlelist.length <= 0) { // ResLoad.allDoen = true; return; } let tpreData = preBundlelist.shift(); this.loadBundle(tpreData.bundle, (e, bundle: AssetManager.Bundle) => { if (--this.preLoadBundleCount <= 0) { // ResLoad.allDoen = true; this.preLoadBundleComplete && this.preLoadBundleComplete(); } if (e) { this.LoadBundleList(preBundlelist); return; } let urls: string[] = []; for (let i = 0; i < tpreData.ui?.length; i++) { urls.push(EResUrls.UIPrefabs(tpreData.ui[i])); } for (let i = 0; i < tpreData.pres?.length; i++) { urls.push(EResUrls.Prefabs(tpreData.pres[i])); } for (let i = 0; i < tpreData.Atlas?.length; i++) { //urls.push(EResUrls.Atlas(tpreData.Atlas[i])); } // for (let i = 0; i < tpreData.Spine?.length; i++) { // urls.push(EResUrls.Spine(`${tpreData.Spine[i]}/${tpreData.Spine[i]}`)); // } for (let i = 0; i < tpreData.Dir?.length; i++) { bundle.loadDir(tpreData.Dir[i], (err, res) => { PREVIEW && ConsoleEx.Com("路径加载完成", tpreData.bundle, tpreData.Dir[i]) }) } for (let i = 0; i < tpreData.preDir?.length; i++) { bundle.preloadDir(tpreData.preDir[i], (err, res) => { PREVIEW && ConsoleEx.Com("路径加载完成", tpreData.bundle, tpreData.preDir[i]) }) } if (tpreData.AtlasAll) { bundle.preloadDir("Atlas", (err, res) => { PREVIEW && ConsoleEx.Com("预加载图集完成", tpreData.bundle) }) } if (tpreData.preUIPrefab) { bundle.preloadDir("UIPrefabs", (err, res) => { PREVIEW && ConsoleEx.Com("预加载UI资源完成", tpreData.bundle) }) } if (urls.length <= 0) { this.LoadBundleList(preBundlelist); return; } bundle.preload(urls, (e2, res) => { if (PREVIEW) { let list: string[] = []; for (let i = 0; i < res.length; i++) { const tRes = res[i]; let bundleName = tpreData.bundle const tBundle = CocosUtils.GetResBundle(tRes.uuid) if (tBundle) { bundleName = tBundle.name as EBundleName; } let path = CocosUtils.GetResBundlePath(tRes.uuid); if (path == "") { path = tRes.uuid; } list.push(`${bundleName} ${path}`); } ConsoleEx.Com(tpreData.bundle, list) } this.LoadBundleList(preBundlelist); }) }); } /**根据名称 获取一个Bundle */ getBundle(BundleName?: string) { var bundle = assetManager.bundles.get(BundleName); if (bundle) { return bundle; } if (PREVIEW) { if (BundleName && BundleName != "resources") { ConsoleEx.Warn("未找到目标Bundle", BundleName) } } return resources; } async Perfab(url: string, bundle: EBundleName | string, callBack?: (error: Error, assets: Prefab) => void) { this.Load(url, bundle, Prefab, callBack); } PrePerfab(url: any, bundle: string, callBack?: preLoadType) { this.preLoad(url, bundle, Prefab, callBack); } /**预加载spine资源 */ PreSpine(url: any, bundle: string, callBack?: preLoadType) { this.preLoad(url, bundle, sp.SkeletonData, callBack); } /**预加载Sprite资源 */ PreSprite(url: any, bundle: string, callBack?: preLoadType) { this.preLoad(url + "/spriteFrame", bundle, SpriteFrame, callBack); } /**加载spine文件 */ Spine(url: any, bundle: string, callBack?: (error: Error, assets: sp.SkeletonData) => void) { this.Load(url, bundle, sp.SkeletonData, callBack); } /**加载spritefame */ public Sprite(url: string, bundle: string, callBack?: (error: Error, assets: SpriteFrame) => void) { this.Load(url + "/spriteFrame", bundle, SpriteFrame, callBack); } /**加载AudioClip */ public PreDirAudioClip(url: any, bundle: string, callBack?: (error: Error, assets: AudioClip[]) => void) { this.getBundle(bundle).preloadDir(url, AudioClip); } /**加载AudioClip */ public AudioClip(url: string, bundle: string, callBack?: (error: Error, assets: AudioClip) => void) { this.Load(url, bundle, AudioClip, callBack); } /**加载SpriteAtlas */ public AutoAtlas(url: any, bundle: string, callBack?: (error: Error, assets: SpriteAtlas) => void) { this.Load(url, bundle, SpriteAtlas, callBack); } /** * 加载资源 * @param urls 资源路径列表 * @param model 加载模式 * @param onCompleted 完成时回调 * @param _onProgress 加载进度 */ public Load(urls: string | string[], model: EBundleName | string, type: CCAssetType, onComplete?: LoadType, onProgress?: (finish?: any, total?: any, item?: any) => void) { this.LoadAsync(urls, model, type, onProgress).then((res) => { onComplete && onComplete(null, res as any); }) } /** * 加载资源 * @param urls 资源路径列表 * @param model 加载模式 * @param onCompleted 完成时回调 * @param _onProgress 加载进度 */ public preLoad(urls: string | string[], model: EBundleName | string, type: CCAssetType, onComplete?: preLoadType, onProgress?: (finish?: any, total?: any, item?: any) => void) { this.preLoadAsync(urls, model, type, onProgress).then((res) => { onComplete && onComplete(res); }) } /** * 加载资源 * @param urls 资源路径列表 * @param model 加载模式 * @param onCompleted 完成时回调 * @param _onProgress 加载进度 */ public async LoadAsync(urls: string | string[], bName: string, type: CCAssetType, onProgress?: (finish?: any, total?: any, item?: any) => void) { if (Array.isArray(urls)) { //去除虚值 urls = urls.filter(Boolean); } let bundle = await this.loadBundleAsync(bName); if (Array.isArray(urls)) { return new Promise((resolve, reject) => { bundle.load(urls, type, onProgress, (err, res: T[]) => { if (err) { resolve(null); } else { resolve(res); } }); }); } else { return new Promise((resolve, reject) => { bundle.load(urls, type, onProgress, (err, res: T) => { if (err) { resolve(null); } else { resolve(res); } }); }); } } /** * 加载资源 * @param urls 资源路径列表 * @param model 加载模式 * @param onCompleted 完成时回调 * @param _onProgress 加载进度 */ public async preLoadAsync(urls: string | string[], bName: string, type: CCAssetType, onProgress?: (finish?: any, total?: any, item?: any) => void) { if (Array.isArray(urls)) { //去除虚值 urls = urls.filter(Boolean); } const bundle = await this.loadBundleAsync(bName); if (!bundle) { ConsoleEx.Error("加载失败!", bName); return; } if (Array.isArray(urls)) { return new Promise((resolve, reject) => { bundle.preload(urls, type, onProgress, (err) => { if (err) { resolve(false); } else { resolve(true); } }); }); } else { return new Promise((resolve, reject) => { bundle.preload(urls, type, onProgress, (err) => { if (err) { resolve(false); } else { resolve(true); } }); }); } } /** * 获取资源 * @param resUrl 资源路径 * @param noClone 是否不获取克隆的资源 */ public GetRes(resUrl: string, BundleName?: EBundleName | string, noClone: boolean = false, type = Asset): any { if (!resUrl) { return ConsoleEx.Error(resUrl, "路径错误!") } const Bundle: AssetManager.Bundle = this.getBundle(BundleName); const getRes = Bundle.get(resUrl, type); if (!getRes) { ConsoleEx.Warn("资源尚未加载", resUrl); return null; } return noClone ? getRes : instantiate(getRes); } public GetTextureMemory() { console.log(ResourceMemoryChecker.generateMemoryReport()) } } if (PREVIEW) { window['ResLoad'] = ResLoad; }