@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 3.99 kB
JavaScript
class s{constructor(s){this._idToBundle=new Map,this._assetToBundles=new Map,this._urlsToBundles=new Map,this._fileRequests=new Map,this._assets=s,this._assets.bundles=this,this._assets.on("add",this._onAssetAdd,this),this._assets.on("remove",this._onAssetRemove,this)}_onAssetAdd(s){if("bundle"===s.type){this._idToBundle.set(s.id,s),this._assets.on(`load:start:${s.id}`,this._onBundleLoadStart,this),this._assets.on(`load:${s.id}`,this._onBundleLoad,this),this._assets.on(`error:${s.id}`,this._onBundleError,this);const e=s.data.assets;for(let t=0;t<e.length;t++)this._indexAssetInBundle(e[t],s)}else this._assetToBundles.has(s.id)&&this._indexAssetFileUrls(s)}_unbindAssetEvents(s){this._assets.off(`load:start:${s}`,this._onBundleLoadStart,this),this._assets.off(`load:${s}`,this._onBundleLoad,this),this._assets.off(`error:${s}`,this._onBundleError,this)}_indexAssetInBundle(s,e){let t=this._assetToBundles.get(s);t||(t=new Set,this._assetToBundles.set(s,t)),t.add(e);const n=this._assets.get(s);n&&this._indexAssetFileUrls(n)}_indexAssetFileUrls(s){const e=this._getAssetFileUrls(s);if(e)for(let t=0;t<e.length;t++){const n=this._assetToBundles.get(s.id);n&&this._urlsToBundles.set(e[t],n)}}_getAssetFileUrls(s){let e=s.getFileUrl();if(!e)return null;e=e.split("?")[0];const t=[e];if("font"===s.type){const n=s.data.info.maps.length;for(let s=1;s<n;s++)t.push(e.replace(".png",`${s}.png`))}return t}_onAssetRemove(s){if("bundle"===s.type){this._idToBundle.delete(s.id),this._unbindAssetEvents(s.id);const e=s.data.assets;for(let t=0;t<e.length;t++){const n=this._assetToBundles.get(e[t]);if(n&&(n.delete(s),0===n.size)){this._assetToBundles.delete(e[t]);for(const[s,e]of this._urlsToBundles)e===n&&this._urlsToBundles.delete(s)}}this._onBundleError(`Bundle ${s.id} was removed`)}else{if(!this._assetToBundles.get(s.id))return;this._assetToBundles.delete(s.id);const e=this._getAssetFileUrls(s);if(!e)return;for(let s=0;s<e.length;s++)this._urlsToBundles.delete(e[s])}}_onBundleLoadStart(s){s.resource.on("add",((s,e)=>{const t=this._fileRequests.get(s);if(t){for(let s=0;s<t.length;s++)t[s](null,e);this._fileRequests.delete(s)}}))}_onBundleLoad(s){if(s.resource){if(this._fileRequests)for(const[e,t]of this._fileRequests){const n=this._urlsToBundles.get(e);if(!n||!n.has(s))continue;const i=decodeURIComponent(e);let o,l;if(s.resource.has(i))l=s.resource.get(i);else{if(!s.resource.loaded)continue;o=`Bundle ${s.id} does not contain URL ${e}`}for(let s=0;s<t.length;s++)t[s](o,o||l);this._fileRequests.delete(e)}}else this._onBundleError(`Bundle ${s.id} failed to load`)}_onBundleError(s){for(const[e,t]of this._fileRequests){if(!this._findLoadedOrLoadingBundleForUrl(e)){for(let e=0;e<t.length;e++)t[e](s);this._fileRequests.delete(e)}}}_findLoadedOrLoadingBundleForUrl(s){const e=this._urlsToBundles.get(s);if(!e)return null;let t=null;for(const s of e){if(s.loaded&&s.resource)return s;s.loading&&(t=s)}return t}listBundlesForAsset(s){const e=this._assetToBundles.get(s.id);return e?Array.from(e):null}list(){return Array.from(this._idToBundle.values())}hasUrl(s){return this._urlsToBundles.has(s)}urlIsLoadedOrLoading(s){return!!this._findLoadedOrLoadingBundleForUrl(s)}loadUrl(s,e){const t=this._findLoadedOrLoadingBundleForUrl(s);if(!t)return void e(`URL ${s} not found in any bundles`);if(t.loaded){const n=decodeURIComponent(s);if(t.resource.has(n))return void e(null,t.resource.get(n));if(t.resource.loaded)return void e(`Bundle ${t.id} does not contain URL ${s}`)}let n=this._fileRequests.get(s);n||(n=[],this._fileRequests.set(s,n)),n.push(e)}destroy(){this._assets.off("add",this._onAssetAdd,this),this._assets.off("remove",this._onAssetRemove,this);for(const s of this._idToBundle.keys())this._unbindAssetEvents(s);this._assets=null,this._idToBundle.clear(),this._idToBundle=null,this._assetToBundles.clear(),this._assetToBundles=null,this._urlsToBundles.clear(),this._urlsToBundles=null,this._fileRequests.clear(),this._fileRequests=null}}export{s as BundleRegistry};