UNPKG

awv3

Version:
140 lines (123 loc) 4.92 kB
import * as THREE from 'three'; import Object3 from '../../../three/object3'; import Ccref from '../ccref'; import Snapper from '../snapper'; export default class BaseHandler { constructor(sketcher, name) { this.sketcher = sketcher; this.sketch = sketcher.activeSketch; this.name = name; this.interactions = new Map(); this.destroyed = false; // bind this.on* to this and don't trigger event callbacks after destruction const onKeyUp = this.onKeyUp, onKeyDown = this.onKeyDown, onMouseMove = this.onMouseMove; this.onKeyUp = event => this.destroyed || onKeyUp.call(this, event); this.onKeyDown = event => this.destroyed || onKeyDown.call(this, event); if (this.onMouseMove) this.onMouseMove = event => this.destroyed || onMouseMove.call(this, event); } destroy(options) { this.destroyed = true; this.removeInteractions(options); } filterObjectsWithInteraction(object) { return false; } addInteraction(object) { if (!this.filterObjectsWithInteraction(object)) return; const interactionListeners = {}; for (let event of Object.values(Object3.Events.Interaction)) if (this[event]) interactionListeners[event] = this[event].bind(this, object); this.interactions.set(object.id, interactionListeners); object.graphics .createInteraction({ recursive: true, first: false, types: ['InfinitePlane', 'SketcherMesh'] }) .on(interactionListeners, {sync: true}); // prioritize sketch points in interaction if there is overlapping if (object.isPoint()) object.graphics.interaction.priority = 1; } addInteractions() { for (let object of this.sketch.descendants) this.addInteraction(object); this.sketcher.view.input.on('keyup', this.onKeyUp); this.sketcher.view.input.on('keydown', this.onKeyDown); if (this.onMouseMove) this.sketcher.view.input.on('mousemove', this.onMouseMove); } removeInteraction(object) { const interactionListeners = this.interactions.get(object.id); this.interactions.delete(object.id); if (object.graphics) { object.graphics.removeListener(interactionListeners); object.graphics.removeInteraction(); } } removeInteractions() { if (this.onMouseMove) this.sketcher.view.input.removeListener('mousemove', this.onMouseMove); this.sketcher.view.input.removeListener('keydown', this.onKeyDown); this.sketcher.view.input.removeListener('keyup', this.onKeyUp); for (let id of this.interactions.keys()) this.removeInteraction(new Ccref(this.sketcher, id)); } cancel() { // switch to drag handler by default this.sketcher.namedElements.handlers.drag.value = true; } onKeyUp(event) { switch (event.which) { case 27: // escape this.cancel(); break; case 46: // delete this.sketcher.deleteSelected({ onlyIfConsoleIsEmpty: true }); break; } } onKeyDown(event) {} createSnapper() { return new Snapper({ sketch: this.sketch, gridStep: this.sketcher.gridStep, pointRadius: this.sketcher.graphicScale, }); } //note: can be called in (view.input.on + 'mousemove') callback //in order to get current sketch coordinates of the mouse getRecentMousePosition() { const mousemove = this.sketcher.view.input.recent.mousemove; const point2 = new THREE.Vector2(mousemove.offsetX, mousemove.offsetY); const line3 = this.sketcher.view.getViewLine3(point2); const ray = new THREE.Ray(line3.start, line3.end.sub(line3.start).normalize()); ray.applyMatrix4(new THREE.Matrix4().getInverse(this.sketch.matrixWorld)); const plane = new THREE.Plane(new THREE.Vector3(0, 0, 1)); const result = new THREE.Vector3(); ray.intersectPlane(plane, result); ray.direction.negate(); ray.intersectPlane(plane, result); return result; } consoleComplete(cmd) { return Object.keys(commands); } consoleExecute(cmd) { // watch out for cmd === '__proto__' which could access the prototype if (commands.hasOwnProperty(cmd)) { this.sketcher.namedElements.handlers[commands[cmd]].value = true; return true; } else { return false; } } parseRestrictions(cmd) {} } const commands = Object.freeze({ point: 'point', pt: 'point', line: 'line', ln: 'line', arccenter: 'arccenter', ac: 'arccenter', arcmiddle: 'arcmiddle', am: 'arcmiddle', arctangent: 'arctangent', at: 'arctangent', circle: 'circle', cr: 'circle', });