UNPKG

@polygonjs/polygonjs

Version:

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

330 lines (329 loc) 12.3 kB
"use strict"; import { MOUSE, TOUCH } from "three"; import { TypedCameraControlsEventNode } from "./_BaseCameraControls"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { EventConnectionPoint, EventConnectionPointType } from "../utils/io/connections/Event"; import { CameraControlsNodeType } from "../../poly/NodeContext"; import { isBooleanTrue } from "../../../core/BooleanValue"; import { OrbitControls } from "../../../modules/core/controls/OrbitControls"; export { OrbitControls }; const OUTPUT_START = "start"; const OUTPUT_CHANGE = "change"; const OUTPUT_END = "end"; const _targetArray = [0, 0, 0]; export var MouseControl = /* @__PURE__ */ ((MouseControl2) => { MouseControl2["ROTATE"] = "rotate"; MouseControl2["PAN"] = "pan"; MouseControl2["DOLLY"] = "dolly"; return MouseControl2; })(MouseControl || {}); export const MOUSE_CONTROLS = ["rotate" /* ROTATE */, "dolly" /* DOLLY */, "pan" /* PAN */]; var TouchControl = /* @__PURE__ */ ((TouchControl2) => { TouchControl2["ROTATE"] = "rotate"; TouchControl2["PAN"] = "pan"; TouchControl2["DOLLY_PAN"] = "dolly + pan"; TouchControl2["DOLLY_ROTATE"] = "dolly + rotate"; return TouchControl2; })(TouchControl || {}); const TOUCH_CONTROLS = [ "rotate" /* ROTATE */, "pan" /* PAN */, "dolly + pan" /* DOLLY_PAN */, "dolly + rotate" /* DOLLY_ROTATE */ ]; const THREE_MOUSE_BY_MOUSE_CONTROL = { ["rotate" /* ROTATE */]: MOUSE.ROTATE, ["dolly" /* DOLLY */]: MOUSE.DOLLY, ["pan" /* PAN */]: MOUSE.PAN }; const THREE_TOUCH_BY_TOUCH_CONTROL = { ["rotate" /* ROTATE */]: TOUCH.ROTATE, ["pan" /* PAN */]: TOUCH.PAN, ["dolly + pan" /* DOLLY_PAN */]: TOUCH.DOLLY_PAN, ["dolly + rotate" /* DOLLY_ROTATE */]: TOUCH.DOLLY_ROTATE }; class CameraOrbitEventParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); this.main = ParamConfig.FOLDER(); /** @param enable/disable */ this.enabled = ParamConfig.BOOLEAN(1); /** @param toggle on to allow pan */ this.allowPan = ParamConfig.BOOLEAN(1); /** @param toggle on to allow rotate */ this.allowRotate = ParamConfig.BOOLEAN(1); /** @param toggle on to allow zoom */ this.allowZoom = ParamConfig.BOOLEAN(1); /** @param zoom speed */ this.zoomSpeed = ParamConfig.FLOAT(1, { range: [0, 2], rangeLocked: [true, false], visibleIf: { allowZoom: 1 } }); /** @param zoom to cursor */ this.zoomToCursor = ParamConfig.BOOLEAN(1, { visibleIf: { allowZoom: 1 } }); /** @param toggle on to have damping */ this.tdamping = ParamConfig.BOOLEAN(1); /** @param damping value */ this.damping = ParamConfig.FLOAT(0.1, { visibleIf: { tdamping: true } }); /** @param toggle on to have the pan in screen space */ this.screenSpacePanning = ParamConfig.BOOLEAN(1); /** @param rotation speed */ this.rotateSpeed = ParamConfig.FLOAT(0.5); this.limits = ParamConfig.FOLDER(); /** @param smallest distance the camera can go to the target (perspective cameras only) */ this.minDistance = ParamConfig.FLOAT(0.1, { range: [0.1, 100], rangeLocked: [true, false] }); /** @param max distance the camera can go away the target (perspective cameras only) */ this.maxDistance = ParamConfig.FLOAT(50, { range: [0, 100], rangeLocked: [true, false] }); /** @param min zoom (orthographic cameras only) */ this.minZoom = ParamConfig.FLOAT(0.01, { range: [0.01, 100], rangeLocked: [true, false] }); /** @param max zoom (orthographic cameras only) */ this.maxZoom = ParamConfig.FLOAT(50, { range: [0, 100], rangeLocked: [true, false] }); /** @param toggle on to limit the azimuth (up-down) angle */ this.limitAzimuthAngle = ParamConfig.BOOLEAN(0); /** @param azimuth angle range */ this.azimuthAngleRange = ParamConfig.VECTOR2(["-2*$PI", "2*$PI"], { visibleIf: { limitAzimuthAngle: 1 } }); /** @param polar (left-right) angle range */ this.polarAngleRange = ParamConfig.VECTOR2([0, "$PI"]); /** @param clamp position */ this.clampPosition = ParamConfig.BOOLEAN(false); /** @param min position */ this.positionMin = ParamConfig.VECTOR3([-10, -10, -10], { visibleIf: { clampPosition: 1 } }); /** @param max position */ this.positionMax = ParamConfig.VECTOR3([10, 10, 10], { visibleIf: { clampPosition: 1 } }); this.controls = ParamConfig.FOLDER(); /** @param leftMouseButton */ this.leftMouseButton = ParamConfig.INTEGER(MOUSE_CONTROLS.indexOf("rotate" /* ROTATE */), { menu: { entries: MOUSE_CONTROLS.map((name, value) => ({ name, value })) } }); /** @param leftMouseButton */ this.middleMouseButton = ParamConfig.INTEGER(MOUSE_CONTROLS.indexOf("dolly" /* DOLLY */), { menu: { entries: MOUSE_CONTROLS.map((name, value) => ({ name, value })) } }); /** @param leftMouseButton */ this.rightMouseButton = ParamConfig.INTEGER(MOUSE_CONTROLS.indexOf("pan" /* PAN */), { menu: { entries: MOUSE_CONTROLS.map((name, value) => ({ name, value })) } }); /** @param 1 finger touch */ this.oneFingerTouch = ParamConfig.INTEGER(TOUCH_CONTROLS.indexOf("rotate" /* ROTATE */), { menu: { entries: TOUCH_CONTROLS.map((name, value) => ({ name, value })) }, separatorBefore: true }); /** @param 2 fingers touch */ this.twoFingersTouch = ParamConfig.INTEGER(TOUCH_CONTROLS.indexOf("dolly + pan" /* DOLLY_PAN */), { menu: { entries: TOUCH_CONTROLS.map((name, value) => ({ name, value })) } }); this.misc = ParamConfig.FOLDER(); this.updateTargetEndMoveEnd = ParamConfig.BOOLEAN(1); /** @param target position. This is updated automatically as the camera is controlled by user events */ this.target = ParamConfig.VECTOR3([0, 0, 0], { cook: false, computeOnDirty: true, callback: (node) => { CameraOrbitControlsEventNode.PARAM_CALLBACK_updateTarget(node); } }); } /** @param toggle on to enable keys */ // enableKeys = ParamConfig.BOOLEAN(0); // /** @param key modes (pan or rotate) */ // keysMode = ParamConfig.INTEGER(KEYS_MODES.indexOf(KeysMode.PAN), { // visibleIf: {enableKeys: 1}, // menu: { // entries: KEYS_MODES.map((name, value) => { // return {name, value}; // }), // }, // }); // /** @param keys pan speed */ // keysPanSpeed = ParamConfig.FLOAT(7, { // range: [0, 10], // rangeLocked: [false, false], // visibleIf: {enableKeys: 1, keysMode: KEYS_MODES.indexOf(KeysMode.PAN)}, // }); // /** @param keys rotate speed vertical */ // keysRotateSpeedVertical = ParamConfig.FLOAT(1, { // range: [0, 1], // rangeLocked: [false, false], // visibleIf: {enableKeys: 1, keysMode: KEYS_MODES.indexOf(KeysMode.ROTATE)}, // }); // /** @param keys rotate speed horizontal */ // keysRotateSpeedHorizontal = ParamConfig.FLOAT(1, { // range: [0, 1], // rangeLocked: [false, false], // visibleIf: {enableKeys: 1, keysMode: KEYS_MODES.indexOf(KeysMode.ROTATE)}, // }); } const ParamsConfig = new CameraOrbitEventParamsConfig(); export class CameraOrbitControlsEventNode extends TypedCameraControlsEventNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._controlsByElementId = /* @__PURE__ */ new Map(); } static type() { return CameraControlsNodeType.ORBIT; } endEventName() { return "end"; } initializeNode() { this.io.outputs.setNamedOutputConnectionPoints([ new EventConnectionPoint(OUTPUT_START, EventConnectionPointType.BASE), new EventConnectionPoint(OUTPUT_CHANGE, EventConnectionPointType.BASE), new EventConnectionPoint(OUTPUT_END, EventConnectionPointType.BASE) ]); } _createControls(camera, element) { return new OrbitControls(camera, element); } async createControlsInstance(camera, element) { const controls = this._createControls(camera, element); controls.addEventListener("end", () => { this._on_controls_end(controls); }); this._controlsByElementId.set(element.id, controls); this._updateCache(); this._bind_listeners_to_controls_instance(controls); return controls; } _bind_listeners_to_controls_instance(controls) { controls.addEventListener("start", () => { this.dispatchEventToOutput(OUTPUT_START, {}); }); controls.addEventListener("change", () => { this.dispatchEventToOutput(OUTPUT_CHANGE, {}); }); controls.addEventListener("end", () => { this.dispatchEventToOutput(OUTPUT_END, {}); }); } setupControls(controls) { controls.enabled = isBooleanTrue(this.pv.enabled); controls.enablePan = isBooleanTrue(this.pv.allowPan); controls.enableRotate = isBooleanTrue(this.pv.allowRotate); controls.enableZoom = isBooleanTrue(this.pv.allowZoom); controls.zoomSpeed = this.pv.zoomSpeed; controls.zoomToCursor = isBooleanTrue(this.pv.zoomToCursor); controls.enableDamping = isBooleanTrue(this.pv.tdamping); controls.dampingFactor = this.pv.damping; controls.rotateSpeed = this.pv.rotateSpeed; controls.screenSpacePanning = isBooleanTrue(this.pv.screenSpacePanning); controls.minDistance = this.pv.minDistance; controls.maxDistance = this.pv.maxDistance; controls.minZoom = this.pv.minZoom; controls.maxZoom = this.pv.maxZoom; controls.clampPosition = this.pv.clampPosition; controls.positionBounds.min.copy(this.pv.positionMin); controls.positionBounds.max.copy(this.pv.positionMax); this._set_azimuth_angle(controls); controls.minPolarAngle = this.pv.polarAngleRange.x; controls.maxPolarAngle = this.pv.polarAngleRange.y; controls.target.copy(this.pv.target); if (controls.enabled) { controls.update(); } controls.mouseButtons.LEFT = THREE_MOUSE_BY_MOUSE_CONTROL[MOUSE_CONTROLS[this.pv.leftMouseButton]]; controls.mouseButtons.MIDDLE = THREE_MOUSE_BY_MOUSE_CONTROL[MOUSE_CONTROLS[this.pv.middleMouseButton]]; controls.mouseButtons.RIGHT = THREE_MOUSE_BY_MOUSE_CONTROL[MOUSE_CONTROLS[this.pv.rightMouseButton]]; controls.touches.ONE = THREE_TOUCH_BY_TOUCH_CONTROL[TOUCH_CONTROLS[this.pv.oneFingerTouch]]; controls.touches.TWO = THREE_TOUCH_BY_TOUCH_CONTROL[TOUCH_CONTROLS[this.pv.twoFingersTouch]]; } _set_azimuth_angle(controls) { if (isBooleanTrue(this.pv.limitAzimuthAngle)) { controls.minAzimuthAngle = this.pv.azimuthAngleRange.x; controls.maxAzimuthAngle = this.pv.azimuthAngleRange.y; } else { controls.minAzimuthAngle = Infinity; controls.maxAzimuthAngle = Infinity; } } updateRequired() { return isBooleanTrue(this.pv.tdamping); } // set_from_camera_node(controls: CameraControls, camera_node: BaseCameraObjNodeType): void { // const target = camera_node.params.vector3('target'); // controls.target.copy(target); // console.warn('set from camera node'); // } _on_controls_end(controls) { if (!isBooleanTrue(this.pv.updateTargetEndMoveEnd)) { return; } if (!isBooleanTrue(this.pv.allowPan)) { return; } controls.target.toArray(_targetArray); this.p.target.set(_targetArray); } static PARAM_CALLBACK_updateTarget(node) { node._updateTarget(); } _updateTarget() { this.setTarget(this.pv.target); } target(target) { if (!this._firstControls) { return; } target.copy(this._firstControls.target); } setTarget(newTarget) { this._controlsByElementId.forEach((control, element_id) => { const destTarget = control.target; if (!destTarget.equals(newTarget)) { destTarget.copy(newTarget); control.update(); } }); } disposeControlsForHtmlElementId(html_element_id) { const controls = this._controlsByElementId.get(html_element_id); if (controls) { this._controlsByElementId.delete(html_element_id); } this._updateCache(); } _updateCache() { this._firstControls = void 0; this._controlsByElementId.forEach((controls) => { this._firstControls = this._firstControls || controls; }); } }