UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

144 lines (143 loc) 3.68 kB
import { EventHandler } from "../../core/event-handler.js"; import { Asset } from "./asset.js"; class AssetListLoader extends EventHandler { _assets = /* @__PURE__ */ new Set(); _loadingAssets = /* @__PURE__ */ new Set(); _waitingAssets = /* @__PURE__ */ new Set(); _loading = false; _loaded = false; _failed = []; constructor(assetList, assetRegistry) { super(); this._registry = assetRegistry; assetList.forEach((a) => { if (a instanceof Asset) { if (!a.registry) { a.registry = assetRegistry; } this._assets.add(a); } else { const asset = assetRegistry.get(a); if (asset) { this._assets.add(asset); } else { this._waitForAsset(a); } } }); } destroy() { this._registry.off("load", this._onLoad); this._registry.off("error", this._onError); this._waitingAssets.forEach((id) => { this._registry.off(`add:${id}`, this._onAddAsset); }); this.off("progress"); this.off("load"); } _assetHasDependencies(asset) { return asset.type === "model" && asset.file?.url && asset.file.url && asset.file.url.match(/.json$/g); } load(done, scope) { if (this._loading) { return; } this._loading = true; this._callback = done; this._scope = scope; this._registry.on("load", this._onLoad, this); this._registry.on("error", this._onError, this); let loadingAssets = false; this._assets.forEach((asset) => { if (!asset.loaded) { loadingAssets = true; if (this._assetHasDependencies(asset)) { this._registry.loadFromUrl(asset.file.url, asset.type, (err, loadedAsset) => { if (err) { this._onError(err, asset); return; } this._onLoad(asset); }); } this._loadingAssets.add(asset); this._registry.add(asset); } }); this._loadingAssets.forEach((asset) => { if (!this._assetHasDependencies(asset)) { this._registry.load(asset); } }); if (!loadingAssets && this._waitingAssets.size === 0) { this._loadingComplete(); } } ready(done, scope = this) { if (this._loaded) { done.call(scope, Array.from(this._assets)); } else { this.once("load", (assets) => { done.call(scope, assets); }); } } // called when all assets are loaded _loadingComplete() { if (this._loaded) return; this._loaded = true; this._registry.off("load", this._onLoad, this); this._registry.off("error", this._onError, this); if (this._failed.length) { if (this._callback) { this._callback.call(this._scope, "Failed to load some assets", this._failed); } this.fire("error", this._failed); } else { if (this._callback) { this._callback.call(this._scope); } this.fire("load", Array.from(this._assets)); } } // called when an (any) asset is loaded _onLoad(asset) { if (this._loadingAssets.has(asset)) { this.fire("progress", asset); this._loadingAssets.delete(asset); } if (this._loadingAssets.size === 0) { setTimeout(() => { this._loadingComplete(); }, 0); } } // called when an asset fails to load _onError(err, asset) { if (this._loadingAssets.has(asset)) { this._failed.push(asset); this._loadingAssets.delete(asset); } if (this._loadingAssets.size === 0) { setTimeout(() => { this._loadingComplete(); }, 0); } } // called when a expected asset is added to the asset registry _onAddAsset(asset) { this._waitingAssets.delete(asset); this._assets.add(asset); if (!asset.loaded) { this._loadingAssets.add(asset); this._registry.load(asset); } } _waitForAsset(assetId) { this._waitingAssets.add(assetId); this._registry.once(`add:${assetId}`, this._onAddAsset, this); } } export { AssetListLoader };