awv3
Version:
⚡ AWV3 embedded CAD
623 lines (514 loc) • 27.7 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ObjectSelector = undefined;
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _three = require('three');
var THREE = _interopRequireWildcard(_three);
var _object = require('../three/object3');
var _object2 = _interopRequireDefault(_object);
var _orbit = require('../controls/orbit');
var _orbit2 = _interopRequireDefault(_orbit);
var _perspective = require('../three/perspective');
var _perspective2 = _interopRequireDefault(_perspective);
var _region = require('../three/region');
var _region2 = _interopRequireDefault(_region);
var _elements = require('./store/elements');
var _helpers = require('./helpers');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @class ObjectSelector is used to select whole objects in the view
* (Filtersettings: Object).
* includes single selection as well as rubberband selection. Object selection
* is based on the object's id only and works without userData and meta-information.
*/
var ObjectSelector = exports.ObjectSelector = function () {
function ObjectSelector(session, options) {
var _this = this;
(0, _classCallCheck3.default)(this, ObjectSelector);
this.session = session;
// Wait until the sessions pool has been added into the view (happens in <App/>)
this.session.pool.viewFound().then(function (view) {
return _this.view = view;
});
// the currently active selecion-element
this.element = undefined;
// stores the selected objects
this.selectedSet = new _set2.default();
// call unobserve when deactivated
this.unobserve = undefined;
}
/**
* Deactivates the object-selector. Observation of selection-element is stopped.
* Rubberband selection handlers are removed.
*/
(0, _createClass3.default)(ObjectSelector, [{
key: 'deactivate',
value: function deactivate() {
var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.element;
this.removeAll(false);
this.shiftHandler && document.removeEventListener('keydown', this.shiftHandler);
this.shiftHandler = undefined;
this.element = undefined;
this.unobserve && this.unobserve();
}
/**
* Activates the object-selector. The Given selection-element is observed in
* order to register changes when click-deleting labels. Handlers for
* rubberband selection are created.
*/
}, {
key: 'activate',
value: function activate() {
var _this2 = this;
var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.element;
this.unobserve = this.session.observe(function (state) {
return state.elements[element.id].children;
}, function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_helpers.arrayDiff.apply(undefined, args.concat([function (newItems) {}, function (deletedItems) {
var candidates = [];
var _loop = function _loop(i) {
_this2.selectedSet.forEach(function (object) {
if (deletedItems[i] === object.id) {
candidates.push(object);
}
});
};
for (var i = 0; i < deletedItems.length; i++) {
_loop(i);
}
candidates.forEach(function (object) {
return _this2.remove({ object: object });
});
}]));
});
this.element = element;
this.view.interaction.filter = [this.session.pool];
// restore previously selected objects
if (this.element.children.length > 0) {
this.session.pool.traverse(function (obj) {
if (_this2.element.children.indexOf(obj.id) > -1) {
_this2.session.store.dispatch(_elements.actions.removeChild(_this2.element.id, obj.id));
_this2.add({ object: obj });
}
});
}
// update materials
this.session.pool.traverse(function (item) {
return item.updateMaterials();
});
// SHIFT KEY selection handler
var candidates = [];
this.shiftHandler = function (event) {
if (!_this2.shiftHandler.handled && event.keyCode === 16) {
(function () {
_this2.shiftHandler.handled = true;
_this2.view.input.debounce = false;
_this2.view.controls.enabled = false;
_this2.view.interaction.enabled = false;
var boundingBoxes2D = [];
_this2.session.pool.traverse(function (item) {
//project bounding box to view coordinates
if (item.visible && item.interactive && item.geometry) {
item.updateMatrixWorld(true);
item.geometry.computeBoundingBox();
var minPt = item.geometry.boundingBox.min.clone(); //TODO: get all 8 points
var maxPt = item.geometry.boundingBox.max.clone(); //TODO: get all 8 points
//project to view-coordinates
var p1 = _this2.view.getPoint2(minPt);
var p2 = _this2.view.getPoint2(maxPt);
//bounding box in 2D
var bounds2D = new THREE.Box2();
bounds2D.setFromPoints([p1, p2]);
bounds2D.__object = item;
boundingBoxes2D.push(bounds2D);
}
});
//draw rectangle
var nearDistance = _this2.view.camera.near;
var farDistance = _this2.view.camera.far;
_this2.view.hud = true;
_this2.view.controlsHud = undefined;
_this2.view.cameraHud = new _perspective2.default({ near: nearDistance, far: farDistance, fov: _this2.view.camera.fov });
_this2.view.measure(true);
var modelBounds = _this2.view.scene.updateBounds().bounds;
var geom = new THREE.PlaneGeometry(1, 1);
var box = new THREE.Mesh(geom, new THREE.MeshBasicMaterial({ transparent: true, opacity: 0.05, color: new THREE.Color(0) }));
box.renderOrder = -1;
_this2.view.sceneHud.add(box);
var clickDown = void 0,
mousePos = void 0,
rubberBandLine = void 0,
clickHud = void 0;
var handler = function handler(event) {
var _ret3 = function () {
switch (event.type) {
case 'mousedown':
clickDown = new THREE.Vector2(event.offsetX, event.offsetY);
mousePos = new THREE.Vector2(event.offsetX + 11, event.offsetY + 1);
clickHud = _this2.view.getPoint3({ x: event.offsetX, y: event.offsetY }, _this2.view.cameraHud, 0);
box.position.copy(clickHud);
break;
case 'mousemove':
if (!clickDown) return {
v: void 0
};
//update rectangle
var tempPoint = _this2.view.getPoint3({ x: event.offsetX, y: event.offsetY }, _this2.view.cameraHud, 0);
var delta = tempPoint.sub(clickHud);
var width = Math.abs(delta.x);
var height = Math.abs(delta.y);
var halfHeight = height / 2;
var halfWidth = width / 2;
var halfDeltaX = delta.x / 2;
var halfDeltaY = delta.y / 2;
geom.vertices[0].set(-halfWidth + halfDeltaX, halfHeight + halfDeltaY, 0);
geom.vertices[1].set(width - halfWidth + halfDeltaX, halfHeight + halfDeltaY, 0);
geom.vertices[2].set(-halfWidth + halfDeltaX, -(height - halfHeight) + halfDeltaY, 0);
geom.vertices[3].set(width - halfWidth + halfDeltaX, -(height - halfHeight) + halfDeltaY, 0);
geom.verticesNeedUpdate = true;
mousePos = new THREE.Vector2(event.offsetX, event.offsetY);
//check intersection with rectangle in display-coordinates
var rubberBandRectangle = new THREE.Box2();
rubberBandRectangle.setFromPoints([clickDown, mousePos]);
var newCandidates = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3.default)(boundingBoxes2D), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _box = _step.value;
if (rubberBandRectangle.containsBox(_box)) {
// create new object identical to raycast-hit
newCandidates.push({
distance: 0,
point: undefined,
face: undefined,
faceIndex: undefined,
indices: undefined,
object: _box.__object
});
}
}
// Remove items not present any longer
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _getIterator3.default)(candidates), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var item = _step2.value;
var found = false;
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = (0, _getIterator3.default)(newCandidates), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var newItem = _step4.value;
if (item.object.id === newItem.object.id) {
found = true;
break;
}
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
if (!found) {
_this2.remove(item, false);
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
candidates = newCandidates;
// Add new items, but only if they aren't known yet
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = (0, _getIterator3.default)(candidates), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var _item = _step3.value;
_this2.add(_item, false);
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
_this2.view.invalidate();
break;
case 'mouseup':
box && box.destroy();
var tempIds = [];
candidates.forEach(function (item) {
return tempIds.push(item.object.id);
});
clickDown = undefined;
if (rubberBandLine != undefined) {
_this2.view.scene.remove(rubberBandLine);
rubberBandLine = undefined;
}
// Update UI after mouse-up
_this2.session.store.dispatch(_elements.actions.update(_this2.element.id, { children: candidates.map(function (item) {
return item.material.meta.id;
}) }));
break;
}
}();
if ((typeof _ret3 === 'undefined' ? 'undefined' : (0, _typeof3.default)(_ret3)) === "object") return _ret3.v;
};
_this2.view.input.on(['mousedown', 'mousemove', 'mouseup'], handler);
_this2.tempHandler = function () {
box && box.destroy();
_this2.shiftHandler.handled = false;
_this2.view.input.removeListener(['mousedown', 'mousemove', 'mouseup'], handler);
document.removeEventListener('keyup', _this2.tempHandler);
_this2.view.input.debounce = true;
_this2.view.controls.enabled = true;
_this2.view.interaction.enabled = true;
_this2.view.scene.setRenderOrder();
};
document.addEventListener('keyup', _this2.tempHandler);
})();
}
};
this.shiftHandler.handled = false;
document.addEventListener('keydown', this.shiftHandler);
}
/**
* Add object to the set of selected elements
* @param {RayCast-Hit} event - Object generated by the raycaster including the
* hit object, material and meta-information
*/
}, {
key: 'add',
value: function add(event) {
var notify = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
if (!this.isSelected(event.object)) {
this.select(event.object);
this.selectedSet.add(event.object);
notify && this.session.store.dispatch(_elements.actions.addChild(this.element.id, event.object.id));
}
return event;
}
/**
* Remove object from the set of selected elements
* @param {RayCast-Hit} event - Object generated by the raycaster including the
* hit object, material and meta-information
*/
}, {
key: 'remove',
value: function remove(event) {
var notify = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
if (this.isSelected(event.object)) {
this.unselect(event.object);
this.selectedSet.delete(event.object);
notify && this.session.store.dispatch(_elements.actions.removeChild(this.element.id, event.object.id));
}
}
/**
* Remove all items (three object) from the set of selected elements
* @param {Boolean} keepLocals - If true, selected ids are kept within the selection-element
*/
}, {
key: 'removeAll',
value: function removeAll() {
var _this3 = this;
var removeElements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
this.selectedSet.forEach(function (object) {
return _this3.unselect(object);
});
this.selectedSet.clear();
if (removeElements) {
this.session.store.dispatch(_elements.actions.removeAllChilds(this.element.id));
}
}
/**
* Called by selector when event is triggered.
*/
}, {
key: 'hover',
value: function hover(event) {
this.session.pool.view.setCursor('pointer');
if (event.object.materials && !this.isSelected(event.object)) {
var anim = event.object.animate({ materials: { meshes: [{ color: new THREE.Color(0x28d79f), opacity: 1 }] } });
if (event.object.__origProps === undefined) {
event.object.__origProps = anim.getProperties();
}
anim.start(0);
}
}
/**
* Called by selector when event is triggered.
*/
}, {
key: 'unhover',
value: function unhover(event) {
if (event.object.materials && event.object.__origProps && !this.isSelected(event.object)) {
event.object.animate(event.object.__origProps).start(500);
}
}
/**
* Highlight the selected object. Store original material for unhighlight.
*/
}, {
key: 'select',
value: function select(object) {
if (object.materials) {
var anim = object.animate({ materials: { meshes: [{ color: new THREE.Color(0xc23369), opacity: 1 }] } });
anim.start(500);
}
}
/**
* Unighlight the object using hover material.
*/
}, {
key: 'unselect',
value: function unselect(object) {
if (this.view.interaction.hitsArray.length && object.materials) {
object.animate({ materials: { meshes: [{ color: new THREE.Color(0x28d79f), opacity: 1 }] } }).start(0);
} else if (object.materials && object.__origProps) {
object.animate(object.__origProps).start(0);
}
}
/**
* Called by selector when event is triggered.
*/
}, {
key: 'clicked',
value: function clicked(event) {
if (this.shiftHandler.handled) return;
if (this.isSelected(event.object)) {
this.remove(event);
} else {
this.add(event);
}
}
/**
* Called by selector when event is triggered.
*/
}, {
key: 'missed',
value: function missed(event) {
this.removeAll(true);
}
/**
* Called by selector when event is triggered.
*/
}, {
key: 'rendered',
value: function rendered(event) {}
/**
* Check if object is already selected
* @return TRUE if selected, FALSE otherwise
*/
}, {
key: 'isSelected',
value: function isSelected(object) {
return this.selectedSet.has(object);
}
/**
* Returns the selected ids in an array
* @return selectedIds - Array with the selected ids
*/
}, {
key: 'getSelectedIds',
value: function getSelectedIds() {
var iter = this.selectedSet.values();
var selectedIds = [];
var item = iter.next();
while (item.value !== undefined) {
selectedIds.push(item.id);
item = iter.next();
}
return selectedIds;
}
/**
* Returns the selected elements in an array
* @return selectedElements - Array with the selected elements
*/
}, {
key: 'getSelectedElements',
value: function getSelectedElements() {
var iter = this.selectedSet.values();
var selectedElements = [];
var item = iter.next();
while (item.value !== undefined) {
selectedElements.push(item.value);
item = iter.next();
}
return selectedElements;
}
/**
* Removes the given elements from the current selection.
* @param {array} elements - elements to be removed from the selection.
*/
}, {
key: 'unselectElements',
value: function unselectElements(elements) {
var _this4 = this;
elements.forEach(function (element) {
return _this4.remove({ object: element });
});
}
}]);
return ObjectSelector;
}();