@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
116 lines (115 loc) • 4.52 kB
JavaScript
"use strict";
import { BaseRayObjectIntersectionsController } from "./_BaseRayObjectIntersectionsController";
import {
filterObjectsWithMatchButtonsConfig,
propertyMatchesButtonsConfig,
buttonsConfigFromEvent
} from "./Common";
import { ParamConfig } from "../../../../nodes/utils/params/ParamsConfig";
import { MouseButtons } from "../../../../../core/MouseButton";
import { CursorMoveMonitor } from "../../../../../core/CursorMoveMonitor";
const _buttonsConfig = { buttons: MouseButtons.LEFT, ctrl: false, shift: false, alt: false };
function hasPropertiesWithCursorMoveLessThan(options, distance) {
for (const option of options) {
if (distance < option.click.maxCursorMoveDistance) {
return true;
}
}
return false;
}
export function ClickParamConfig(Base) {
return class Mixin extends Base {
constructor() {
super(...arguments);
/** @param max cursor move distance */
this.maxCursorMoveDistance = ParamConfig.FLOAT(0.05, {
range: [0, 1],
rangeLocked: [true, false]
});
/** @param max duration */
this.maxDuration = ParamConfig.INTEGER(200, {
range: [0, 1e3],
rangeLocked: [true, false]
});
}
};
}
export class RayObjectIntersectionsMouseClickController extends BaseRayObjectIntersectionsController {
constructor() {
super(...arguments);
this._propertiesListByObject = /* @__PURE__ */ new Map();
this._intersectedStateOnMousedownByObject = /* @__PURE__ */ new Map();
this._intersectedStateOnMouseupByObject = /* @__PURE__ */ new Map();
this._objectsMatchingEventConfig = [];
this._objectsIntersectedOnMousedown = [];
this._cursorMoveMonitor = new CursorMoveMonitor();
this._mousedownReceivedAt = 0;
this._bound = {
mouseup: this._onMouseup.bind(this)
};
}
onMousedown(event) {
this._mousedownEvent = event;
this._mousedownReceivedAt = performance.now();
if (this._objects.length == 0) {
return;
}
filterObjectsWithMatchButtonsConfig(
event,
this._objects,
this._propertiesListByObject,
this._objectsMatchingEventConfig
);
if (this._objectsMatchingEventConfig.length == 0) {
return;
}
document.addEventListener("mouseup", this._bound.mouseup);
document.addEventListener("touchend", this._bound.mouseup);
this._cursorMoveMonitor.addPointermoveEventListener(
this._scene.eventsDispatcher.pointerEventsController.cursor()
);
this._setIntersectedState(this._objectsMatchingEventConfig, this._intersectedStateOnMousedownByObject);
}
_onMouseup() {
document.removeEventListener("mouseup", this._bound.mouseup);
document.removeEventListener("touchend", this._bound.mouseup);
this._cursorMoveMonitor.removeEventListener();
const event = this._mousedownEvent;
if (!event) {
return;
}
this._mousedownEvent = void 0;
const duration = performance.now() - this._mousedownReceivedAt;
const movedCursorDistance = this._cursorMoveMonitor.movedCursorDistance();
const objects = this._objectsMatchingEventConfig;
this._objectsIntersectedOnMousedown.length = 0;
for (const object of objects) {
const propertiesList = this._propertiesListByObject.get(object);
if (propertiesList && hasPropertiesWithCursorMoveLessThan(propertiesList, movedCursorDistance)) {
const isIntersectingOnMousedown = this._intersectedStateOnMousedownByObject.get(object);
if (isIntersectingOnMousedown) {
this._objectsIntersectedOnMousedown.push(object);
}
}
}
if (this._objectsIntersectedOnMousedown.length == 0) {
return;
}
this._setIntersectedState(objects, this._intersectedStateOnMouseupByObject);
buttonsConfigFromEvent(event, _buttonsConfig);
const objectsIntersectedOnMousedown = this._objectsIntersectedOnMousedown;
for (const object of objectsIntersectedOnMousedown) {
const propertiesList = this._propertiesListByObject.get(object);
if (propertiesList) {
const isIntersectingOnMouseup = this._intersectedStateOnMouseupByObject.get(object);
if (isIntersectingOnMouseup == true) {
for (const properties of propertiesList) {
if (movedCursorDistance < properties.click.maxCursorMoveDistance && duration < properties.click.maxDuration && propertyMatchesButtonsConfig(properties.config, _buttonsConfig)) {
properties.click.callback();
}
}
}
}
}
}
}