kunpolibrary/src/asset/AssetPool.ts
2025-05-11 18:21:30 +08:00

171 lines
5.2 KiB
TypeScript

/**
* @Author: Gongxh
* @Date: 2025-02-11
* @Description: 资源池
*/
import { Asset, AssetManager, resources } from "cc";
import { log } from "../tool/log";
import { AssetUtils } from "./AssetUtils";
export class AssetPool {
/**
* 资源名对应的资源
* @internal
*/
private static _assets: { [path: string]: Asset } = {};
/**
* uuid 对应的资源名
* @internal
*/
private static _uuidToName: Map<string, string> = new Map();
/**
* 资源加载批次对应的资源名
* @internal
*/
private static _batchAssetNames: Map<string, string[]> = new Map();
/** 批量添加资源 */
public static add(asset: Asset[] | Asset, bundle: AssetManager.Bundle = resources, batchName: string = ""): void {
if (Array.isArray(asset)) {
for (const item of asset) {
this.add(item, bundle, batchName);
}
} else {
let uuid = asset.uuid || asset._uuid;
if (this._uuidToName.has(uuid)) {
return;
}
// 增加引用计数
asset.addRef();
let info = bundle.getAssetInfo(uuid);
let key = this.getKey(info.path, bundle.name);
// log(`>>>uuid:${uuid}, path:${info.path}`);
this._uuidToName.set(uuid, key);
this._assets[key] = asset;
if (batchName) {
let names = this._batchAssetNames.get(batchName) || [];
names.push(key);
this._batchAssetNames.set(batchName, names);
}
}
}
public static has(path: string, bundlename: string = "resources"): boolean {
let key = this.getKey(path, bundlename);
if (!this._assets[key]) {
return false;
}
return true;
}
public static get<T extends Asset>(path: string, bundlename: string = "resources"): T {
let key = this.getKey(path, bundlename);
if (!this._assets[key]) {
log(`获取资源失败: 资源 bundle:${bundlename}, path:${path} 未加载`);
}
return this._assets[key] as T;
}
/** 按 uuid 判断资源是否存在 */
public static hasUUID(uuid: string): boolean {
if (!this._uuidToName.has(uuid)) {
return false;
}
return true;
}
/** 按 uuid 获取资源 */
public static getByUUID<T extends Asset>(uuid: string): T {
if (!this._uuidToName.has(uuid)) {
log(`获取资源失败: 资源 uuid:${uuid} 未加载`);
}
let key = this._uuidToName.get(uuid);
return this._assets[key] as T;
}
/**
* 按资源加载批次释放资源
* @param batchName 资源加载批次名 对应 AssetLoader 实例化时传入的 name
*/
public static releaseBatchAssets(batchName: string): void {
if (!this._batchAssetNames.has(batchName)) {
return;
}
let names = this._batchAssetNames.get(batchName);
for (const name of names) {
this.release(name);
}
this._batchAssetNames.delete(batchName);
}
/** 按资源路径释放资源 */
public static releasePath(path: string, bundlename: string = "resources"): void {
let key = this.getKey(path, bundlename);
this.release(key);
}
/** 按 bundle 和 文件夹释放资源 */
public static releaseDir(dir: string, bundlename: string = "resources", asset: typeof Asset): Promise<boolean> {
return new Promise((resolve, reject) => {
if (bundlename == "resources") {
let uuids = AssetUtils.getUUIDs(dir, asset, resources);
for (const uuid of uuids) {
this.releaseUUID(uuid);
}
resolve(true);
} else {
AssetUtils.loadBundle(bundlename).then((bundle: AssetManager.Bundle) => {
let uuids = AssetUtils.getUUIDs(dir, asset, bundle);
for (const uuid of uuids) {
this.releaseUUID(uuid);
}
resolve(true);
}).catch((err: Error) => {
reject(false);
});
}
});
}
/** 按 uuid 释放资源 */
public static releaseUUID(uuid: string): void {
if (this._uuidToName.has(uuid)) {
let key = this._uuidToName.get(uuid);
this.release(key);
}
}
/** 释放所有加载的资源 */
public static releaseAll(): void {
for (const key in this._assets) {
this._assets[key].decRef();
}
this._assets = {};
this._uuidToName.clear();
this._batchAssetNames.clear();
}
/**
* 按key释放资源
* @internal
*/
private static release(key: string): void {
if (this._assets[key]) {
this._uuidToName.delete(this._assets[key].uuid);
this._assets[key].decRef();
delete this._assets[key];
}
}
/**
* 获取资源 key
* @internal
*/
private static getKey(path: string, bundlename: string = "resources"): string {
return `${bundlename}:${path}`;
}
}