| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import { BUNDLE_ID } from '@scripts/define/ResDefine';
- import { Asset, assetManager, AssetManager, ImageAsset, Prefab, Sprite, SpriteFrame, Texture2D } from 'cc';
- export enum ResourceScope {
- App = 'app',
- Scene = 'scene',
- View = 'view',
- }
- interface RemoteRes<T> {
- url: string,
- asset?: T,
- task?: Promise<Asset>;
- }
- interface ResLoader<T> {
- asset: T,
- }
- export class ResourceManager {
- private readonly bundles = new Map<string, AssetManager.Bundle>();
- private readonly remotes = new Map<string, RemoteRes<Asset>>();
- private readonly loaders = new Map<string, Promise<Asset>>();
- private getLoaderKey(bundleName: string, path: string, typeName: string) {
- return `Bundle:${bundleName}-path:${path}-type:${typeName}`;
- }
- private async getResLoading<T extends Asset>(key: string): Promise<T> {
- if (this.loaders.has(key)) {
- const res = await this.loaders.get(key);
- return res as T;
- }
- }
- async loadBundle(name: string): Promise<AssetManager.Bundle> {
- const cached = this.bundles.get(name) ?? assetManager.getBundle(name);
- if (cached) {
- this.bundles.set(name, cached);
- return cached;
- }
- return new Promise((resolve, reject) => {
- assetManager.loadBundle(name, (error, bundle) => {
- if (error || !bundle) {
- reject(error ?? new Error(`Bundle not found: ${name}`));
- return;
- }
- this.bundles.set(name, bundle);
- resolve(bundle);
- });
- });
- }
- private async onLoad<T extends Asset>(key: string, loader: Promise<T>) {
- this.loaders.set(key, loader);
- try {
- const res = await loader;
- this.loaders.delete(key);
- return res as T;
- } catch {
- this.loaders.delete(key);
- return null;
- }
- }
- async load<T extends Asset>(bundleName: string, path: string, type: new (...args: never[]) => T): Promise<T> {
- const key = this.getLoaderKey(bundleName, path, type.name);
- if (this.loaders.has(key)) {
- const res = await this.loaders.get(key);
- return res as T;
- }
- const bundle = await this.loadBundle(bundleName);
- const loader = new Promise<T>((resolve, reject) => {
- bundle.load<T>(path, type, (error, asset) => {
- if (error || !asset) {
- console.log(`asset load error!! file:${bundleName}/${path} error:${error}`);
- resolve(null);
- return;
- }
- resolve(asset);
- });
- });
- return await this.onLoad<T>(key, loader);
- }
- loadPrefab(bundleName: string, path: string): Promise<Prefab> {
- return this.load(bundleName, path, Prefab);
- }
- releaseBundle(name: string): void {
- const bundle = this.bundles.get(name);
- if (!bundle) return;
- bundle.releaseAll();
- assetManager.removeBundle(bundle);
- this.bundles.delete(name);
- }
- async loadRemoteSp(url: string): Promise<SpriteFrame | null> {
- const key = this.getLoaderKey("RemoteAsset", url, "SpriteFrame");
- if (this.remotes.has(key)) {
- const res = this.remotes.get(key);
- if (res.task) {
- await res.task;
- }
- return res.asset as SpriteFrame;
- }
- const cache: RemoteRes<SpriteFrame> = { url };
- cache.task = this.loadRemoteRes<ImageAsset>(url, "ImageAsset");
- this.remotes.set(key, cache);
- const img = await cache.task;
- if (!img) {
- this.remotes.delete(key);
- return null;
- }
- const sp = SpriteFrame.createWithImage(img as ImageAsset);
- cache.asset = sp;
- delete cache.task;
- sp["_cacheKey"] = key;
- (sp.texture as Texture2D).image
- return sp;
- }
- async loadRemoteRes<T extends Asset>(url: string, type: string): Promise<T | null> {
- const key = this.getLoaderKey("RemoteAsset", url, type);
- if (this.loaders.has(key)) {
- const res = await this.loaders.get(key);
- return res as T;
- }
- const loader = new Promise<T>((resolve, reject) => {
- assetManager.loadRemote<T>(url, (err, res) => {
- if (err) {
- console.error(err, url);
- resolve(null);
- return;
- }
- resolve(res);
- });
- })
- return await this.onLoad<T>(key, loader);
- }
- async releaseRes(res: Asset) {
- res.decRef();
- const cacheKey: string = res["_cacheKey"];
- if (cacheKey && this.remotes.has(cacheKey)) {
- const cache = this.remotes.get(cacheKey);
- const refCount = cache.asset.refCount;
- if (refCount === 0) {
- // if (cache.asset) {
- // if (cache.asset instanceof SpriteFrame) {
- // const texture = cache.asset.texture as Texture2D;
- // const image = texture.image;
- // image.destroy();
- // texture.destroy()
- // }
- // cache.asset.destroy();
- // }
- this.remotes.delete(cacheKey);
- }
- }
- }
- }
|