UNPKG

polygonjs-engine

Version:

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

167 lines (166 loc) 6.49 kB
import {TypedSopNode} from "./_Base"; import {CoreObject} from "../../../core/geometry/Object"; import {CoreInstancer} from "../../../core/geometry/Instancer"; import {CoreString} from "../../../core/String"; import {CopyStamp as CopyStamp2} from "./utils/CopyStamp"; import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig"; import {InputCloneMode as InputCloneMode2} from "../../poly/InputCloneMode"; import {Vector3 as Vector32} from "three/src/math/Vector3"; import {Quaternion as Quaternion2} from "three/src/math/Quaternion"; import {ArrayUtils as ArrayUtils2} from "../../../core/ArrayUtils"; class CopySopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); this.count = ParamConfig.INTEGER(1, { range: [1, 20], rangeLocked: [true, false] }); this.transformOnly = ParamConfig.BOOLEAN(0); this.copyAttributes = ParamConfig.BOOLEAN(0); this.attributesToCopy = ParamConfig.STRING("", { visibleIf: {copyAttributes: true} }); this.useCopyExpr = ParamConfig.BOOLEAN(0); } } const ParamsConfig2 = new CopySopParamsConfig(); export class CopySopNode extends TypedSopNode { constructor() { super(...arguments); this.params_config = ParamsConfig2; this._attribute_names_to_copy = []; this._objects = []; } static type() { return "copy"; } static displayedInputNames() { return ["geometry to be copied", "points to copy to"]; } initializeNode() { this.io.inputs.setCount(1, 2); this.io.inputs.initInputsClonedState([InputCloneMode2.ALWAYS, InputCloneMode2.NEVER]); } async cook(input_contents) { const core_group0 = input_contents[0]; if (!this.io.inputs.has_input(1)) { await this.cook_without_template(core_group0); return; } const core_group1 = input_contents[1]; if (!core_group1) { this.states.error.set("second input invalid"); return; } await this.cook_with_template(core_group0, core_group1); } async cook_with_template(instance_core_group, template_core_group) { this._objects = []; const template_points = template_core_group.points(); const instancer = new CoreInstancer(template_core_group); let instance_matrices = instancer.matrices(); const t = new Vector32(); const q = new Quaternion2(); const s = new Vector32(); instance_matrices[0].decompose(t, q, s); this._attribute_names_to_copy = CoreString.attribNames(this.pv.attributesToCopy).filter((attrib_name) => template_core_group.hasAttrib(attrib_name)); await this._copy_moved_objects_on_template_points(instance_core_group, instance_matrices, template_points); this.setObjects(this._objects); } async _copy_moved_objects_on_template_points(instance_core_group, instance_matrices, template_points) { for (let point_index = 0; point_index < template_points.length; point_index++) { await this._copy_moved_object_on_template_point(instance_core_group, instance_matrices, template_points, point_index); } } async _copy_moved_object_on_template_point(instance_core_group, instance_matrices, template_points, point_index) { const matrix = instance_matrices[point_index]; const template_point = template_points[point_index]; this.stamp_node.set_point(template_point); const moved_objects = await this._get_moved_objects_for_template_point(instance_core_group, point_index); for (let moved_object of moved_objects) { if (this.pv.copyAttributes) { this._copyAttributes_from_template(moved_object, template_point); } if (this.pv.transformOnly) { moved_object.applyMatrix4(matrix); } else { const geometry = moved_object.geometry; if (geometry) { moved_object.geometry.applyMatrix4(matrix); } } this._objects.push(moved_object); } } async _get_moved_objects_for_template_point(instance_core_group, point_index) { const stamped_instance_core_group = await this._stamp_instance_group_if_required(instance_core_group); if (stamped_instance_core_group) { const moved_objects = this.pv.transformOnly ? ArrayUtils2.compact([stamped_instance_core_group.objectsWithGeo()[point_index]]) : stamped_instance_core_group.clone().objectsWithGeo(); return moved_objects; } else { return []; } } async _stamp_instance_group_if_required(instance_core_group) { if (this.pv.useCopyExpr) { const container0 = await this.container_controller.requestInputContainer(0); if (container0) { const core_group0 = container0.coreContent(); if (core_group0) { return core_group0; } else { return; } } else { this.states.error.set(`input failed for index ${this.stamp_value()}`); return; } } else { return instance_core_group; } } async _copy_moved_objects_for_each_instance(instance_core_group) { for (let i = 0; i < this.pv.count; i++) { await this._copy_moved_objects_for_instance(instance_core_group, i); } } async _copy_moved_objects_for_instance(instance_core_group, i) { this.stamp_node.set_global_index(i); const stamped_instance_core_group = await this._stamp_instance_group_if_required(instance_core_group); if (stamped_instance_core_group) { stamped_instance_core_group.objects().forEach((object) => { const new_object = CoreObject.clone(object); this._objects.push(new_object); }); } } async cook_without_template(instance_core_group) { this._objects = []; await this._copy_moved_objects_for_each_instance(instance_core_group); this.setObjects(this._objects); } _copyAttributes_from_template(object, template_point) { this._attribute_names_to_copy.forEach((attrib_name, i) => { const attrib_value = template_point.attribValue(attrib_name); const object_wrapper = new CoreObject(object, i); object_wrapper.addAttribute(attrib_name, attrib_value); }); } stamp_value(attrib_name) { return this.stamp_node.value(attrib_name); } get stamp_node() { return this._stamp_node = this._stamp_node || this.create_stamp_node(); } create_stamp_node() { const stamp_node = new CopyStamp2(this.scene()); this.dirtyController.set_forbidden_trigger_nodes([stamp_node]); return stamp_node; } dispose() { super.dispose(); if (this._stamp_node) { this._stamp_node.dispose(); } } }