Files
oops-plugin-framework/assets/core/common/loader/ResLoader.ts
2024-05-16 17:28:02 +08:00

336 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Asset, AssetManager, Constructor, __private, assetManager, error, js, resources } from "cc";
export type ProgressCallback = __private._cocos_asset_asset_manager_deprecated__LoadProgressCallback;
export type CompleteCallback<T = any> = any; // (error: Error | null, asset: T) => void; (error: Error | null, asset: T[], urls: string[]) => void;
export type IRemoteOptions = { [k: string]: any; ext?: string; } | null;
export type AssetType<T = Asset> = Constructor<T>;
interface ILoadResArgs<T extends Asset> {
bundle?: string;
dir?: string;
paths: string | string[];
type: AssetType<T> | null;
onProgress: ProgressCallback | null;
onComplete: CompleteCallback<T> | null;
}
/**
* 游戏资管理
* 1、加载默认resources文件夹中资源
* 2、加载默认bundle远程资源
* 3、主动传递bundle名时优先加载传递bundle名资源包中的资源
*/
export class ResLoader {
/** 全局默认加载的资源包名 */
defaultBundleName: string = "resources";
/**
* 加载远程资源
* @param url 资源地址
* @param options 资源参数,例:{ ext: ".png" }
* @param onComplete 加载完成回调
* @example
var opt: IRemoteOptions = { ext: ".png" };
var onComplete = (err: Error | null, data: ImageAsset) => {
const texture = new Texture2D();
texture.image = data;
const spriteFrame = new SpriteFrame();
spriteFrame.texture = texture;
var sprite = this.sprite.addComponent(Sprite);
sprite.spriteFrame = spriteFrame;
}
oops.res.loadRemote<ImageAsset>(this.url, opt, onComplete);
*/
loadRemote<T extends Asset>(url: string, options: IRemoteOptions | null, onComplete?: CompleteCallback<T> | null): void;
loadRemote<T extends Asset>(url: string, onComplete?: CompleteCallback<T> | null): void;
loadRemote<T extends Asset>(url: string, ...args: any): void {
var options: IRemoteOptions | null = null;
var onComplete: CompleteCallback<T> | null = null;
if (args.length == 2) {
options = args[0];
onComplete = args[1];
}
else {
onComplete = args[0];
}
assetManager.loadRemote<T>(url, options, onComplete);
}
/**
* 加载资源包
* @param url 资源地址
* @param complete 完成事件
* @param v 资源MD5版本号
* @example
var serverUrl = "http://192.168.1.8:8080/"; // 服务器地址
var md5 = "8e5c0"; // Cocos Creator 构建后的MD5字符
await oops.res.loadBundle(serverUrl,md5);
*/
loadBundle(url: string, v?: string) {
return new Promise<AssetManager.Bundle>((resolve, reject) => {
assetManager.loadBundle(url, { version: v }, (err, bundle: AssetManager.Bundle) => {
if (err) {
return error(err);
}
resolve(bundle);
});
});
}
/**
* 加载一个资源
* @param bundleName 远程包名
* @param paths 资源路径
* @param type 资源类型
* @param onProgress 加载进度回调
* @param onComplete 加载完成回调
* @example
oops.res.load("spine_path", sp.SkeletonData, (err: Error | null, sd: sp.SkeletonData) => {
});
*/
load<T extends Asset>(bundleName: string, paths: string | string[], type: AssetType<T> | null, onProgress: ProgressCallback | null, onComplete: CompleteCallback<T> | null): void;
load<T extends Asset>(bundleName: string, paths: string | string[], onProgress: ProgressCallback | null, onComplete: CompleteCallback<T> | null): void;
load<T extends Asset>(bundleName: string, paths: string | string[], onComplete?: CompleteCallback<T> | null): void;
load<T extends Asset>(bundleName: string, paths: string | string[], type: AssetType<T> | null, onComplete?: CompleteCallback<T> | null): void;
load<T extends Asset>(paths: string | string[], type: AssetType<T> | null, onProgress: ProgressCallback | null, onComplete: CompleteCallback<T> | null): void;
load<T extends Asset>(paths: string | string[], onProgress: ProgressCallback | null, onComplete: CompleteCallback<T> | null): void;
load<T extends Asset>(paths: string | string[], onComplete?: CompleteCallback<T> | null): void;
load<T extends Asset>(paths: string | string[], type: AssetType<T> | null, onComplete?: CompleteCallback<T> | null): void;
load<T extends Asset>(
bundleName: string,
paths?: string | string[] | AssetType<T> | ProgressCallback | CompleteCallback | null,
type?: AssetType<T> | ProgressCallback | CompleteCallback | null,
onProgress?: ProgressCallback | CompleteCallback | null,
onComplete?: CompleteCallback | null,
) {
let args: ILoadResArgs<T> | null = null;
if (typeof paths === "string" || paths instanceof Array) {
args = this.parseLoadResArgs(paths, type, onProgress, onComplete);
args.bundle = bundleName;
}
else {
args = this.parseLoadResArgs(bundleName, paths, type, onProgress);
args.bundle = this.defaultBundleName;
}
this.loadByArgs(args);
}
loadAsync<T extends Asset>(bundleName: string, paths: string | string[], type: AssetType<T> | null): Promise<T>;
loadAsync<T extends Asset>(bundleName: string, paths: string | string[]): Promise<T>;
loadAsync<T extends Asset>(bundleName: string, paths: string | string[]): Promise<T>;
loadAsync<T extends Asset>(bundleName: string, paths: string | string[], type: AssetType<T> | null): Promise<T>;
loadAsync<T extends Asset>(paths: string | string[], type: AssetType<T> | null): Promise<T>;
loadAsync<T extends Asset>(paths: string | string[]): Promise<T>;
loadAsync<T extends Asset>(paths: string | string[]): Promise<T>;
loadAsync<T extends Asset>(paths: string | string[], type: AssetType<T> | null): Promise<T>;
loadAsync<T extends Asset>(bundleName: string, paths?: string | string[] | AssetType<T> | ProgressCallback | CompleteCallback | null, type?: AssetType<T> | ProgressCallback | CompleteCallback | null): Promise<T> {
return new Promise((resolve, reject) => {
this.load(bundleName, paths, type, (err: Error | null, asset: T) => {
if (err) {
error(err.message);
}
resolve(asset);
});
});
}
/**
* 加载文件夹中的资源
* @param bundleName 远程包名
* @param dir 文件夹名
* @param type 资源类型
* @param onProgress 加载进度回调
* @param onComplete 加载完成回调
* @example
// 加载进度事件
var onProgressCallback = (finished: number, total: number, item: any) => {
console.log("资源加载进度", finished, total);
}
// 加载完成事件
var onCompleteCallback = () => {
console.log("资源加载完成");
}
oops.res.loadDir("game", onProgressCallback, onCompleteCallback);
*/
loadDir<T extends Asset>(bundleName: string, dir: string, type: AssetType<T> | null, onProgress: ProgressCallback | null, onComplete: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(bundleName: string, dir: string, onProgress: ProgressCallback | null, onComplete: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(bundleName: string, dir: string, onComplete?: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(bundleName: string, dir: string, type: AssetType<T> | null, onComplete?: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(dir: string, type: AssetType<T> | null, onProgress: ProgressCallback | null, onComplete: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(dir: string, onProgress: ProgressCallback | null, onComplete: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(dir: string, onComplete?: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(dir: string, type: AssetType<T> | null, onComplete?: CompleteCallback<T[]> | null): void;
loadDir<T extends Asset>(
bundleName: string,
dir?: string | AssetType<T> | ProgressCallback | CompleteCallback | null,
type?: AssetType<T> | ProgressCallback | CompleteCallback | null,
onProgress?: ProgressCallback | CompleteCallback | null,
onComplete?: CompleteCallback | null,
) {
let args: ILoadResArgs<T> | null = null;
if (typeof dir === "string") {
args = this.parseLoadResArgs(dir, type, onProgress, onComplete);
args.bundle = bundleName;
}
else {
args = this.parseLoadResArgs(bundleName, dir, type, onProgress);
args.bundle = this.defaultBundleName;
}
args.dir = args.paths as string;
this.loadByArgs(args);
}
/**
* 通过资源相对路径释放资源
* @param path 资源路径
* @param bundleName 远程资源包名
*/
release(path: string, bundleName?: string) {
if (bundleName == null) bundleName = this.defaultBundleName;
var bundle = assetManager.getBundle(bundleName);
if (bundle) {
var asset = bundle.get(path);
if (asset) {
this.releasePrefabtDepsRecursively(asset);
}
}
}
/**
* 通过相对文件夹路径删除所有文件夹中资源
* @param path 资源文件夹路径
* @param bundleName 远程资源包名
*/
releaseDir(path: string, bundleName?: string) {
if (bundleName == null) bundleName = this.defaultBundleName;
var bundle: AssetManager.Bundle | null = assetManager.getBundle(bundleName);
if (bundle) {
var infos = bundle.getDirWithPath(path);
if (infos) {
infos.map((info) => {
this.releasePrefabtDepsRecursively(info.uuid);
});
}
if (path == "" && bundleName != "resources") {
assetManager.removeBundle(bundle);
}
}
}
/** 释放预制依赖资源 */
private releasePrefabtDepsRecursively(uuid: string | Asset) {
if (uuid instanceof Asset) {
uuid.decRef();
// assetManager.releaseAsset(uuid);
}
else {
var asset = assetManager.assets.get(uuid);
if (asset) {
asset.decRef();
// assetManager.releaseAsset(asset);
}
}
// Cocos引擎内部已处理子关联资源的释放
// if (asset instanceof Prefab) {
// var uuids: string[] = assetManager.dependUtil.getDepsRecursively(uuid)!;
// uuids.forEach(uuid => {
// var asset = assetManager.assets.get(uuid)!;
// asset.decRef();
// });
// }
}
/**
* 获取资源
* @param path 资源路径
* @param type 资源类型
* @param bundleName 远程资源包名
*/
get<T extends Asset>(path: string, type?: __private.__types_globals__Constructor<T> | null, bundleName?: string): T | null {
if (bundleName == null) bundleName = this.defaultBundleName;
var bundle: AssetManager.Bundle = assetManager.getBundle(bundleName)!;
return bundle.get(path, type);
}
/** 打印缓存中所有资源信息 */
dump() {
assetManager.assets.forEach((value: Asset, key: string) => {
console.log(assetManager.assets.get(key));
})
console.log(`当前资源总数:${assetManager.assets.count}`);
}
private parseLoadResArgs<T extends Asset>(
paths: string | string[],
type?: AssetType<T> | ProgressCallback | CompleteCallback | null,
onProgress?: AssetType<T> | ProgressCallback | CompleteCallback | null,
onComplete?: ProgressCallback | CompleteCallback | null
) {
let pathsOut: any = paths;
let typeOut: any = type;
let onProgressOut: any = onProgress;
let onCompleteOut: any = onComplete;
if (onComplete === undefined) {
const isValidType = js.isChildClassOf(type as AssetType, Asset);
if (onProgress) {
onCompleteOut = onProgress as CompleteCallback;
if (isValidType) {
onProgressOut = null;
}
}
else if (onProgress === undefined && !isValidType) {
onCompleteOut = type as CompleteCallback;
onProgressOut = null;
typeOut = null;
}
if (onProgress !== undefined && !isValidType) {
onProgressOut = type as ProgressCallback;
typeOut = null;
}
}
return { paths: pathsOut, type: typeOut, onProgress: onProgressOut, onComplete: onCompleteOut };
}
private loadByBundleAndArgs<T extends Asset>(bundle: AssetManager.Bundle, args: ILoadResArgs<T>): void {
if (args.dir) {
bundle.loadDir(args.paths as string, args.type, args.onProgress, args.onComplete);
}
else {
if (typeof args.paths == 'string') {
bundle.load(args.paths, args.type, args.onProgress, args.onComplete);
}
else {
bundle.load(args.paths, args.type, args.onProgress, args.onComplete);
}
}
}
private loadByArgs<T extends Asset>(args: ILoadResArgs<T>) {
if (args.bundle) {
if (assetManager.bundles.has(args.bundle)) {
let bundle = assetManager.bundles.get(args.bundle);
this.loadByBundleAndArgs(bundle!, args);
}
else {
// 自动加载bundle
assetManager.loadBundle(args.bundle, (err, bundle) => {
if (!err) {
this.loadByBundleAndArgs(bundle, args);
}
})
}
}
else {
this.loadByBundleAndArgs(resources, args);
}
}
}