UNPKG

polygonjs-engine

Version:

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

127 lines (126 loc) 4.57 kB
import {BaseSopOperation} from "./_Base"; import {TypedNodePathParamValue} from "../../Walker"; import {NodeContext as NodeContext2} from "../../../engine/poly/NodeContext"; import {CoreMaterial} from "../../geometry/Material"; import {GlobalsGeometryHandler} from "../../../engine/nodes/gl/code/globals/Geometry"; import {InputCloneMode as InputCloneMode2} from "../../../engine/poly/InputCloneMode"; import {ShaderMaterial as ShaderMaterial2} from "three/src/materials/ShaderMaterial"; import {CoreObject} from "../../geometry/Object"; export class MaterialSopOperation extends BaseSopOperation { constructor() { super(...arguments); this._globals_handler = new GlobalsGeometryHandler(); this._old_mat_by_old_new_id = new Map(); this._materials_by_uuid = new Map(); } static type() { return "material"; } async cook(input_contents, params) { const core_group = input_contents[0]; this._old_mat_by_old_new_id.clear(); await this._apply_materials(core_group, params); this._swap_textures(core_group, params); return core_group; } async _apply_materials(core_group, params) { if (!params.assignMat) { return; } const material_node = params.material.ensure_node_context(NodeContext2.MAT, this.states?.error); if (material_node) { const material = material_node.material; const assembler_controller = material_node.assemblerController; if (assembler_controller) { assembler_controller.set_assembler_globals_handler(this._globals_handler); } await material_node.requestContainer(); if (material) { if (params.applyToChildren) { for (let object of core_group.objects()) { object.traverse((grand_child) => { this._apply_material(grand_child, material, params); }); } } else { for (let object of core_group.objectsFromGroup(params.group)) { this._apply_material(object, material, params); } } return core_group; } else { this.states?.error.set(`material invalid. (error: '${material_node.states.error.message()}')`); } } else { this.states?.error.set(`no material node found`); } } _swap_textures(core_group, params) { if (!params.swapCurrentTex) { return; } this._materials_by_uuid.clear(); for (let object of core_group.objectsFromGroup(params.group)) { if (params.applyToChildren) { object.traverse((child) => { const mat = object.material; this._materials_by_uuid.set(mat.uuid, mat); }); } else { const mat = object.material; this._materials_by_uuid.set(mat.uuid, mat); } } this._materials_by_uuid.forEach((mat, mat_uuid) => { this._swap_texture(mat, params); }); } _apply_material(object, src_material, params) { if (params.group) { if (!CoreObject.isInGroup(params.group, object)) { return; } } const used_material = params.cloneMat ? CoreMaterial.clone(src_material) : src_material; if (src_material instanceof ShaderMaterial2 && used_material instanceof ShaderMaterial2) { for (let uniform_name in src_material.uniforms) { used_material.uniforms[uniform_name] = src_material.uniforms[uniform_name]; } } const object_with_material = object; this._old_mat_by_old_new_id.set(used_material.uuid, object_with_material.material); object_with_material.material = used_material; CoreMaterial.apply_render_hook(object, used_material); CoreMaterial.apply_custom_materials(object, used_material); } _swap_texture(target_mat, params) { if (params.texSrc0 == "" || params.texDest0 == "") { return; } let src_mat = this._old_mat_by_old_new_id.get(target_mat.uuid); src_mat = src_mat || target_mat; const src_tex = src_mat[params.texSrc0]; if (src_tex) { target_mat[params.texDest0] = src_tex; const uniforms = target_mat.uniforms; if (uniforms) { const uniforms_map = uniforms[params.texDest0]; if (uniforms_map) { uniforms[params.texDest0] = {value: src_tex}; } } } } } MaterialSopOperation.DEFAULT_PARAMS = { group: "", assignMat: true, material: new TypedNodePathParamValue("/MAT/mesh_standard1"), applyToChildren: true, cloneMat: false, shareUniforms: true, swapCurrentTex: false, texSrc0: "emissiveMap", texDest0: "map" }; MaterialSopOperation.INPUT_CLONED_STATE = InputCloneMode2.FROM_NODE;