UNPKG

@polygonjs/polygonjs

Version:

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

236 lines (235 loc) 7.3 kB
"use strict"; import { TypedObjNode } from "./_Base"; import { FlagsControllerD } from "../utils/FlagsController"; import { AxesHelper } from "three"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { GeoObjNode } from "./Geo"; import { HierarchyController } from "./utils/HierarchyController"; import { NodeContext } from "../../poly/NodeContext"; import { Mesh } from "three"; import { Vector3 } from "three"; import { TypeAssert } from "../../poly/Assert"; var RivetUpdateMode = /* @__PURE__ */ ((RivetUpdateMode2) => { RivetUpdateMode2["ON_RENDER"] = "On Every Render"; RivetUpdateMode2["MANUAL"] = "Manual"; return RivetUpdateMode2; })(RivetUpdateMode || {}); const UPDATE_MODES = ["On Every Render" /* ON_RENDER */, "Manual" /* MANUAL */]; class RivetObjParamConfig extends NodeParamsConfig { constructor() { super(...arguments); this.object = ParamConfig.NODE_PATH("", { nodeSelection: { context: NodeContext.OBJ, types: [GeoObjNode.type()] }, dependentOnFoundNode: false, computeOnDirty: true, callback: (node) => { RivetObjNode.PARAM_CALLBACK_update_resolved_object(node); } }); this.pointIndex = ParamConfig.INTEGER(0, { range: [0, 100] // callback: (node: BaseNodeType) => { // RivetObjNode.PARAM_CALLBACK_update_object_position(node as RivetObjNode); // }, }); // active = ParamConfig.BOOLEAN(true, { // callback: (node: BaseNodeType) => { // RivetObjNode.PARAM_CALLBACK_update_active_state(node as RivetObjNode); // }, // }); this.updateMode = ParamConfig.INTEGER(UPDATE_MODES.indexOf("On Every Render" /* ON_RENDER */), { callback: (node) => { RivetObjNode.PARAM_CALLBACK_update_updateMode(node); }, menu: { entries: UPDATE_MODES.map((name, value) => { return { name, value }; }) } // visibleIf: {active: true}, }); this.update = ParamConfig.BUTTON(null, { callback: (node) => { RivetObjNode.PARAM_CALLBACK_update(node); }, visibleIf: { updateMode: UPDATE_MODES.indexOf("Manual" /* MANUAL */) } }); } // update = ParamConfig.BUTTON(null, { // callback: (node: BaseNodeType) => { // RivetObjNode.PARAM_CALLBACK_update_object_position(node as RivetObjNode); // }, // }); } const ParamsConfig = new RivetObjParamConfig(); export class RivetObjNode extends TypedObjNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this.hierarchyController = new HierarchyController(this); this.flags = new FlagsControllerD(this); this._helper = new AxesHelper(1); this._found_point_post = new Vector3(); this._on_object_before_render_bound = this._update.bind(this); } static type() { return "rivet"; } createObject() { const mesh = new Mesh(); mesh.matrixAutoUpdate = false; return mesh; } initializeNode() { this.hierarchyController.initializeNode(); this.addPostDirtyHook("rivet_on_dirty", () => { this.cookController.cookMainWithoutInputs(); }); this._updateHelperHierarchy(); this.flags.display.onUpdate(() => { 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._updateRenderHook(); this.cookController.endCook(); } // private _remove_render_hook() { // if (this._previous_on_before_render) { // this.object.onBeforeRender = this._previous_on_before_render; // } // } // private _update_updateMode(){ // The problem with a frame dependency is that if there is a hierarchy // of rivets, the update chain will be in the wrong order, and therefore wrong. // It is then better to update it via a code node. // const mode = UPDATE_MODES[this.pv.mode] // switch(mode){ // case RivetUpdateMode.ON_RENDER: { // this._remove_frame_dependency() // return this._add_render_hook() // } // case RivetUpdateMode.ON_FRAME_CHANGE: { // this._remove_render_hook() // return this._add_frame_depedency() // } // } // TypeAssert.unreachable(mode) // } // private _remove_frame_dependency(){ // const frame_graph_node = this.scene.time_controller.graph_node // this.removeGraphInput(frame_graph_node) // } // private _add_frame_depedency(){ // const frame_graph_node = this.scene.time_controller.graph_node // this.addGraphInput(frame_graph_node) // } _updateRenderHook() { const mode = UPDATE_MODES[this.pv.updateMode]; switch (mode) { case "On Every Render" /* ON_RENDER */: { return this._addRenderHook(); } case "Manual" /* MANUAL */: { return this._removeRenderHook(); } } TypeAssert.unreachable(mode); } _addRenderHook() { this.object.onBeforeRender = this._on_object_before_render_bound; this.object.frustumCulled = false; } _removeRenderHook() { this.object.onBeforeRender = () => { }; } // private _previous_on_before_render: RenderHook | undefined; _update(renderer, scene, camera, geometry, material, group) { const resolved_object = this._resolvedObject(); 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 ); } } } } // // // RESOLVE // // 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.pv.object.nodeWithContext(NodeContext.OBJ); if (node) { if (node.type() == GeoObjNode.type()) { const geoNode = node; this._resolvedSopGroup = geoNode.childrenDisplayController.sopGroup(); } else { this.states.error.set("found node is not a geo node"); } } } _resolvedObject() { if (!this._resolvedSopGroup) { return; } const object = this._resolvedSopGroup.children[0]; if (object) { return object; } } // // // ACTIVE // // static PARAM_CALLBACK_update_updateMode(node) { node._updateRenderHook(); } // private async _update_active_state() { // // await this.p.active.compute(); // this._update_render_hook(); // } // // // UPDATE // // static PARAM_CALLBACK_update(node) { node._update(); } // private _reset() { // this._resolved_sop_group = undefined; // // this._resolved_sop_group_child = undefined; // this._update_resolved_object(); // } }