UNPKG

wwobjloader2

Version:

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/kaisalmen/WWOBJLoader/blob/dev/LICENSE) [![WWOBJLoader](https://github.com/kaisalmen/WWOBJLoader/actions/workflows/actions.yml/badge.svg)](https://github.com/kaisalm

197 lines 6.44 kB
import { FileLoader } from 'three'; import { applyProperties } from 'wtd-core'; class AssetPipelineLoader { name; assetPipeline; baseObject3d; onComplete = null; constructor(name, assetPipeline) { this.name = name; this.assetPipeline = assetPipeline; } getName() { return this.name; } setBaseObject3d(baseObject3d) { this.baseObject3d = baseObject3d; return this; } setOnComplete(onComplete) { this.onComplete = onComplete; } run() { this.assetPipeline.initPipeline(this.name, this.onComplete); if (this.baseObject3d) { this.assetPipeline.runPipeline(this.baseObject3d); } else { throw new Error('baseObject3d was not properly specified.'); } return this; } } /** * The AssetPipeline defines a set of {@link AssetTask} that need to be executed one after the other and return a {@link Object3D}. * @constructor */ class AssetPipeline { name = null; onComplete = null; assetTasks = new Map(); addAssetTask(assetTask) { this.assetTasks.set(assetTask.getName(), assetTask); return this; } /** * Init all {@link AssetTask} * * @param {string} name Name of the pipeline * @param {CallbackCompleteType} onComplete set callback function * @return {AssetPipeline} */ initPipeline(name, onComplete) { this.name = name; this.onComplete = onComplete; let assetTaskBefore = null; for (const assetTask of this.assetTasks.values()) { if (assetTaskBefore !== null) { assetTask.setTaskBefore(assetTaskBefore); assetTaskBefore.setTaskAfter(assetTask); } assetTaskBefore = assetTask; assetTask.init(); } return this; } /** * Run the pipeline: First load resources and then execute the parsing functions * @param {Object3D} baseObject3d * @return {AssetPipeline} */ async runPipeline(baseObject3d) { const onComplete = this.onComplete ? this.onComplete : (x) => { console.log('Done loading: ' + x); }; const loadResources = async (assetTasks) => { const loadPromises = []; for (const assetTask of assetTasks.values()) { if (assetTask.getResourceDescriptor()) { const promise = assetTask.loadResource(); loadPromises.push(promise); } } console.log('Waiting for completion of loading of all assets!'); return await Promise.all(loadPromises); }; const processAssets = (loadResults) => { console.log('Count of loaded resources: ' + loadResults.length); let assetTask; for (assetTask of this.assetTasks.values()) { // TODO: process must be async, so we can process worker based workloads assetTask.process(); } // last assetTask if (assetTask && assetTask.getProcessResult()) { baseObject3d.add(assetTask.getProcessResult()); } return baseObject3d; }; try { const resourceDescriptor = await loadResources(this.assetTasks); const object3d = processAssets(resourceDescriptor); onComplete(this.name, object3d); } catch (e) { console.error(e); } } } class AssetTask { name; resourceDescriptor; assetLoader = { loader: { instance: undefined, config: {} }, linker: undefined }; relations = { before: undefined, after: undefined, }; processResult = undefined; constructor(name) { this.name = name; } getName() { return this.name; } setResourceDescriptor(resourceDescriptor) { this.resourceDescriptor = resourceDescriptor; return this; } getResourceDescriptor() { return this.resourceDescriptor; } setTaskBefore(assetTask) { this.relations.before = assetTask; } setTaskAfter(assetTask) { this.relations.after = assetTask; } getProcessResult() { return this.processResult; } setLinker(linker) { this.assetLoader.linker = linker; } setLoader(loader, loaderConfig) { const parser = loader; if (typeof parser.parse === 'function') { this.assetLoader.loader.instance = parser; } else { throw new Error('Provide loader has now parse method! Aborting...'); } this.assetLoader.loader.config = loaderConfig ?? {}; return this; } init() { console.log(this.name + ': Performing init'); applyProperties(this.assetLoader.loader.instance, this.assetLoader.loader.config, false); } async loadResource() { const fileLoader = new FileLoader(); fileLoader.setResponseType('arraybuffer'); if (this.resourceDescriptor) { const buffer = await fileLoader.loadAsync(this.resourceDescriptor.getUrl().href); this.resourceDescriptor.setBuffer(buffer); return Promise.resolve(this.resourceDescriptor); } else { return Promise.reject(); } } process() { if (this.assetLoader.linker) { const resultBefore = this.relations.before?.processResult; const nextTask = this.relations.after?.assetLoader.loader.instance; if (resultBefore) { this.processResult = this.assetLoader.linker.link(resultBefore, nextTask); } } else if (this.assetLoader.loader.instance) { if (this.resourceDescriptor?.isNeedStringOutput()) { const dataAsString = this.resourceDescriptor.getBufferAsString(); this.processResult = this.assetLoader.loader.instance.parse(dataAsString); } else { const dataAsBuffer = this.resourceDescriptor?.getBuffer(); this.processResult = this.assetLoader.loader.instance.parse(dataAsBuffer); } } } } export { AssetPipelineLoader, AssetPipeline, AssetTask }; //# sourceMappingURL=AssetPipelineLoader.js.map