UNPKG

@polygonjs/polygonjs

Version:

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

201 lines (200 loc) 7.17 kB
"use strict"; import { Color, Vector2, Vector3, Vector4 } from "three"; import { UpdateMatNode } from "./_Base"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { OnBeforeCompileDataHandler, cloneOnBeforeCompileData, assignOnBeforeCompileDataAndFunction } from "../gl/code/assemblers/materials/OnBeforeCompile"; import { GL_CONNECTION_POINT_TYPES_FOR_CONSTANT, GlConnectionPointType } from "../utils/io/connections/Gl"; import { isNumber } from "../../../core/Type"; import { NodeContext } from "../../poly/NodeContext"; import { isBoolean } from "../../../core/Type"; export var AdditionalType = /* @__PURE__ */ ((AdditionalType2) => { AdditionalType2["COLOR"] = "color"; AdditionalType2["TEXTURE"] = "texture"; return AdditionalType2; })(AdditionalType || {}); const AVAILABLE_TYPES = [...GL_CONNECTION_POINT_TYPES_FOR_CONSTANT, "color" /* COLOR */, "texture" /* TEXTURE */]; function typedVisibleOptions(type, otherParamVal = {}) { const val = AVAILABLE_TYPES.indexOf(type); return { visibleIf: { type: val, ...otherParamVal }, cook: false, callback: (node) => { BuilderUniformUpdateMatNode.PARAM_CALLBACK_applyCurrentParam(node); } }; } class BuilderUniformUpdateMatParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param name of the uniform */ this.uniformName = ParamConfig.STRING(""); /** @param type of the uniform */ this.type = ParamConfig.INTEGER(AVAILABLE_TYPES.indexOf(GlConnectionPointType.FLOAT), { menu: { entries: AVAILABLE_TYPES.map((name, value) => ({ name, value })) } }); this.bool = ParamConfig.BOOLEAN(0, typedVisibleOptions(GlConnectionPointType.BOOL)); this.int = ParamConfig.INTEGER(0, typedVisibleOptions(GlConnectionPointType.INT)); this.float = ParamConfig.FLOAT(0, typedVisibleOptions(GlConnectionPointType.FLOAT)); this.vec2 = ParamConfig.VECTOR2([0, 0], typedVisibleOptions(GlConnectionPointType.VEC2)); this.vec3 = ParamConfig.VECTOR3([0, 0, 0], typedVisibleOptions(GlConnectionPointType.VEC3)); this.color = ParamConfig.COLOR([0, 0, 0], typedVisibleOptions("color" /* COLOR */)); this.vec4 = ParamConfig.VECTOR4([0, 0, 0, 0], typedVisibleOptions(GlConnectionPointType.VEC4)); this.texture = ParamConfig.NODE_PATH("", { ...typedVisibleOptions("texture" /* TEXTURE */), nodeSelection: { context: NodeContext.COP } }); } } const ParamsConfig = new BuilderUniformUpdateMatParamsConfig(); export class BuilderUniformUpdateMatNode extends UpdateMatNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; } static type() { return "builderUniformUpdate"; } async cook(inputMaterials) { const inputMaterial = inputMaterials[0]; inputMaterial.needsUpdate = true; const uniformName = this.pv.uniformName; if (uniformName.trim() == "") { this.states.error.set(`uniform name is empty`); this.setMaterial(inputMaterial); return; } const inputMaterialData = OnBeforeCompileDataHandler.getData(inputMaterial); if (!inputMaterialData) { this.states.error.set(`input material does not come from a builder material`); this.setMaterial(inputMaterial); return; } const clonedData = cloneOnBeforeCompileData(inputMaterialData, { clonedParamConfigName: this.pv.uniformName }); const { paramConfigs } = clonedData; this._paramConfig = paramConfigs.find((p) => p.name() == this.pv.uniformName); if (!this._paramConfig) { this.states.error.set(`uniform '${this.pv.uniformName}' not found`); this.setMaterial(inputMaterial); return; } await this._applyCurrentParam(); assignOnBeforeCompileDataAndFunction(this.scene(), inputMaterial, clonedData); if (inputMaterial.customMaterials) { const customMaterialNames = Object.keys(inputMaterial.customMaterials); for (const customMaterialName of customMaterialNames) { const customMaterial = inputMaterial.customMaterials[customMaterialName]; if (customMaterial) { this._handleCustomMaterial(customMaterial); } } } this.setMaterial(inputMaterial); } _handleCustomMaterial(customMaterial) { const inputMaterialData = OnBeforeCompileDataHandler.getData(customMaterial); if (!inputMaterialData) { return; } const clonedData = cloneOnBeforeCompileData(inputMaterialData, { clonedParamConfigName: this.pv.uniformName, clonedParamConfig: this._paramConfig }); assignOnBeforeCompileDataAndFunction(this.scene(), customMaterial, clonedData); } setType(type) { this.p.type.set(AVAILABLE_TYPES.indexOf(type)); } static PARAM_CALLBACK_applyCurrentParam(node) { node._applyCurrentParam(); } async _applyCurrentParam() { if (!this._paramConfig) { return; } const type = AVAILABLE_TYPES[this.pv.type]; const uniform = this._paramConfig.uniform(); switch (type) { case GlConnectionPointType.BOOL: { if (isBoolean(uniform.value)) { uniform.value = this.pv.bool; } else { this.states.error.set("uniform is not a boolean"); } return; } case GlConnectionPointType.INT: { if (isNumber(uniform.value)) { uniform.value = this.pv.int; } else { this.states.error.set("uniform is not an int"); } return; } case GlConnectionPointType.FLOAT: { if (isNumber(uniform.value)) { uniform.value = this.pv.float; } else { this.states.error.set("uniform is not a float"); } return; } case GlConnectionPointType.VEC2: { if (uniform.value instanceof Vector2) { uniform.value = this.pv.vec2; } else { this.states.error.set("uniform is not a vec2"); } return; } case GlConnectionPointType.VEC3: { if (uniform.value instanceof Vector3) { uniform.value = this.pv.vec3; } else { this.states.error.set("uniform is not a vec3"); } return; } case GlConnectionPointType.VEC4: { if (uniform.value instanceof Vector4) { uniform.value = this.pv.vec4; } else { this.states.error.set("uniform is not a vec4"); } return; } case "color" /* COLOR */: { if (uniform.value instanceof Color) { uniform.value = this.pv.color; } else { this.states.error.set("uniform is not a color"); } return; } case "texture" /* TEXTURE */: { await this._updateTexture(); return; } } } async _updateTexture() { if (!this._paramConfig) { return; } const textureNode = this.p.texture.value.nodeWithContext(NodeContext.COP); if (textureNode) { const container = await textureNode.compute(); const texture = container.texture(); this._paramConfig.uniform().value = texture; } else { this._paramConfig.uniform().value = null; } } }