UNPKG

@polygonjs/polygonjs

Version:

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

331 lines (330 loc) 10.8 kB
"use strict"; import { CoreTransform } from "../../../core/Transform"; import { ObjNodeRenderOrder } from "./_Base"; import { LayersController, LayerParamConfig } from "./utils/LayersController"; import { CameraRenderParamConfig } from "./utils/cameras/RenderController"; import { TransformedParamConfig, TransformController } from "./utils/TransformController"; import { ObjChildrenDisplayController } from "./utils/ObjChildrenDisplayController"; import { DisplayNodeController } from "../utils/DisplayNodeController"; import { NodeContext } from "../../poly/NodeContext"; import { FlagsControllerD } from "../utils/FlagsController"; import { TypedObjNode } from "./_Base"; import { HierarchyController } from "./utils/HierarchyController"; import { CameraHelper } from "../../../core/helpers/CameraHelper"; import { ParamConfig, NodeParamsConfig } from "../utils/params/ParamsConfig"; import { isBooleanTrue } from "../../../core/BooleanValue"; import { CameraPostProcessParamConfig } from "./utils/cameras/PostProcessParamOptions"; import { Poly } from "../../Poly"; import { CORE_CAMERA_DEFAULT } from "../../../core/camera/CoreCamera"; import { CameraControlsSopOperation } from "../../operations/sop/CameraControls"; import { CameraRendererSopOperation } from "../../operations/sop/CameraRenderer"; import { CameraCSSRendererSopOperation } from "../../operations/sop/CameraCSSRenderer"; import { CameraPostProcessSopOperation } from "../../operations/sop/CameraPostProcess"; import { CameraRenderSceneSopOperation } from "../../operations/sop/CameraRenderScene"; import { CameraFrameModeSopOperation } from "../../operations/sop/CameraFrameMode"; import { CoreCameraFrameParamConfig } from "../../../core/camera/CoreCameraFrameMode"; import { CorePath } from "../../../core/geometry/CorePath"; const EVENT_CHANGE = { type: "change" }; export function CameraMainCameraParamConfig(Base) { return class Mixin extends Base { constructor() { super(...arguments); this.setMainCamera = ParamConfig.BUTTON(null, { callback: (node, param) => { BaseCameraObjNodeClass.PARAM_CALLBACK_setMainCamera(node); } }); } }; } export function ThreejsCameraTransformParamConfig(Base) { return class Mixin extends Base { constructor() { super(...arguments); this.camera = ParamConfig.FOLDER(); /** @param controls node to allow the camera to be moved by user input */ this.controls = ParamConfig.NODE_PATH("", { nodeSelection: { context: NodeContext.EVENT }, dependentOnFoundNode: true }); /** @param near */ this.near = ParamConfig.FLOAT(CORE_CAMERA_DEFAULT.near, { range: [0.1, 100], cook: false, computeOnDirty: true, callback: (node, param) => { BaseThreejsCameraObjNodeClass.PARAM_CALLBACK_update_near_far_from_param( node, param ); } }); /** @param far */ this.far = ParamConfig.FLOAT(CORE_CAMERA_DEFAULT.far, { range: [0, 100], cook: false, computeOnDirty: true, callback: (node, param) => { BaseThreejsCameraObjNodeClass.PARAM_CALLBACK_update_near_far_from_param( node, param ); } }); // aspect = ParamConfig.FLOAT(1); // lock_width = ParamConfig.BOOLEAN(1); // look_at = ParamConfig.OPERATOR_PATH(''); /** @param display */ this.display = ParamConfig.BOOLEAN(1); /** @param show helper */ this.showHelper = ParamConfig.BOOLEAN(0); } }; } export class BaseCameraObjParamsConfig extends CameraMainCameraParamConfig(NodeParamsConfig) { } export class BaseThreejsCameraObjParamsConfig extends CameraPostProcessParamConfig( CameraRenderParamConfig( CoreCameraFrameParamConfig( TransformedParamConfig( LayerParamConfig(ThreejsCameraTransformParamConfig(CameraMainCameraParamConfig(NodeParamsConfig))) ) ) ) ) { } export class TypedCameraObjNode extends TypedObjNode { constructor() { super(...arguments); // public readonly flags: FlagsControllerD = new FlagsControllerD(this); this.renderOrder = ObjNodeRenderOrder.CAMERA; this._aspect = -1; } get object() { return this._object; } async cook() { this.updateCamera(); this._object.dispatchEvent(EVENT_CHANGE); this.cookController.endCook(); } // prepareRaycaster(mouse: Vector2, raycaster: Raycaster) {} camera() { return this._object; } updateCamera() { } static PARAM_CALLBACK_setMainCamera(node) { node.setAsMainCamera(); } setAsMainCamera() { const path = CorePath.objectPath(this.object); this.scene().camerasController.setMainCameraPath(path); } setupForAspectRatio(aspect) { } // protected _updateForAspectRatio(): void {} update_transform_params_from_object() { CoreTransform.setParamsFromObject(this._object, this); } static PARAM_CALLBACK_update_from_param(node, param) { node.object[param.name()] = node.pv[param.name()]; } } export class TypedThreejsCameraObjNode extends TypedCameraObjNode { constructor() { super(...arguments); this.flags = new FlagsControllerD(this); this.hierarchyController = new HierarchyController(this); this.transformController = new TransformController(this); // protected _renderController: RenderController | undefined; // renderController(): RenderController { // return (this._renderController = this._renderController || new RenderController(this)); // } // protected _postProcessController: PostProcessController | undefined; // postProcessController(): PostProcessController { // return (this._postProcessController = this._postProcessController || new PostProcessController(this)); // } // display_node and children_display controllers this.childrenDisplayController = new ObjChildrenDisplayController( this ); this.displayNodeController = new DisplayNodeController( this, this.childrenDisplayController.displayNodeControllerCallbacks() ); // this._childrenControllerContext = NodeContext.SOP; } _layersController() { return this.__layersController__ = this.__layersController__ || new LayersController(this); } initializeBaseNode() { super.initializeBaseNode(); this.io.outputs.setHasOneOutput(); this.hierarchyController.initializeNode(); this.transformController.initializeNode(); this.childrenDisplayController.initializeNode(); this.initHelperHook(); } createNode(node_class, options) { return super.createNode(node_class, options); } children() { return super.children(); } nodesByType(type) { return super.nodesByType(type); } // override prepareRaycaster(mouse: Vector2, raycaster: Raycaster) { // raycaster.setFromCamera(mouse, this._object); // } async cook() { this.transformController.update(); this._layersController().update(); this.updateNearFar(); this.updateCamera(); this._updateHelper(); const objects = [this._object]; const node = this; const hierachyParams = { group: "" }; CameraControlsSopOperation.updateObject({ objects, params: { node: this.pv.controls, ...hierachyParams }, node, active: true, errorIfNodeNotFound: false }); CameraRendererSopOperation.updateObject({ objects, params: { node: this.pv.renderer, ...hierachyParams }, node, active: this.pv.setRenderer }); CameraCSSRendererSopOperation.updateObject({ objects, params: { node: this.pv.CSSRenderer, ...hierachyParams }, node, active: this.pv.setCSSRenderer }); CameraPostProcessSopOperation.updateObject({ objects, params: { node: this.pv.postProcessNode, useOtherNode: false, ...hierachyParams }, node, active: this.pv.doPostProcess }); CameraRenderSceneSopOperation.updateObject({ objects, params: { node: this.pv.scene, ...hierachyParams }, node, active: this.pv.setScene }); CameraFrameModeSopOperation.updateObject({ objects, params: { frameMode: this.pv.frameMode, expectedAspectRatio: this.pv.expectedAspectRatio, ...hierachyParams } }); this._object.dispatchEvent(EVENT_CHANGE); this.scene().camerasController.updateFromChangeInObject(this.object); this.cookController.endCook(); } static PARAM_CALLBACK_update_near_far_from_param(node, param) { node.updateNearFar(); } updateNearFar() { if (this._object.near != this.pv.near || this._object.far != this.pv.far) { this._object.near = this.pv.near; this._object.far = this.pv.far; this._object.updateProjectionMatrix(); this._updateHelper(); } } // override setupForAspectRatio(aspect: number) { // if (isNaN(aspect)) { // return; // } // if (aspect && this._aspect != aspect) { // this._aspect = aspect; // this._updateForAspectRatio(); // } // } async createViewer(options) { if (this.isDirty()) { await this.compute(); } const viewer = Poly.camerasRegister.createViewer({ camera: this.object, scene: this.scene() }); let element; let updateAutoRenderOnIntersectionChange; if (options && options instanceof HTMLElement) { element = options; } else { element = options == null ? void 0 : options.element; updateAutoRenderOnIntersectionChange = options == null ? void 0 : options.updateAutoRenderOnIntersectionChange; } if (viewer) { if (element) { viewer.mount(element, { updateAutoRenderOnIntersectionChange }); } } return viewer; } initHelperHook() { this.flags.display.onUpdate(() => { this._updateHelper(); }); } helperVisible() { return this.flags.display.active() && isBooleanTrue(this.pv.showHelper); } _createHelper() { const helper = new CameraHelper(this.object); helper.update(); return helper; } _updateHelper() { if (this.helperVisible()) { if (!this._helper) { this._helper = this._createHelper(); } if (this._helper) { this.object.add(this._helper); this._helper.update(); } } else { if (this._helper) { this.object.remove(this._helper); } } } } export class BaseCameraObjNodeClass extends TypedCameraObjNode { } export class BaseThreejsCameraObjNodeClass extends TypedThreejsCameraObjNode { PARAM_CALLBACK_update_effects_composer(node) { } }