@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
145 lines (144 loc) • 4.8 kB
JavaScript
;
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);
}
}