playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
122 lines (121 loc) • 3.2 kB
JavaScript
import { Asset } from "../../asset/asset.js";
import { GSplatAssetLoaderBase } from "../../../scene/gsplat-unified/gsplat-asset-loader-base.js";
class GSplatAssetLoader extends GSplatAssetLoaderBase {
_urlToAsset = /* @__PURE__ */ new Map();
_registry;
maxConcurrentLoads = 2;
maxRetries = 2;
_currentlyLoading = /* @__PURE__ */ new Set();
_loadQueue = [];
_retryCount = /* @__PURE__ */ new Map();
_destroyed = false;
constructor(registry) {
super();
this._registry = registry;
}
destroy() {
this._destroyed = true;
for (const asset of this._urlToAsset.values()) {
asset.fire("unload", asset);
asset.off("load");
asset.off("error");
this._registry.remove(asset);
asset.unload();
}
this._urlToAsset.clear();
this._loadQueue.length = 0;
this._currentlyLoading.clear();
this._retryCount.clear();
}
_canLoad() {
return !!this._registry.loader?.getHandler("gsplat");
}
load(url) {
const asset = this._urlToAsset.get(url);
if (asset?.loaded || this._currentlyLoading.has(url)) {
return;
}
if (this._loadQueue.includes(url)) {
return;
}
if (this._currentlyLoading.size < this.maxConcurrentLoads) {
this._startLoading(url);
} else {
this._loadQueue.push(url);
}
}
_startLoading(url) {
this._currentlyLoading.add(url);
let asset = this._urlToAsset.get(url);
if (!asset) {
asset = new Asset(url, "gsplat", { url });
this._registry.add(asset);
this._urlToAsset.set(url, asset);
}
asset.once("load", () => this._onAssetLoadSuccess(url, asset));
asset.once("error", (err) => this._onAssetLoadError(url, asset, err));
if (!asset.loaded && !asset.loading) {
this._registry.load(asset);
}
}
_onAssetLoadSuccess(url, asset) {
if (this._destroyed || !this._urlToAsset.has(url)) {
return;
}
this._currentlyLoading.delete(url);
this._retryCount.delete(url);
this._processQueue();
}
_onAssetLoadError(url, asset, err) {
if (this._destroyed || !this._canLoad() || !this._urlToAsset.has(url)) {
return;
}
const retryCount = this._retryCount.get(url) || 0;
if (retryCount < this.maxRetries) {
this._retryCount.set(url, retryCount + 1);
asset.loaded = false;
asset.loading = false;
this._registry.load(asset);
} else {
this._currentlyLoading.delete(url);
this._retryCount.delete(url);
this._processQueue();
}
}
_processQueue() {
if (this._destroyed || !this._canLoad()) {
return;
}
while (this._currentlyLoading.size < this.maxConcurrentLoads && this._loadQueue.length > 0) {
const url = this._loadQueue.shift();
if (url) {
this._startLoading(url);
}
}
}
unload(url) {
this._currentlyLoading.delete(url);
const queueIndex = this._loadQueue.indexOf(url);
if (queueIndex !== -1) {
this._loadQueue.splice(queueIndex, 1);
}
this._retryCount.delete(url);
const asset = this._urlToAsset.get(url);
if (asset) {
asset.fire("unload", asset);
asset.off("load");
asset.off("error");
this._registry.remove(asset);
asset.unload();
this._urlToAsset.delete(url);
}
this._processQueue();
}
getResource(url) {
const asset = this._urlToAsset.get(url);
return asset?.resource;
}
}
export {
GSplatAssetLoader
};