UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

145 lines (144 loc) 4.8 kB
"use strict"; import { ParamEvent } from "./../../../../poly/ParamEvent"; import { TypedSopNode } from "./../../_Base"; import { NodeParamsConfig, ParamConfig } from "../../../utils/params/ParamsConfig"; import { InputCloneMode } from "../../../../poly/InputCloneMode"; import { Group } from "three"; import { CoreInstancer } from "../../../../../core/geometry/Instancer"; import { Matrix4 } from "three"; import { Poly } from "../../../../Poly"; const _points = []; class BaseFileMultiParamsConfigResult extends NodeParamsConfig { constructor() { super(...arguments); this.url = ParamConfig.STRING(""); this.matrixAutoUpdate = ParamConfig.BOOLEAN(0); this.reload = ParamConfig.BUTTON(null); } } export class BaseFileMultiSopNodeFactoryResult extends TypedSopNode { } export class BaseFileMultiParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param url to load the geometry from */ this.url = ParamConfig.STRING("", { fileBrowse: { extensions: [] }, expression: { forEntities: true } }); /** @param sets the matrixAutoUpdate attribute for the objects loaded */ this.matrixAutoUpdate = ParamConfig.BOOLEAN(false); /** @param reload the geometry */ this.reload = ParamConfig.BUTTON(null, { callback: (node) => { BaseFileMultiSopNode.PARAM_CALLBACK_reload( node ); } }); } } export class BaseFileMultiSopNode extends TypedSopNode { constructor() { super(...arguments); this._instancer = new CoreInstancer(); this._instanceMatrix = new Matrix4(); } dispose() { super.dispose(); Poly.blobs.clearBlobsForNode(this); } initializeNode() { this.io.inputs.setCount(1); this.io.inputs.initInputsClonedState(InputCloneMode.NEVER); } async cook(inputCoreGroups) { const inputCoreGroup = inputCoreGroups[0]; inputCoreGroup.points(_points); const urls = []; const urlByIndex = /* @__PURE__ */ new Map(); const loadedResultByUrl = /* @__PURE__ */ new Map(); const urlUsageCount = /* @__PURE__ */ new Map(); const param = this.p.url; if (param.hasExpression() && param.expressionController) { const uniqueUrls = /* @__PURE__ */ new Set(); const _applyUrlToPoint = (point, url) => { const index = point.index(); if (urlByIndex.has(index)) { this.states.error.set(`input points have duplicate indices. Make sure to merge inputs together.`); } else { urlByIndex.set(index, url); uniqueUrls.add(url); BaseFileMultiSopNode._incrementUrlUsageCount(url, urlUsageCount); } }; if (param.expressionController.entitiesDependent()) { await param.expressionController.computeExpressionForPoints(_points, _applyUrlToPoint); } else { for (const point of _points) { _applyUrlToPoint(point, param.value); } } uniqueUrls.forEach((url) => { urls.push(url); }); } else { const url = this.pv.url; urls.push(url); BaseFileMultiSopNode._incrementUrlUsageCount(url, urlUsageCount); } const loadedObjects = []; const promises = urls.map((url) => this._loadFromUrlPromises(url, loadedResultByUrl)); await Promise.all(promises); this._instancer.setCoreGroup(inputCoreGroup); for (const point of _points) { const index = point.index(); const url = urlByIndex.get(index) || this.pv.url; this._instancer.matrixFromPoint(point, this._instanceMatrix); const usageCount = urlUsageCount.get(url) || 1; let parent = loadedResultByUrl.get(url); if (parent) { if (usageCount > 1) { parent = parent.clone(); } parent.applyMatrix4(this._instanceMatrix); loadedObjects.push(parent); } } this.setObjects(loadedObjects); } static _incrementUrlUsageCount(url, map) { const currentUsage = map.get(url); if (currentUsage != null) { map.set(url, currentUsage + 1); } else { map.set(url, 1); } } async _loadFromUrlPromises(url, loadedResultByUrl) { const objects = await this._loadObject(url); if (objects) { const parent = new Group(); parent.matrixAutoUpdate = false; parent.name = url; for (const object of objects) { parent.add(object); } loadedResultByUrl.set(url, parent); } } _loadObject(url) { const loader = this._createLoader(url); return this._loadWithLoader(loader); } _loadWithLoader(loader) { return loader.load({ node: this }); } static PARAM_CALLBACK_reload(node) { node._paramCallbackReload(); } _paramCallbackReload() { this.p.url.setDirty(); this.p.url.emit(ParamEvent.ASSET_RELOAD_REQUEST); } }