UNPKG

polygonjs-engine

Version:

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

161 lines (160 loc) 5.23 kB
import {TypedObjNode} from "./_Base"; import {FlagsControllerD} from "../utils/FlagsController"; import {AxesHelper as AxesHelper2} from "three/src/helpers/AxesHelper"; import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig"; import {GeoObjNode} from "./Geo"; import {HierarchyController as HierarchyController2} from "./utils/HierarchyController"; import {NodeContext as NodeContext2} from "../../poly/NodeContext"; import {Mesh as Mesh2} from "three/src/objects/Mesh"; import {Vector3 as Vector32} from "three/src/math/Vector3"; import {TypeAssert} from "../../poly/Assert"; var RivetUpdateMode; (function(RivetUpdateMode2) { RivetUpdateMode2["ON_RENDER"] = "On Every Render"; RivetUpdateMode2["MANUAL"] = "Manual"; })(RivetUpdateMode || (RivetUpdateMode = {})); const UPDATE_MODES = [RivetUpdateMode.ON_RENDER, RivetUpdateMode.MANUAL]; class RivetObjParamConfig extends NodeParamsConfig { constructor() { super(...arguments); this.object = ParamConfig.OPERATOR_PATH("", { nodeSelection: { context: NodeContext2.OBJ }, dependentOnFoundNode: false, computeOnDirty: true, callback: (node) => { RivetObjNode.PARAM_CALLBACK_update_resolved_object(node); } }); this.pointIndex = ParamConfig.INTEGER(0, { range: [0, 100] }); this.updateMode = ParamConfig.INTEGER(UPDATE_MODES.indexOf(RivetUpdateMode.ON_RENDER), { callback: (node) => { RivetObjNode.PARAM_CALLBACK_update_updateMode(node); }, menu: { entries: UPDATE_MODES.map((name, value) => { return {name, value}; }) } }); this.update = ParamConfig.BUTTON(null, { callback: (node) => { RivetObjNode.PARAM_CALLBACK_update(node); }, visibleIf: {updateMode: UPDATE_MODES.indexOf(RivetUpdateMode.MANUAL)} }); } } const ParamsConfig2 = new RivetObjParamConfig(); export class RivetObjNode extends TypedObjNode { constructor() { super(...arguments); this.params_config = ParamsConfig2; this.hierarchy_controller = new HierarchyController2(this); this.flags = new FlagsControllerD(this); this._helper = new AxesHelper2(1); this._found_point_post = new Vector32(); this._on_object_before_render_bound = this._update.bind(this); } static type() { return "rivet"; } create_object() { const mesh = new Mesh2(); mesh.matrixAutoUpdate = false; return mesh; } initializeNode() { this.hierarchy_controller.initializeNode(); this.addPostDirtyHook("rivet_on_dirty", () => { this.cookController.cook_main_without_inputs(); }); this._updateHelperHierarchy(); this.flags.display.add_hook(() => { this._updateHelperHierarchy(); }); } _updateHelperHierarchy() { if (this.flags.display.active()) { this.object.add(this._helper); } else { this.object.remove(this._helper); } } async cook() { await this._update_resolved_object(); this._update_render_hook(); this.cookController.end_cook(); } _update_render_hook() { const mode = UPDATE_MODES[this.pv.updateMode]; switch (mode) { case RivetUpdateMode.ON_RENDER: { return this._add_render_hook(); } case RivetUpdateMode.MANUAL: { return this._remove_render_hook(); } } TypeAssert.unreachable(mode); } _add_render_hook() { this.object.onBeforeRender = this._on_object_before_render_bound; this.object.frustumCulled = false; } _remove_render_hook() { this.object.onBeforeRender = () => { }; } _update(renderer, scene, camera, geometry, material, group) { const resolved_object = this._resolved_object(); if (resolved_object) { const geometry2 = resolved_object.geometry; if (geometry2) { const position_attrib = geometry2.attributes["position"]; if (position_attrib) { const position_array = position_attrib.array; this._found_point_post.fromArray(position_array, this.pv.pointIndex * 3); resolved_object.updateWorldMatrix(true, false); resolved_object.localToWorld(this._found_point_post); this.object.matrix.makeTranslation(this._found_point_post.x, this._found_point_post.y, this._found_point_post.z); } } } } static PARAM_CALLBACK_update_resolved_object(node) { node._update_resolved_object(); } async _update_resolved_object() { if (this.p.object.isDirty()) { await this.p.object.compute(); } const node = this.p.object.found_node(); if (node) { if (node.nodeContext() == NodeContext2.OBJ && node.type() == GeoObjNode.type()) { const geo_node = node; this._resolved_sop_group = geo_node.children_display_controller.sop_group; } else { this.states.error.set("found node is not a geo node"); } } } _resolved_object() { if (!this._resolved_sop_group) { return; } const object = this._resolved_sop_group.children[0]; if (object) { return object; } } static PARAM_CALLBACK_update_updateMode(node) { node._update_render_hook(); } static PARAM_CALLBACK_update(node) { node._update(); } }