@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
236 lines (235 loc) • 7.3 kB
JavaScript
"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();
// }
}