UNPKG

polygonjs-engine

Version:

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

138 lines (137 loc) 5.3 kB
import {TypedObjNode} from "../_Base"; import {Matrix4 as Matrix42} from "three/src/math/Matrix4"; import {CoreTransform, ROTATION_ORDERS, RotationOrder} from "../../../../core/Transform"; import {NodeParamsConfig, ParamConfig} from "../../utils/params/ParamsConfig"; export function TransformedParamConfig(Base3, default_params) { const matrixAutoUpdate = default_params?.matrixAutoUpdate || false; return class Mixin extends Base3 { constructor() { super(...arguments); this.transform = ParamConfig.FOLDER(); this.keepPosWhenParenting = ParamConfig.BOOLEAN(0); this.rotationOrder = ParamConfig.INTEGER(ROTATION_ORDERS.indexOf(RotationOrder.XYZ), { menu: { entries: ROTATION_ORDERS.map((order, v) => { return {name: order, value: v}; }) } }); this.t = ParamConfig.VECTOR3([0, 0, 0]); this.r = ParamConfig.VECTOR3([0, 0, 0]); this.s = ParamConfig.VECTOR3([1, 1, 1]); this.scale = ParamConfig.FLOAT(1); this.matrixAutoUpdate = ParamConfig.BOOLEAN(matrixAutoUpdate ? 1 : 0); this.updateTransformFromObject = ParamConfig.BUTTON(null, { callback: (node) => { TransformController.PARAM_CALLBACK_update_transform_from_object(node); } }); this.tlookAt = ParamConfig.BOOLEAN(0); this.lookAtPos = ParamConfig.VECTOR3([0, 0, 0], { visibleIf: {tlookAt: 1} }); this.up = ParamConfig.VECTOR3([0, 1, 0], { visibleIf: {tlookAt: 1} }); } }; } class TransformedParamsConfig extends TransformedParamConfig(NodeParamsConfig) { } export class TransformedObjNode extends TypedObjNode { constructor() { super(...arguments); this.transform_controller = new TransformController(this); } } const HOOK_NAME = "_cook_main_without_inputs_when_dirty"; export class TransformController { constructor(node) { this.node = node; this._cook_main_without_inputs_when_dirty_bound = this._cook_main_without_inputs_when_dirty.bind(this); this._core_transform = new CoreTransform(); this._keep_pos_when_parenting_m_object = new Matrix42(); this._keep_pos_when_parenting_m_new_parent_inv = new Matrix42(); } initializeNode() { if (!this.node.dirtyController.has_hook(HOOK_NAME)) { this.node.dirtyController.addPostDirtyHook(HOOK_NAME, this._cook_main_without_inputs_when_dirty_bound); } } async _cook_main_without_inputs_when_dirty() { await this.node.cookController.cook_main_without_inputs(); } update() { this.update_transform_with_matrix(); const object = this.node.object; object.matrixAutoUpdate = this.node.pv.matrixAutoUpdate; } update_transform_with_matrix(matrix) { const object = this.node.object; if (matrix != null && !matrix.equals(object.matrix)) { object.matrix.copy(matrix); object.dispatchEvent({type: "change"}); } else { this._update_matrix_from_params_with_core_transform(); } } _update_matrix_from_params_with_core_transform() { const object = this.node.object; let prev_auto_update = object.matrixAutoUpdate; if (prev_auto_update) { object.matrixAutoUpdate = false; } const matrix = this._core_transform.matrix(this.node.pv.t, this.node.pv.r, this.node.pv.s, this.node.pv.scale, ROTATION_ORDERS[this.node.pv.rotationOrder]); object.matrix.identity(); object.applyMatrix4(matrix); this._apply_look_at(); object.updateMatrix(); if (prev_auto_update) { object.matrixAutoUpdate = true; } object.dispatchEvent({type: "change"}); } _apply_look_at() { const pv = this.node.pv; if (!pv.tlookAt) { return; } this.node.object.up.copy(pv.up); this.node.object.lookAt(pv.lookAtPos); } set_params_from_matrix(matrix, options = {}) { CoreTransform.set_params_from_matrix(matrix, this.node, options); } static update_node_transform_params_if_required(node, new_parent_object) { node.transform_controller.update_node_transform_params_if_required(new_parent_object); } update_node_transform_params_if_required(new_parent_object) { if (!this.node.pv.keepPosWhenParenting) { return; } if (!this.node.scene().loadingController.loaded()) { return; } if (new_parent_object == this.node.object.parent) { return; } const object = this.node.object; object.updateMatrixWorld(true); new_parent_object.updateMatrixWorld(true); this._keep_pos_when_parenting_m_object.copy(object.matrixWorld); this._keep_pos_when_parenting_m_new_parent_inv.copy(new_parent_object.matrixWorld); this._keep_pos_when_parenting_m_new_parent_inv.invert(); this._keep_pos_when_parenting_m_object.premultiply(this._keep_pos_when_parenting_m_new_parent_inv); CoreTransform.set_params_from_matrix(this._keep_pos_when_parenting_m_object, this.node, {scale: true}); } update_node_transform_params_from_object(update_matrix = false) { const object = this.node.object; if (update_matrix) { object.updateMatrix(); } CoreTransform.set_params_from_matrix(object.matrix, this.node, {scale: true}); } static PARAM_CALLBACK_update_transform_from_object(node) { node.transform_controller.update_node_transform_params_from_object(); } }