| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718 |
- /**
- * @author mschuetz / http://mschuetz.at
- *
- *
- */
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {KeyCodes} from "../KeyCodes.js";
- import {Utils} from "../utils.js";
- import {EventDispatcher} from "../EventDispatcher.js";
- export class InputHandler extends EventDispatcher {
- constructor (viewer) {
- super();
- this.viewer = viewer;
- this.renderer = viewer.renderer;
- this.domElement = this.renderer.domElement;
- this.enabled = true;
-
- this.scene = null;
- this.interactiveScenes = [];
- this.interactiveObjects = new Set();
- this.inputListeners = [];
- this.blacklist = new Set();
- this.drag = null;
- this.mouse = new THREE.Vector2(0, 0);
- this.selection = [];
- this.hoveredElements = [];
- this.pressedKeys = {};
- this.wheelDelta = 0;
- this.speed = 1;
- this.logMessages = false;
- if (this.domElement.tabIndex === -1) {
- this.domElement.tabIndex = 2222;
- }
- this.domElement.addEventListener('contextmenu', (event) => { event.preventDefault(); }, false);
- this.domElement.addEventListener('click', this.onMouseClick.bind(this), false);
- this.domElement.addEventListener('mousedown', this.onMouseDown.bind(this), false);
- this.domElement.addEventListener('mouseup', this.onMouseUp.bind(this), false);
- this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this), false);
- this.domElement.addEventListener('mousewheel', this.onMouseWheel.bind(this), false);
- this.domElement.addEventListener('DOMMouseScroll', this.onMouseWheel.bind(this), false); // Firefox
- this.domElement.addEventListener('dblclick', this.onDoubleClick.bind(this));
- this.domElement.addEventListener('keydown', this.onKeyDown.bind(this));
- this.domElement.addEventListener('keyup', this.onKeyUp.bind(this));
- this.domElement.addEventListener('touchstart', this.onTouchStart.bind(this));
- this.domElement.addEventListener('touchend', this.onTouchEnd.bind(this));
- this.domElement.addEventListener('touchmove', this.onTouchMove.bind(this));
- }
- addInputListener (listener) {
- this.inputListeners.push(listener);
- }
- removeInputListener (listener) {
- this.inputListeners = this.inputListeners.filter(e => e !== listener);
- }
- getSortedListeners(){
- return this.inputListeners.sort( (a, b) => {
- let ia = (a.importance !== undefined) ? a.importance : 0;
- let ib = (b.importance !== undefined) ? b.importance : 0;
- return ib - ia;
- });
- }
- onTouchStart (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onTouchStart');
- e.preventDefault();
- if (e.touches.length === 1) {
- let rect = this.domElement.getBoundingClientRect();
- let x = e.touches[0].pageX - rect.left;
- let y = e.touches[0].pageY - rect.top;
- this.mouse.set(x, y);
- this.startDragging(null);
- }
-
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: e.type,
- touches: e.touches,
- changedTouches: e.changedTouches
- });
- }
- }
- onTouchEnd (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onTouchEnd');
- e.preventDefault();
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'drop',
- drag: this.drag,
- viewer: this.viewer
- });
- }
- this.drag = null;
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: e.type,
- touches: e.touches,
- changedTouches: e.changedTouches
- });
- }
- }
- onTouchMove (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onTouchMove');
- e.preventDefault();
- if (e.touches.length === 1) {
- let rect = this.domElement.getBoundingClientRect();
- let x = e.touches[0].pageX - rect.left;
- let y = e.touches[0].pageY - rect.top;
- this.mouse.set(x, y);
- if (this.drag) {
- this.drag.mouse = 1;
- this.drag.lastDrag.x = x - this.drag.end.x;
- this.drag.lastDrag.y = y - this.drag.end.y;
- this.drag.end.set(x, y);
- if (this.logMessages) console.log(this.constructor.name + ': drag: ');
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'drag',
- drag: this.drag,
- viewer: this.viewer
- });
- }
- }
- }
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: e.type,
- touches: e.touches,
- changedTouches: e.changedTouches
- });
- }
- // DEBUG CODE
- // let debugTouches = [...e.touches, {
- // pageX: this.domElement.clientWidth / 2,
- // pageY: this.domElement.clientHeight / 2}];
- // for(let inputListener of this.getSortedListeners()){
- // inputListener.dispatchEvent({
- // type: e.type,
- // touches: debugTouches,
- // changedTouches: e.changedTouches
- // });
- // }
- }
- onKeyDown (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onKeyDown');
- // DELETE
- if (e.keyCode === KeyCodes.DELETE && this.selection.length > 0) {
- this.dispatchEvent({
- type: 'delete',
- selection: this.selection
- });
- this.deselectAll();
- }
- this.dispatchEvent({
- type: 'keydown',
- keyCode: e.keyCode,
- event: e
- });
- // for(let l of this.getSortedListeners()){
- // l.dispatchEvent({
- // type: "keydown",
- // keyCode: e.keyCode,
- // event: e
- // });
- // }
- this.pressedKeys[e.keyCode] = true;
- // e.preventDefault();
- }
- onKeyUp (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onKeyUp');
- delete this.pressedKeys[e.keyCode];
- e.preventDefault();
- }
- onDoubleClick (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onDoubleClick');
- let consumed = false;
- for (let hovered of this.hoveredElements) {
- if (hovered._listeners && hovered._listeners['dblclick']) {
- hovered.object.dispatchEvent({
- type: 'dblclick',
- mouse: this.mouse,
- object: hovered.object
- });
- consumed = true;
- break;
- }
- }
- if (!consumed) {
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'dblclick',
- mouse: this.mouse,
- object: null
- });
- }
- }
- e.preventDefault();
- }
- onMouseClick (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onMouseClick');
- e.preventDefault();
- }
- onMouseDown (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onMouseDown');
- e.preventDefault();
- let consumed = false;
- let consume = () => { return consumed = true; };
- if (this.hoveredElements.length === 0) {
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'mousedown',
- viewer: this.viewer,
- mouse: this.mouse
- });
- }
- }else{
- for(let hovered of this.hoveredElements){
- let object = hovered.object;
- object.dispatchEvent({
- type: 'mousedown',
- viewer: this.viewer,
- consume: consume
- });
- if(consumed){
- break;
- }
- }
- }
- if (!this.drag) {
- let target = this.hoveredElements
- .find(el => (
- el.object._listeners &&
- el.object._listeners['drag'] &&
- el.object._listeners['drag'].length > 0));
- if (target) {
- this.startDragging(target.object, {location: target.point});
- } else {
- this.startDragging(null);
- }
- }
- if (this.scene) {
- this.viewStart = this.scene.view.clone();
- }
- }
- onMouseUp (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onMouseUp');
- e.preventDefault();
- let noMovement = this.getNormalizedDrag().length() === 0;
-
- let consumed = false;
- let consume = () => { return consumed = true; };
- if (this.hoveredElements.length === 0) {
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'mouseup',
- viewer: this.viewer,
- mouse: this.mouse,
- consume: consume
- });
- if(consumed){
- break;
- }
- }
- }else{
- let hovered = this.hoveredElements
- .map(e => e.object)
- .find(e => (e._listeners && e._listeners['mouseup']));
- if(hovered){
- hovered.dispatchEvent({
- type: 'mouseup',
- viewer: this.viewer,
- consume: consume
- });
- }
- }
- if (this.drag) {
- if (this.drag.object) {
- if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);
- this.drag.object.dispatchEvent({
- type: 'drop',
- drag: this.drag,
- viewer: this.viewer
- });
- } else {
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'drop',
- drag: this.drag,
- viewer: this.viewer
- });
- }
- }
- // check for a click
- let clicked = this.hoveredElements.map(h => h.object).find(v => v === this.drag.object) !== undefined;
- if(clicked){
- if (this.logMessages) console.log(`${this.constructor.name}: click ${this.drag.object.name}`);
- this.drag.object.dispatchEvent({
- type: 'click',
- viewer: this.viewer,
- consume: consume,
- });
- }
- this.drag = null;
- }
- if(!consumed){
- if (e.button === THREE.MOUSE.LEFT) {
- if (noMovement) {
- let selectable = this.hoveredElements
- .find(el => el.object._listeners && el.object._listeners['select']);
- if (selectable) {
- selectable = selectable.object;
- if (this.isSelected(selectable)) {
- this.selection
- .filter(e => e !== selectable)
- .forEach(e => this.toggleSelection(e));
- } else {
- this.deselectAll();
- this.toggleSelection(selectable);
- }
- } else {
- this.deselectAll();
- }
- }
- } else if ((e.button === THREE.MOUSE.RIGHT) && noMovement) {
- this.deselectAll();
- }
- }
- }
- onMouseMove (e) {
- e.preventDefault();
- let rect = this.domElement.getBoundingClientRect();
- let x = e.clientX - rect.left;
- let y = e.clientY - rect.top;
- this.mouse.set(x, y);
- let hoveredElements = this.getHoveredElements();
- if(hoveredElements.length > 0){
- let names = hoveredElements.map(h => h.object.name).join(", ");
- if (this.logMessages) console.log(`${this.constructor.name}: onMouseMove; hovered: '${names}'`);
- }
- if (this.drag) {
- this.drag.mouse = e.buttons;
- this.drag.lastDrag.x = x - this.drag.end.x;
- this.drag.lastDrag.y = y - this.drag.end.y;
- this.drag.end.set(x, y);
- if (this.drag.object) {
- if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
- this.drag.object.dispatchEvent({
- type: 'drag',
- drag: this.drag,
- viewer: this.viewer
- });
- } else {
- if (this.logMessages) console.log(this.constructor.name + ': drag: ');
- let dragConsumed = false;
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'drag',
- drag: this.drag,
- viewer: this.viewer,
- consume: () => {dragConsumed = true;}
- });
- if(dragConsumed){
- break;
- }
- }
- }
- }else{
- let curr = hoveredElements.map(a => a.object).find(a => true);
- let prev = this.hoveredElements.map(a => a.object).find(a => true);
- if(curr !== prev){
- if(curr){
- if (this.logMessages) console.log(`${this.constructor.name}: mouseover: ${curr.name}`);
- curr.dispatchEvent({
- type: 'mouseover',
- object: curr,
- });
- }
- if(prev){
- if (this.logMessages) console.log(`${this.constructor.name}: mouseleave: ${prev.name}`);
- prev.dispatchEvent({
- type: 'mouseleave',
- object: prev,
- });
- }
- }
- if(hoveredElements.length > 0){
- let object = hoveredElements
- .map(e => e.object)
- .find(e => (e._listeners && e._listeners['mousemove']));
-
- if(object){
- object.dispatchEvent({
- type: 'mousemove',
- object: object
- });
- }
- }
- }
-
- // for (let inputListener of this.getSortedListeners()) {
- // inputListener.dispatchEvent({
- // type: 'mousemove',
- // object: null
- // });
- // }
-
- this.hoveredElements = hoveredElements;
- }
-
- onMouseWheel(e){
- if(!this.enabled) return;
- if(this.logMessages) console.log(this.constructor.name + ": onMouseWheel");
-
- e.preventDefault();
- let delta = 0;
- if (e.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9
- delta = e.wheelDelta;
- } else if (e.detail !== undefined) { // Firefox
- delta = -e.detail;
- }
- let ndelta = Math.sign(delta);
- // this.wheelDelta += Math.sign(delta);
- if (this.hoveredElement) {
- this.hoveredElement.object.dispatchEvent({
- type: 'mousewheel',
- delta: ndelta,
- object: this.hoveredElement.object
- });
- } else {
- for (let inputListener of this.getSortedListeners()) {
- inputListener.dispatchEvent({
- type: 'mousewheel',
- delta: ndelta,
- object: null
- });
- }
- }
- }
- startDragging (object, args = null) {
- let name = object ? object.name : "no name";
- if (this.logMessages) console.log(`${this.constructor.name}: startDragging: '${name}'`);
- this.drag = {
- start: this.mouse.clone(),
- end: this.mouse.clone(),
- lastDrag: new THREE.Vector2(0, 0),
- startView: this.scene.view.clone(),
- object: object
- };
- if (args) {
- for (let key of Object.keys(args)) {
- this.drag[key] = args[key];
- }
- }
- }
- getMousePointCloudIntersection (mouse) {
- return Utils.getMousePointCloudIntersection(
- this.mouse,
- this.scene.getActiveCamera(),
- this.viewer,
- this.scene.pointclouds);
- }
- toggleSelection (object) {
- let oldSelection = this.selection;
- let index = this.selection.indexOf(object);
- if (index === -1) {
- this.selection.push(object);
- object.dispatchEvent({
- type: 'select'
- });
- } else {
- this.selection.splice(index, 1);
- object.dispatchEvent({
- type: 'deselect'
- });
- }
- this.dispatchEvent({
- type: 'selection_changed',
- oldSelection: oldSelection,
- selection: this.selection
- });
- }
- deselect(object){
- let oldSelection = this.selection;
- let index = this.selection.indexOf(object);
- if(index >= 0){
- this.selection.splice(index, 1);
- object.dispatchEvent({
- type: 'deselect'
- });
- this.dispatchEvent({
- type: 'selection_changed',
- oldSelection: oldSelection,
- selection: this.selection
- });
- }
- }
- deselectAll () {
- for (let object of this.selection) {
- object.dispatchEvent({
- type: 'deselect'
- });
- }
- let oldSelection = this.selection;
- if (this.selection.length > 0) {
- this.selection = [];
- this.dispatchEvent({
- type: 'selection_changed',
- oldSelection: oldSelection,
- selection: this.selection
- });
- }
- }
- isSelected (object) {
- let index = this.selection.indexOf(object);
- return index !== -1;
- }
- registerInteractiveObject(object){
- this.interactiveObjects.add(object);
- }
- removeInteractiveObject(object){
- this.interactiveObjects.delete(object);
- }
- registerInteractiveScene (scene) {
- let index = this.interactiveScenes.indexOf(scene);
- if (index === -1) {
- this.interactiveScenes.push(scene);
- }
- }
- unregisterInteractiveScene (scene) {
- let index = this.interactiveScenes.indexOf(scene);
- if (index > -1) {
- this.interactiveScenes.splice(index, 1);
- }
- }
- getHoveredElement () {
- let hoveredElements = this.getHoveredElements();
- if (hoveredElements.length > 0) {
- return hoveredElements[0];
- } else {
- return null;
- }
- }
- getHoveredElements () {
- let scenes = this.interactiveScenes.concat(this.scene.scene);
- let interactableListeners = ['mouseup', 'mousemove', 'mouseover', 'mouseleave', 'drag', 'drop', 'click', 'select', 'deselect'];
- let interactables = [];
- for (let scene of scenes) {
- scene.traverseVisible(node => {
- if (node._listeners && node.visible && !this.blacklist.has(node)) {
- let hasInteractableListener = interactableListeners.filter((e) => {
- return node._listeners[e] !== undefined;
- }).length > 0;
- if (hasInteractableListener) {
- interactables.push(node);
- }
- }
- });
- }
-
- let camera = this.scene.getActiveCamera();
- let ray = Utils.mouseToRay(this.mouse, camera, this.domElement.clientWidth, this.domElement.clientHeight);
-
- let raycaster = new THREE.Raycaster();
- raycaster.ray.set(ray.origin, ray.direction);
- raycaster.params.Line.threshold = 0.2;
- let intersections = raycaster.intersectObjects(interactables.filter(o => o.visible), false);
- return intersections;
- }
- setScene (scene) {
- this.deselectAll();
- this.scene = scene;
- }
- update (delta) {
- }
- getNormalizedDrag () {
- if (!this.drag) {
- return new THREE.Vector2(0, 0);
- }
- let diff = new THREE.Vector2().subVectors(this.drag.end, this.drag.start);
- diff.x = diff.x / this.domElement.clientWidth;
- diff.y = diff.y / this.domElement.clientHeight;
- return diff;
- }
- getNormalizedLastDrag () {
- if (!this.drag) {
- return new THREE.Vector2(0, 0);
- }
- let lastDrag = this.drag.lastDrag.clone();
- lastDrag.x = lastDrag.x / this.domElement.clientWidth;
- lastDrag.y = lastDrag.y / this.domElement.clientHeight;
- return lastDrag;
- }
- }
|