UNPKG

awv3

Version:
645 lines (512 loc) 25.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _getIterator2 = require('babel-runtime/core-js/get-iterator'); var _getIterator3 = _interopRequireDefault(_getIterator2); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _expressions = require('./expressions'); var _statements = require('./statements'); var _statements2 = _interopRequireDefault(_statements); var _sketcher = require('../sketcher'); var _sketcher2 = _interopRequireDefault(_sketcher); var _point = require('../sketcher/graphics/point'); var _point2 = _interopRequireDefault(_point); var _line = require('../sketcher/graphics/line'); var _line2 = _interopRequireDefault(_line); var _arc = require('../sketcher/graphics/arc'); var _arc2 = _interopRequireDefault(_arc); var _object = require('../../three/object3'); var _object2 = _interopRequireDefault(_object); var _three = require('three'); var THREE = _interopRequireWildcard(_three); 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 }; } var Sketch = function () { function Sketch() { (0, _classCallCheck3.default)(this, Sketch); } (0, _createClass3.default)(Sketch, [{ key: 'getPart', value: function getPart() { return this.parent.parent; // Part.SketchSet.Sketch } // Physically add objects to the sketch (in contrast to addAuxObject) // If some objects were previously added with addAuxObject, automatically remove them from aux objects // possible options: // onServer (default: true) - whether to send commands to the server. // onClient (default: true) - whether to add objects to children // autoconstraint (default: false) - if true, then implied constraints are generated if neccessary. // updateSketch (default: false) - whether to update sketch state for the whole sketch, not only for objets. Pass true when adding constraints. }, { key: 'addToSketch', value: function addToSketch(objects) { var _this = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (options.onServer === undefined) options.onServer = true; if (options.onClient === undefined) options.onClient = true; if (options.updateSketch === undefined) options.updateSketch = false; if (options.autoconstraint === undefined) options.autoconstraint = false; objects = [].concat(objects); var sketcher = this.sketcher; var view = sketcher.view; if (objects.length === 0) return _promise2.default.resolve(); if (options.onClient) this.add.apply(this, objects); // must be done before server command so that parseObjectTree can find the objects in children var afterServer = function afterServer() { objects.forEach(function (obj) { if (_this.sketchObjects.has(obj)) return; _this.sketchObjects.add(obj); _this.emit('SketchAdded', obj); }); if (options.autoconstraint && sketcher.autoconstraintIncremental) { //generate implied constraints for the objects just drawn by user var autogen = new ConstraintGenerator(_this); var constraints = autogen.generateImpliedConstraints(Sketch.ForObjectsWithChildren(objects)); if (constraints.length > 0) return _this.addToSketch(constraints, { updateSketch: true }); } }; // add objects to the sketch on the server and, if successful, on the client if (options.onServer) { var statements = objects.map(function (object) { return object.prepareAddOnServer(_this); }); /* if (options.updateSketch) statements.push(this.updateFromServer());*/ return _statements2.default.all(statements).execute(sketcher.socket).then(afterServer); } return _promise2.default.resolve(afterServer()); } // Remove objects previously added with addToSketch }, { key: 'removeFromSketch', value: function () { var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(objects) { var _this2 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var sketcher, view, objectsCh, relatedConstraints, statements, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, obj, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, _obj; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (options.onServer === undefined) options.onServer = true; if (options.onClient === undefined) options.onClient = true; if (options.updateSketch === undefined) options.updateSketch = false; objects = [].concat(objects); sketcher = this.sketcher; view = sketcher.view; //add related constraints for removal (before objects) objectsCh = Sketch.ForObjectsWithChildren(objects); relatedConstraints = this.getConstraintsOnSketch(objectsCh); objects = relatedConstraints.concat(objects.filter(function (obj) { return relatedConstraints.indexOf(obj) === -1; })); objectsCh = relatedConstraints.concat(objectsCh.filter(function (obj) { return relatedConstraints.indexOf(obj) === -1; })); // remove objects from the sketch on the server and, if successful, on the client if (!options.onServer) { _context.next = 15; break; } statements = objects.map(function (object) { return object.prepareRemoveOnServer(_this2); }); if (options.updateSketch) statements.push(this.updateFromServer()); _context.next = 15; return _statements2.default.all(statements).execute(sketcher.socket); case 15: if (!options.onClient) { _context.next = 44; break; } _iteratorNormalCompletion = true; _didIteratorError = false; _iteratorError = undefined; _context.prev = 19; _iterator = (0, _getIterator3.default)(objects); case 21: if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { _context.next = 30; break; } obj = _step.value; this.remove(obj); _context.next = 26; return this.emit('SketchRemoved', obj); case 26: //note: removed object is completely destroyed obj.destroy(); case 27: _iteratorNormalCompletion = true; _context.next = 21; break; case 30: _context.next = 36; break; case 32: _context.prev = 32; _context.t0 = _context['catch'](19); _didIteratorError = true; _iteratorError = _context.t0; case 36: _context.prev = 36; _context.prev = 37; if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } case 39: _context.prev = 39; if (!_didIteratorError) { _context.next = 42; break; } throw _iteratorError; case 42: return _context.finish(39); case 43: return _context.finish(36); case 44: _iteratorNormalCompletion2 = true; _didIteratorError2 = false; _iteratorError2 = undefined; _context.prev = 47; for (_iterator2 = (0, _getIterator3.default)(objects); !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { _obj = _step2.value; this.sketchObjects.delete(_obj); }_context.next = 55; break; case 51: _context.prev = 51; _context.t1 = _context['catch'](47); _didIteratorError2 = true; _iteratorError2 = _context.t1; case 55: _context.prev = 55; _context.prev = 56; if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } case 58: _context.prev = 58; if (!_didIteratorError2) { _context.next = 61; break; } throw _iteratorError2; case 61: return _context.finish(58); case 62: return _context.finish(55); case 63: case 'end': return _context.stop(); } } }, _callee, this, [[19, 32, 36, 44], [37,, 39, 43], [47, 51, 55, 63], [56,, 58, 62]]); })); function removeFromSketch(_x2, _x3) { return _ref.apply(this, arguments); } return removeFromSketch; }() // Duplicate objects }, { key: 'copyObjects', value: function copyObjects(objects, translate, rotate) { var _this3 = this; var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; var statement = (0, _expressions.Return)((0, _expressions.CopyObjects)(this, objects, translate, rotate)); // TODO: parsing objects returned from DuplicateObjects would be more efficient than // updating the whole sketch. chooseTool is needed to add interactions to the new objects return statement.and(this.updateFromServer()).then(function () { return _this3.sketcher.chooseTool('empty'); }); } // Return list of objects added with addToSketch (but not addAuxObject) }, { key: 'getObjectsOnSketch', value: function getObjectsOnSketch() { var _this4 = this; return this.children.filter(function (c) { return _this4.sketchObjects.has(c); }); } // Return list of constraints related to passed object or objects, // or list of all constraints, if 'objects' parameter is undefined }, { key: 'getConstraintsOnSketch', value: function getConstraintsOnSketch(objects) { if (objects) objects = [].concat(objects); var inObjectsList = function inObjectsList(elem) { return !objects || objects.indexOf(elem) !== -1; }; var isRelatedToObjects = function isRelatedToObjects(constr) { return constr.args.some(inObjectsList); }; var constraintsList = this.getObjectsOnSketch().filter(function (child) { return child instanceof Constraint; }).filter(isRelatedToObjects); return constraintsList; } // Return ancestor of the object that is directly lying on the sketch }, { key: 'getAncestorOnSketch', value: function getAncestorOnSketch(object) { var _this5 = this; object.traverseAncestors(function (ancestor) { if (ancestor.parent === _this5) object = ancestor; }); return object; } // Return true if object was added with addToSketch }, { key: 'isOnSketch', value: function isOnSketch(object) { return this.sketchObjects.has(object); } // Add auxiliary objects which shouldn't physically be on the sketch // These objects will be displayed in sketch coordinates but not returned from getObjectsOnSketch // Example of such objects: sketch's grid, preview line segment for polyline being created }, { key: 'addAuxObject', value: function addAuxObject(objects /*, options*/) { var _this6 = this; objects = [].concat(objects); var view = this.sketcher.view; // we can't automatically remove objects from the sketch because // it's an asynchronous action; this function should be synchronous if (objects.some(function (object) { return this.isOnSketch(object); }, this)) throw "Sketch.addAuxObject: can't add object on sketch. Remove it first"; objects.forEach(function (obj) { _this6.add(obj); }); } // Remove objects previously added with addAuxObject }, { key: 'removeAuxObject', value: function removeAuxObject(objects /*, options*/) { var _this7 = this; objects = [].concat(objects); var view = this.sketcher.view; objects.forEach(function (obj) { _this7.remove(obj); //note: object is completely disposed (not usable afterwards) obj.destroy(); }); } }, { key: 'showBox', value: function showBox() { this.addAuxObject(this.__box); } }, { key: 'hideBox', value: function hideBox() { this.removeAuxObject(this.__box); } }, { key: 'updateBox', value: function updateBox() { var _this8 = this; this.updateMatrixWorld(); // bbox is bounding box in local to sketch coordinates var bbox = new THREE.Box3(); var v1 = new THREE.Vector3(); this.getObjectsOnSketch().forEach(function (obj) { return obj.traverseVisible(function (node) { if (!(node.geometry instanceof THREE.Geometry)) return; node.geometry.vertices.forEach(function (vertex) { // translate vertex coordinates from local-to-node to local-to-sketch v1.copy(vertex); node.localToWorld(v1); _this8.worldToLocal(v1); bbox.expandByPoint(v1); }); }); }); var thisBox = this.__box; thisBox.material = new THREE.MeshPhongMaterial({ color: 0xffffff, emissive: 0xffffff, specular: 0xffffff, shininess: 1, transparent: true, opacity: 0.3, depthWrite: false }); if (bbox.isEmpty()) { // (nothing on sketch) thisBox.scale.set(1e-3, 1e-3, 1e-3); thisBox.position.set(0, 0, 0); } else { //make box flat bbox.min.z = -1e-3; bbox.max.z = 1e-3; // !nb: updates thisBox from bbox bbox.size(thisBox.scale); bbox.center(thisBox.position); } } }, { key: 'showDimensions', value: function showDimensions() { this.addAuxObject(this.__dimensions); } }, { key: 'hideDimensions', value: function hideDimensions() { this.removeAuxObject(this.__dimensions); } // intercept graphical objects created on the server }, { key: 'updateDimensionsFactory', value: function updateDimensionsFactory(input, result) { var data = input.data; var worldToLocal = new THREE.Matrix4().getInverse(this.matrix); switch (input.type) { case 'Cone': //transform to sketch coordinates var pos = new THREE.Vector3().fromArray(data.position).applyMatrix4(worldToLocal); var dir = new THREE.Vector3().fromArray(data.axis).transformDirection(worldToLocal); var height = dir.length(); var diam = Math.max(data.diameters[0], data.diameters[1]); //create two-sided arrow var geom = new THREE.Geometry(); geom.vertices.push(new THREE.Vector3(height, -diam / 2, 0), new THREE.Vector3(height, diam / 2, 0), new THREE.Vector3(0, 0, 0)); geom.faces.push(new THREE.Face3(0, 1, 2), new THREE.Face3(0, 2, 1)); geom.computeFaceNormals(); var mesh = new THREE.Mesh(geom, new THREE.MeshBasicMaterial({ color: 0x7fff7f })); //set position and orientation of arrow mesh.position.copy(pos); mesh.quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), dir); result.push(mesh); break; case 'Text': if (data.text == '@') break; //no idea why this trash comes //note: only following types of text are properly supported: // textType = 1 (screen-oriented, fixed-sized text) // alignment = 0 (left/baseline-aligned text) //create 3D text var params = { size: 1, height: 0, font: this.sketcher.font }; var geom = new THREE.TextGeometry(data.text, params); geom.computeBoundingBox(); //for debugging var mesh = new THREE.Mesh(geom, new THREE.MeshBasicMaterial({ color: 0x3fffbf })); //set position in sketch coordinates var obj = new THREE.Object3D(); //obj.fullName = factoryPart.name; //no idea what it is... obj.mesh = mesh; obj.add(mesh); obj.position.fromArray(data.position).applyMatrix4(worldToLocal); //add pixel-based sizing obj.setGeomSizes = function (sizes) { var s = sizes[0]; this.mesh.scale.set(s, s, s); }; //register automatic updates var view = this.sketcher.view; result.push(obj); break; case 'Line': data.geometry.applyMatrix(worldToLocal); data.material = new THREE.MeshBasicMaterial({ color: 0x7fff7f }); result.push(data); break; } } }, { key: 'showConstraints', value: function showConstraints(obj) { var constraints = this.getConstraintsOnSketch(obj); if (constraints.length === 0) return; obj.constraintsSubstrate.visible = true; this.updateConstraints(obj); constraints.forEach(function (child) { return child.show(); }); } }, { key: 'hideConstraints', value: function hideConstraints() { var constraints = this.getConstraintsOnSketch(); constraints.forEach(function (child) { child.args.forEach(function (arg) { arg.hovered = false; }); child.hide(); }); this.getObjectsOnSketch().forEach(function (obj) { Sketch.ForObjectsWithChildren(obj, function (arg) { if (arg.constraintsSubstrate) arg.constraintsSubstrate.visible = false; }); }); } }, { key: 'updateConstraints', value: function updateConstraints(obj) { var substrate = obj.constraintsSubstrate; var constraints = this.getConstraintsOnSketch(obj); if (constraints.length === 0) { obj.constraintsSubstrate.visible = false; obj.interact.unhover && obj.interact.unhover(); return 0; } var len = constraints.length; var scale = constraints[0].mesh.scale.x; var size = 1.2 * scale; substrate.scale.set(size * constraints.length, size, Math.min(size, 1)); var pos = obj.getSubstratePosition(substrate.scale.x, size); substrate.position.set(pos.x, pos.y, -1); var mostLeftX = substrate.position.x + obj.position.x - substrate.scale.x / 2; var middleY = substrate.position.y + obj.position.y; for (var i = 0; i < len; ++i) { constraints[i].position.set(mostLeftX + (i + 0.5) * size, middleY, 0); } } // for loop over object or objects, including child points // if no callback specified, then all the objects are returned in array }], [{ key: 'FindSketchOf', value: function FindSketchOf(obj) { while (obj) { if (obj instanceof Sketch) return obj; obj = obj.parent; } } }, { key: 'FindSketchSetOf', value: function FindSketchSetOf(obj) { var result; obj.traverseAncestors(function (s) { result = result || s.members.SketchSet; }); return result; } }, { key: 'ForObjectsWithChildren', value: function ForObjectsWithChildren(objs, callback) { var result = undefined; if (!callback) { result = []; callback = function callback(obj) { return result.push(obj); }; } objs = [].concat(objs); objs.forEach(function (obj) { if (!obj) return; callback(obj); if (obj instanceof _point2.default) return; if (obj.points) obj.points.forEach(callback); if (obj.centerPoint) callback(obj.centerPoint); }); return result; } }]); return Sketch; }(); exports.default = Sketch;