UNPKG

awv3

Version:
396 lines (315 loc) 13.7 kB
import _extends from "@babel/runtime/helpers/extends"; import * as THREE from 'three'; import Raycaster from '../three/raycaster'; import Object3 from '../three/object3'; var Interaction = /*#__PURE__*/ function () { function Interaction(view, options) { if (view === void 0) { view = Error.log('View undefined'); } if (options === void 0) { options = {}; } this.view = view; this.canvas = view.canvas; this.raycaster = new Raycaster(this); this.enabled = typeof options.enabled !== 'undefined' ? options.enabled : true; this.targets = []; this.intersects = []; this.hits = {}; this.hitsArray = []; this.actions = {}; this.actionsArray = []; this.hovered = {}; this.filter = undefined; this.coordinates = new THREE.Vector3(0, 0, 0); this.click = new THREE.Vector3(0, 0, 0); this.delta = 0; this.__hovered = []; this.__frontside = {}; } var _proto = Interaction.prototype; _proto.update = function update() { if (!this.enabled) return; for (var _iterator = this.targets, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; if (_isArray) { if (_i >= _iterator.length) break; _ref = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; _ref = _i.value; } var _target = _ref; if (_target.interaction && _target.interaction.enabled && (this.view.invalidateFrames > 0 || this.view.renderAlways || this.view.controls.inMotion) /*|| this.view.hudInMotion TODO: there are several hids now */ ) { _target.emit(Object3.Events.Lifecycle.Rendered); } } }; _proto.onMouseMove = function onMouseMove(event) { var _this = this; if (!this.enabled) return; this.coordinates.set(event.offsetX / this.view.width * 2 - 1, -(event.offsetY / this.view.height) * 2 + 1, 1); this.delta = Math.max(this.delta, Math.abs(this.click.x - this.coordinates.x) + Math.abs(this.click.y - this.coordinates.y)); // View is moved or dry run (nothing under the curser when the view was clicked/touched) if (this.view.controls.interaction || !event.fake && this.view.input.mouse.down && this.actionsArray.length == 0) return; this.raycaster.setFromCamera(this.coordinates, this.view.camera.display); this.intersects = []; this.__hovered = []; this.__frontside = {}; if (this.targets.length > 0) { this.raycaster.castObjects(this.targets, this.intersects, this.filter); if (this.intersects.length > 0) { // Objects that have been pierced for (var _iterator2 = this.intersects, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref2; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref2 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref2 = _i2.value; } var _data = _ref2; // Set unique key _data.id = _data.receiver.id; if (_data.receiver.interaction.recursive) _data.id += 'R' + _data.object.id; if (_data.face && _data.object.userData && _data.object.userData.refs) _data.id += 'F' + _data.face.materialIndex; // Add region specific data if (_data.object.type === 'Region') { _data.id += 'V' + _data.ref.id; _data.meta = _data.ref.meta; _data.vertexId = _data.ref.meta.id; _data.material = _data.ref; } // Flag is set on first occurance of a receiver _data.first = _data === this.intersects[0]; // Current RAF timestamp _data.time = this.canvas.renderer.time; // Mouse coordinates in world CS _data.ray = this.raycaster.ray; // Fetch meta, if any if (_data.face && _data.object.userData && _data.object.userData.refs) { _data.meta = _data.object.userData.refs[_data.face.materialIndex]; } else if (_data.object.userData && _data.object.userData.meta) { _data.meta = _data.object.userData.meta; } if (_data.object.material) { var isMultiMaterial = Array.isArray(_data.object.material); if (_data.face) { if (isMultiMaterial) { _data.materialIndex = _data.face.materialIndex; _data.multiMaterial = _data.object.material; _data.material = _data.object.material[_data.face.materialIndex]; } else { _data.material = _data.object.material; } } else if (typeof _data.index !== 'undefined') { if (isMultiMaterial && _data.object.geometry.groups) { for (var _iterator3 = _data.object.geometry.groups, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { var _ref3; if (_isArray3) { if (_i3 >= _iterator3.length) break; _ref3 = _iterator3[_i3++]; } else { _i3 = _iterator3.next(); if (_i3.done) break; _ref3 = _i3.value; } var _group = _ref3; if (_group.start <= _data.index && _group.start + _group.count > _data.index) { _data.materialIndex = _group.materialIndex; _data.multiMaterial = _data.object.material; _data.material = _data.object.material[_group.materialIndex]; _data.meta = _group.meta; _data.id += 'L' + _group.materialIndex; break; } } } else { _data.material = _data.object.material; } } } // Raycaster can return two intersections, front & back, we cast away the backside if (this.__frontside[_data.id]) continue; // Mark it for hover if it hasn't been hit already if ((!_data.receiver.interaction.first || _data.first) && !this.hovered[_data.id]) this.__hovered.push(_data); this.hits[_data.id] = _data; this.__frontside[_data.id] = true; } } else { this.actionsArray.length == 0 && this.view.setCursor(); } // Take out everything that's not under the cursor right now and that's not in the actions this.hitsArray = Object.keys(this.hits).map(function (item) { return _this.hits[item]; }) // Sort after scene-graph .sort(function (a, b) { return a.receiver.depthIndex - b.receiver.depthIndex; }) // Filter .filter(function (data) { var dispose = data.receiver.interaction.first && !data.first || data.time != _this.canvas.renderer.time; if (dispose) { if (_this.hovered[data.id] && !_this.actions[data.id]) { delete _this.hovered[data.id]; data.receiver.emit(Object3.Events.Interaction.Unhovered, data); _this.view.invalidate(); } delete _this.hits[data.id]; } return !dispose; }); // Hover items this.__hovered.forEach(function (data) { _this.hovered[data.id] = true; data.receiver.emit(Object3.Events.Interaction.Hovered, data); _this.view.invalidate(); }); } // Object being dragged if (this.delta > 0.01 && Object.keys(this.actions).length > 0) { for (var _iterator4 = this.actionsArray, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { var _ref4; if (_isArray4) { if (_i4 >= _iterator4.length) break; _ref4 = _iterator4[_i4++]; } else { _i4 = _iterator4.next(); if (_i4.done) break; _ref4 = _i4.value; } var _data3 = _ref4; if (!_data3.receiver.interaction.first || _data3.first) { var vector = this.coordinates.clone().unproject(this.view.camera.display).sub(this.view.camera.display.position).normalize(); _data3.drag = this.view.camera.display.position.clone().add(vector.multiplyScalar(_data3.distance)).add(_data3.offset); _data3.ray = this.raycaster.ray; _data3.receiver.emit(Object3.Events.Interaction.Dragged, _data3); this.view.invalidate(); } } } }; _proto.onMouseOut = function onMouseOut(event) { if (!this.enabled) return; for (var _iterator5 = this.hitsArray, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { var _ref5; if (_isArray5) { if (_i5 >= _iterator5.length) break; _ref5 = _iterator5[_i5++]; } else { _i5 = _iterator5.next(); if (_i5.done) break; _ref5 = _i5.value; } var _data4 = _ref5; if (this.hovered[_data4.id] && !this.actions[_data4.id]) { delete this.hovered[_data4.id]; _data4.receiver.emit(Object3.Events.Interaction.Unhovered, _data4); this.view.invalidate(); } delete this.hits[_data4.id]; } }; _proto.onMouseDown = function onMouseDown(event) { if (!this.enabled) return; this.delta = 0; this.click.set(event.offsetX / this.view.width * 2 - 1, -(event.offsetY / this.view.height) * 2 + 1, 1); // Cause a fake-mousemove to refresh hits this.onMouseMove(_extends({}, event, { fake: true })); this.actions = {}; this.actionsArray = []; for (var _iterator6 = this.hitsArray, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { var _ref6; if (_isArray6) { if (_i6 >= _iterator6.length) break; _ref6 = _iterator6[_i6++]; } else { _i6 = _iterator6.next(); if (_i6.done) break; _ref6 = _i6.value; } var _data5 = _ref6; if (!_data5.receiver.interaction.first || _data5.first) { var pos = _data5.receiver.parent ? _data5.receiver.parent.localToWorld(_data5.receiver.position.clone()) : _data5.receiver.position.clone(); _data5.offset = pos.sub(_data5.point.clone()); this.actions[_data5.id] = _data5; this.actionsArray.push(_data5); _data5.receiver.emit(Object3.Events.Interaction.Picked, _data5); } } this.view.invalidate(); }; _proto.onMouseUp = function onMouseUp(event) { if (!this.enabled) return; // Signal Mouseup for (var _iterator7 = this.actionsArray, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { var _ref7; if (_isArray7) { if (_i7 >= _iterator7.length) break; _ref7 = _iterator7[_i7++]; } else { _i7 = _iterator7.next(); if (_i7.done) break; _ref7 = _i7.value; } var _data6 = _ref7; if (this.hovered[_data6.id] && !this.hits[_data6.id]) { delete this.hovered[_data6.id]; _data6.receiver.emit(Object3.Events.Interaction.Unhovered, _data6); } _data6.receiver.emit(Object3.Events.Interaction.Dropped, _data6); if (this.delta < 0.05) { _data6.receiver.emit(Object3.Events.Interaction.Clicked, _data6); } } if (this.actionsArray.length == 0 && this.delta < 0.05) { for (var _iterator8 = this.targets, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { var _ref8; if (_isArray8) { if (_i8 >= _iterator8.length) break; _ref8 = _iterator8[_i8++]; } else { _i8 = _iterator8.next(); if (_i8.done) break; _ref8 = _i8.value; } var _target2 = _ref8; _target2.emit(Object3.Events.Interaction.Missed); } } this.view.invalidate(); this.actions = {}; this.actionsArray = []; }; _proto.removeTarget = function removeTarget(obj) { var _this2 = this; var index = this.targets.indexOf(obj); if (index > -1) this.targets.splice(index, 1); this.hitsArray.forEach(function (item) { return item.receiver === obj && _this2.hitsArray.splice(_this2.hitsArray.indexOf(item), 1); }); this.actionsArray.forEach(function (item) { return item.receiver === obj && _this2.actionsArray.splice(_this2.actionsArray.indexOf(item), 1); }); Object.keys(this.hits).forEach(function (item) { return _this2.hits[item].receiver === obj && delete _this2.hits[item]; }); Object.keys(this.actions).forEach(function (item) { return _this2.actions[item].receiver === obj && delete _this2.actions[item]; }); Object.keys(this.hovered).forEach(function (item) { return _this2.hovered[item].receiver === obj && delete _this2.hovered[item]; }); }; _proto.getActions = function getActions() { return this.actionsArray; }; _proto.isHit = function isHit(obj) { return this.hitsArray.find(function (data) { if (obj instanceof THREE.Material) return data.material === obj;else return data.object.id === obj.id; }) !== undefined; }; _proto.isAction = function isAction(obj) { return this.actionsArray.find(function (item) { return item.object.id == obj.id; }); }; return Interaction; }(); export { Interaction as default };