大侠
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.
 
 
 

421 lines
15 KiB

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<T = unknown> = new (...args: any[]) => T;
export type CCAssetType<T = Asset> = _types_globals__Constructor<T>;
/**函数类型 */
type BackBundleType = (err: Error | null, res: AssetManager.Bundle) => void;
/**加载资源 返回函数类型 */
type LoadType<T extends Asset | Asset[]> = (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<AssetManager.Bundle>((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<T extends Asset>(urls: string | string[], model: EBundleName | string, type: CCAssetType<T>, onComplete?: LoadType<T>, 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<T extends Asset>(urls: string | string[], model: EBundleName | string, type: CCAssetType<T>, 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<T extends Asset>(urls: string | string[], bName: string, type: CCAssetType<T>, 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<T[]>((resolve, reject) => {
bundle.load(urls, type, onProgress, (err, res: T[]) => {
if (err) {
resolve(null);
} else {
resolve(res);
}
});
});
} else {
return new Promise<T>((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<T extends Asset>(urls: string | string[], bName: string, type: CCAssetType<T>, 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<boolean>((resolve, reject) => {
bundle.preload(urls, type, onProgress, (err) => {
if (err) {
resolve(false);
} else {
resolve(true);
}
});
});
} else {
return new Promise<boolean>((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;
}