awv3
Version:
⚡ AWV3 embedded CAD
134 lines (116 loc) • 5.38 kB
JavaScript
import * as THREE from 'three';
import Object3 from '../../../three/object3';
import { updateCommand } from '../command/highlevel';
import { UpdateDimensions } from '../command/lowlevel';
import { move } from '../geomutils';
import HoverHandler from './hover';
//minimal time between MUC solves (in milliseconds)
//note: 16ms delay is VERY SMALL
const MucDelayTime = 16.66;
export default class DragHandler extends HoverHandler {
constructor(sketcher, name) {
super(sketcher, name);
// allows to snap currently dragged object
this.snapper = undefined;
// the point that should follow the mouse position or undefined
this.draggedPoint = undefined;
// the sketch objects currently being dragged
this.draggedObjects = [];
// promise of the MUC task currently being solve on server
this.mucPromise = undefined;
// position where last processed movement finished
this.dragFrom = new THREE.Vector3();
// target drag position
this.dragTo = new THREE.Vector3();
}
filterObjectsWithInteraction(object) {
return object.id !== this.sketch.id && object.graphics !== undefined;
}
get displacement() {
return this.dragTo.clone().sub(this.draggedPoint ? this.draggedPoint.geomParams.start : this.dragFrom);
}
async startMuc() {
while (!this.dragTo.equals(this.dragFrom)) {
this.mucPromise = this.sketcher.moveUnderConstraints(this.draggedObjects, this.displacement);
this.dragFrom.copy(this.dragTo);
await this.mucPromise;
// artificial slowdown to lessen network/server burden
await new Promise(resolve => setTimeout(resolve, MucDelayTime));
// forget this MUC request (no MUC in progress)
this.mucPromise = undefined;
}
}
[Object3.Events.Interaction.Clicked](object, hitObject) {
if (!hitObject.first) return;
this.sketcher.selector.clicked(hitObject);
}
[Object3.Events.Interaction.Missed](object, hitObject) {
this.sketcher.constraintVisualizer.unhoverAll();
this.sketcher.selector.missed(hitObject);
}
[Object3.Events.Interaction.Picked](object, hitObject) {
if (!hitObject.first) return;
this.sketcher.view.controls.enabled = false;
}
async [Object3.Events.Interaction.Dropped](object, hitObject) {
if (!hitObject.first) return;
this.sketcher.view.controls.enabled = true;
if (!this.draggedObjects.length) return;
// finish MUC in progress (if present)
this.dragTo.copy(this.dragFrom);
await this.mucPromise;
// update object positions on the server
for (let draggedObject of this.draggedObjects) {
const encompassing = draggedObject.encompassing;
this.sketcher.run(updateCommand(this.sketch, encompassing, encompassing.geomParams));
this.sketcher.run(this.sketcher.autoconstraintCommands(draggedObject));
}
this.sketcher.incrementalSolveConstraints();
this.sketcher.run(UpdateDimensions(this.sketch));
// clear possibly overriding transient geomParams after all updates
for (let draggedObject of this.draggedObjects)
draggedObject.encompassing.geomParams = undefined;
this.draggedObjects = [];
this.snapper = undefined;
}
[Object3.Events.Interaction.Dragged](object, hitObject) {
if (!hitObject.first) return;
this.dragTo.copy(this.getRecentMousePosition());
if (!this.draggedObjects.length) {
// dragged objects are this object and all selected objects
// avoid double dragging when e.g. this object is selected or both object and its child are selected
const objects = this.sketcher.getSelected();
if (!objects.some(o => o.id === object.id)) objects.push(object);
this.draggedObjects = objects.filter(o => o === o.encompassing);
this.draggedObjects.push(
...objects.filter(o => {
const e = o.encompassing;
return !this.draggedObjects.some(oo => oo.id === e.id);
}),
);
this.draggedPoint = object.isPoint() ? object : undefined;
this.dragFrom.copy(this.dragTo);
this.snapper = this.createSnapper();
this.snapper.setDraggedObjects(this.draggedObjects, this.dragFrom, object);
this.snapper.ignoreObject(this.draggedObjects);
return;
}
this.dragTo.add(this.snapper.snapDraggedObject(this.dragTo).displacement);
if (this.sketcher.solveIncremental) {
if (!this.mucPromise) this.startMuc();
return;
}
const displacement = this.displacement;
for (let draggedObject of this.draggedObjects) {
const encompassing = draggedObject.encompassing;
// override geomParams from the state by transient geomParams
encompassing.geomParams = move(
encompassing.geomParams,
draggedObject === encompassing ? '' : draggedObject.pointType,
displacement,
);
encompassing.updateGraphicsRecursive();
}
this.dragFrom.copy(this.dragTo);
}
}