awv3
Version:
⚡ AWV3 embedded CAD
396 lines (315 loc) • 13.7 kB
JavaScript
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 };