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