import { Asset, assetManager, ImageAsset, SpriteFrame, Texture2D, _decorator } from 'cc'; import { DEV } from 'cc/env'; import { AutoBind } from '../common/AutoBind'; import { StringUtil } from '../util/StringUtil'; import { LoadQueue } from './LoadQueue'; import { resLoader } from './ResLoader'; const { ccclass, menu, property } = _decorator; @ccclass('ResKeeper') @menu('私有组件/ResKeeper') export class ResKeeper extends AutoBind { @property({ displayName: "启用分帧加载", tooltip: DEV && "该组件加载资源是否使用分帧加载" }) private frame_load = false; @property({ displayName: "加载优先级", slide: true, max: 10, min: 0, step: 1, visible() { return this.frame_load == true; }, tooltip: DEV && "分帧加载优先级,优先级越大越先加载" }) private load_priority = 0; // private _net_cache = new Map(); private _res_cache = new Map(); private _uuid_sign = StringUtil.getUUID(12); private _uuid_idx = 0; protected onDestroy() { this.release(); } /** * 在当前资源缓存中清理一个缓存(主要用于一个组件加载多个资源但只使用其中一个,这个时候就可以调用释放前面的特定资源) * @param uuid 缓存ID */ // protected releaseCache(uuid: string) { // if (uuid && uuid != "" && this._res_cache.has(uuid)) { // let res = this._res_cache.get(uuid); // res?.decRef(); // res = null; // this._res_cache.delete(uuid); // uuid = ""; // } // } /** * 在该节点上添加一个资源,该资源将随父节点销毁自动销毁,如果父节点被销毁,则销毁资源 * @param bundle 包名 * @param url 路径 * @param type 类型 * @param completed 加载成功后回调 */ protected load(bundle: string, url: string, type: typeof Asset, completed: (res: Asset, uuid?: string) => void) { let callback = (error: Error, res: Asset) => { if (error) { console.error(error); } else { if (this.isValid) { let uuid = this._addResCache(res); completed && completed(res, uuid); } else { // resLoader.release(url, bundle); } } }; if (this.frame_load) { LoadQueue.pushLoad(this.load_priority, bundle, url, type, callback, this); } else { resLoader.load(bundle, url, type, callback); } } /** * 在该节点上添加一个网络图片,该资源将随父节点销毁自动销毁,如果父节点被销毁,则销毁资源 * @param url 路径 * @param completed 加载成功后回调 */ // protected loadAvatar(url: string, completed: (res: SpriteFrame) => void) { // let callback = (error: Error, image: ImageAsset) => { // if (error) { // console.error(error); // } else { // if (this.isValid) { // this._addResCache(image); // let frame = this._net_cache.get(url); // if (frame) { // frame.addRef(); // completed && completed(frame); // } else { // let texture = new Texture2D(); // texture.image = image; // let frame = new SpriteFrame(); // frame.texture = texture; // this._net_cache.set(url, frame); // frame.addRef(); // completed && completed(frame); // } // } // } // }; // if (url.indexOf(".png") == -1) { // assetManager.loadRemote(url, { ext: '.png' }, callback); // } else { // assetManager.loadRemote(url, callback); // } // } private _addResCache(res: Asset) { ++this._uuid_idx; let uuid = this.node.uuid + "_<" + this._uuid_sign + ">_[" + this._uuid_idx + "]"; res.addRef(); this._res_cache.set(uuid, res); return uuid; } release() { // this._net_cache.forEach((frame, url) => { // if (frame.isValid) { // const tmp_frame = frame; // frame.decRef(false); // frame = null; // if (tmp_frame.refCount <= 0) { // let texture = tmp_frame.texture as Texture2D; // if (tmp_frame.packable) { // texture = tmp_frame.original?._texture as Texture2D; // } // if (texture) { // texture.image?.decRef(); // texture.image = null; // texture.destroy(); // } // tmp_frame.destroy(); // } // } // }); // this._net_cache.clear(); this._res_cache.forEach((res) => { res?.decRef(); res = null; }); this._res_cache.clear(); } }