UNPKG

awv3

Version:
887 lines (753 loc) 38.9 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = undefined; var _getIterator2 = require('babel-runtime/core-js/get-iterator'); var _getIterator3 = _interopRequireDefault(_getIterator2); var _values = require('babel-runtime/core-js/object/values'); var _values2 = _interopRequireDefault(_values); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _three = require('three'); var THREE = _interopRequireWildcard(_three); var _memoize = require('lodash/memoize'); var _memoize2 = _interopRequireDefault(_memoize); var _cloneDeep = require('lodash/cloneDeep'); var _cloneDeep2 = _interopRequireDefault(_cloneDeep); var _throttle = require('lodash/throttle'); var _throttle2 = _interopRequireDefault(_throttle); var _lifecycle = require('./lifecycle.js'); var _lifecycle2 = _interopRequireDefault(_lifecycle); var _helpers = require('./helpers'); var _connections = require('./store/connections'); var _globals = require('./store/globals'); var _plugins = require('./store/plugins'); var _error = require('../core/error'); var _base = require('../communication/base'); var _base2 = _interopRequireDefault(_base); 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 Connection manages a local or remote connection to a running ClassCAD instances. ClassCAD will then drive the tree-state and cause visual actions, models, meshes, movement, etc. In theory a ClassCAD instance is not needed, results could be fed statically using parse or stream. */ var Connection = function (_Lifecycle) { (0, _inherits3.default)(Connection, _Lifecycle); function Connection() { var session = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : (0, _error.halt)('connection must be initialized with a session'); var props = arguments[1]; (0, _classCallCheck3.default)(this, Connection); var _this = (0, _possibleConstructorReturn3.default)(this, (Connection.__proto__ || (0, _getPrototypeOf2.default)(Connection)).call(this, session, _connections.actions, function (state) { return state.connections[_this.id]; }, (0, _extends3.default)({ name: 'Part' }, props, { connected: false, activeFeature: undefined, defaultFeatureVisibility: false, undo: { count: 0, current: 0 }, messages: [], plugins: [], tree: { '1': { id: 1, name: '', class: '', parent: null }, root: 1 }, managed: false }))); _this.updateView = (0, _throttle2.default)(function () { var _this$pool$view$contr; var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this.session.options.updateView, _ref$focus = _ref.focus, focus = _ref$focus === undefined ? true : _ref$focus, _ref$zoom = _ref.zoom, zoom = _ref$zoom === undefined ? true : _ref$zoom, _ref$rotate = _ref.rotate, rotate = _ref$rotate === undefined ? false : _ref$rotate, _ref$layers = _ref.layers, layers = _ref$layers === undefined ? false : _ref$layers; _this.pool.view.updateBounds(); focus && _this.pool.view.controls.focus(); zoom && _this.pool.view.controls.zoom(); rotate && (_this$pool$view$contr = _this.pool.view.controls).rotate.apply(_this$pool$view$contr, (0, _toConsumableArray3.default)(rotate)); _this.pool.update(); layers && _this.session.showLayer(_this.session.layerNames); }, _this.session.options.throttle); _this._get = (0, _memoize2.default)(function (key) { var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _this.getState().tree; if (_this.store) { var obj = state[key]; if (obj) { obj = (0, _cloneDeep2.default)(state[key]); if (obj.children) obj.children = obj.children.map(function (item) { return _this._get(item, state); }); if (obj.members) { for (var _key in obj.members) { var member = obj.members[_key]; if (_key !== 'mateSystem' && member.type === 'id') { obj.members[_key] = _this._get(member.value, state); } else if (member.type === 'array') { _this._resolveArray(member.members, state); } } } } return obj; } }); _this.pool = new session.options.pool((0, _extends3.default)({ session: session, name: 'connection.pool.' + _this.name }, session.options.materials)); _this.primitives = {}; _this.waiting = {}; _this.featurePlugins = {}; _this.sequence = _promise2.default.resolve(); // Observe tree changes to clear cache _this.observe(function (state) { return state.tree; }, function () { return _this._get.cache.clear(); }); // Observe root _this.observe(function (state) { return state.tree.root; }, function (root) { return _this._observeLink(root); }); // Observe active feature _this.observe(function (state) { return state.activeFeature; }, function (feature, oldFeature) { if (oldFeature) { var data = _this.featurePlugins[oldFeature]; _this.store.dispatch(_plugins.actions.update(data.plugin.id, { enabled: false, collapsed: true })); if (!data.pluginPrototype.persistent) { _this._destroyFeatures(oldFeature); } } if (feature) { var _data = _this.featurePlugins[feature]; if (_data.pluginPrototype.persistent) { _this.store.dispatch(_plugins.actions.update(_data.plugin.id, { enabled: true, collapsed: false })); _this.activeFeaturePlugin = _data.plugin; } else { _this.activeFeaturePlugin = _this._instanciateFeature(feature); _this.store.dispatch(_plugins.actions.update(_this.activeFeaturePlugin.id, { enabled: true, collapsed: false })); } } }); // Connect to server if (_this.session.options.url && _this.session.options.protocol) { _this.connect(_this.session.options.url); } return _this; } (0, _createClass3.default)(Connection, [{ key: 'defer', value: function () { var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(func) { var _this2 = this; return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: return _context3.abrupt('return', new _promise2.default(function () { var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(resolve) { return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return _this2.sequence; case 2: requestIdleCallback((0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() { return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.t0 = resolve; _context.next = 3; return func(); case 3: _context.t1 = _context.sent; return _context.abrupt('return', (0, _context.t0)(_context.t1)); case 5: case 'end': return _context.stop(); } } }, _callee, _this2); }))); case 3: case 'end': return _context2.stop(); } } }, _callee2, _this2); })); return function (_x5) { return _ref3.apply(this, arguments); }; }())); case 1: case 'end': return _context3.stop(); } } }, _callee3, this); })); function defer(_x4) { return _ref2.apply(this, arguments); } return defer; }() }, { key: 'undo', value: function undo() { var factory = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.session.options.materials.factory; return this.store.dispatch(this.actions.request(this.id, undefined, factory, 'undo')); } }, { key: 'redo', value: function redo() { var factory = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.session.options.materials.factory; return this.store.dispatch(this.actions.request(this.id, undefined, factory, 'redo')); } }, { key: 'request', value: function request(command) { var factory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.session.options.materials.factory; return this.store.dispatch(this.actions.request(this.id, command, factory)); } }, { key: 'stream', value: function stream(url) { var factory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.session.options.materials.factory; return this.store.dispatch(this.actions.stream(this.id, url, factory)); } }, { key: 'parse', value: function parse(blob) { var factory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.session.options.materials.factory; return this.store.dispatch(this.actions.parse(this.id, blob, factory)); } }, { key: 'connect', value: function connect(url) { return this.store.dispatch(this.actions.connect(this.id, url, this.session.options.protocol)); } }, { key: 'setTree', value: function setTree(payload) { this.store.dispatch(_connections.actions.destroyTree(this.id)); this.store.dispatch(_connections.actions.setTree(this.id, payload)); } }, { key: 'patchTree', value: function patchTree(payload) { return this.store.dispatch(this.actions.patchTree(this.id, payload)); } }, { key: 'resolveTree', value: function resolveTree(args) { var _this3 = this; if (!args) return; args = Array.isArray(args) ? args : [args]; var result = args.map(function (key) { return _this3._get(key, _this3.getState().tree); }); return result; } }, { key: 'removePrimitives', value: function removePrimitives() { (0, _values2.default)(this.primitives).forEach(function (item) { return item.destroy(); }); this.primitives = {}; this.updateView(); } }, { key: '_observeLink', value: function _observeLink(id, parent, instance) { var _this4 = this; var tree = this.getState().tree; var object = tree[id]; switch (object.class) { case 'CC_Assembly': //console.log("observing", object.name) return this._observeAssembly(id, parent, instance); case 'CC_Part': case 'CC_SheetPart': var container = this._observePart(id, parent, instance); this.defer(function () { return _this4._observeFeatures(id, container); }); return container; } } }, { key: '_observeAssembly', value: function _observeAssembly(root) { var _this5 = this; var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.pool; var instance = arguments[2]; var instances = {}; var container = new this.session.options.objectPrototype({ session: this.session }); container.name = 'Assembly'; container.userData = { id: instance }; parent.add(container); this.observe( // selector function (state) { return (state.tree[root] || {}).instances; }, // onChange function () { var _ref5 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee4() { for (var _len = arguments.length, args = Array(_len), _key2 = 0; _key2 < _len; _key2++) { args[_key2] = arguments[_key2]; } var tree; return _regenerator2.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: tree = _this5.tree; _context4.next = 3; return _helpers.arrayDiff.apply(undefined, args.concat([function (newItems) { return newItems.forEach(function (item) { var instance = tree[item]; var link = undefined; var object = undefined; // Observe changes to it _this5.observe(function (state) { return state.tree[item]; }, function (instance) { // Links should be reactive as well if (instance.link !== link) { if (object) { object.destroy(); delete instances[instance.id]; } object = instances[item] = _this5._observeLink(instance.link, container, item); object.matrixAutoUpdate = false; link = instance.link; } var csys = instance.coordinateSystem; object.userData.name = instance.name; object.name = instance.name; object.visible = typeof instance.visible !== 'undefined' ? instance.visible : true; object.matrix = new THREE.Matrix4().makeBasis(new (Function.prototype.bind.apply(THREE.Vector3, [null].concat((0, _toConsumableArray3.default)(csys[1]))))(), new (Function.prototype.bind.apply(THREE.Vector3, [null].concat((0, _toConsumableArray3.default)(csys[2]))))(), new (Function.prototype.bind.apply(THREE.Vector3, [null].concat((0, _toConsumableArray3.default)(csys[3]))))()).setPosition(new (Function.prototype.bind.apply(THREE.Vector3, [null].concat((0, _toConsumableArray3.default)(csys[0]))))()); _this5.updateView(); //console.log(` moving instance ${instance.name} to ${JSON.stringify(csys[0])}`); }, { fireOnStart: true, unsubscribeOnUndefined: true }); }); }, function (deletedItems) { return deletedItems.forEach(function (item) { var instance = instances[item]; //console.log(` removing instance ${instance.name}`); delete instances[item]; return instance.destroy(); }); }])); case 3: _this5.updateView(); case 4: case 'end': return _context4.stop(); } } }, _callee4, _this5); })); return function () { return _ref5.apply(this, arguments); }; }(), // options { onRemove: function onRemove() { console.log('assembly is gone', container.name); (0, _values2.default)(instances).forEach(function (item) { return item.destroy(); }); instances = {}; container.destroy(); parent === _this5.pool && _this5.removePrimitives(); }, fireOnStart: true, unsubscribeOnUndefined: true }); return container; } }, { key: '_observePart', value: function _observePart(root) { var _this6 = this; var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.pool; var instance = arguments[2]; var clones = {}; var container = new this.session.options.objectPrototype({ session: this.session }); container.name = 'Part'; container.temporary = new THREE.Group(); container.temporary.name = 'Part.temporaray'; container.temporary.updateParentMaterials = false; container.userData = { id: instance }; container.add(container.temporary); parent.add(container); this.observe( // selector function (state) { return (state.tree[root] || {}).solids; }, // onChange function () { var _ref6 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee5() { for (var _len2 = arguments.length, args = Array(_len2), _key3 = 0; _key3 < _len2; _key3++) { args[_key3] = arguments[_key3]; } var part; return _regenerator2.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: part = _this6.tree[root]; _context5.next = 3; return _helpers.arrayDiff.apply(undefined, args.concat([function (newItems) { newItems.map(function (item) { var primitive = _this6.primitives[item]; if (!primitive) { // primitive is not yet known // Create bounds representation var mesh = void 0; if (part.min && part.max) { var min = part.min; var max = part.max; mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(max[0] - min[0], max[1] - min[1], max[2] - min[2]), new _this6.session.options.meshShader((0, _extends3.default)({ color: new THREE.Color('rgb(' + (part.color ? part.color.join(',') : '190, 190, 190') + ')') }, _this6.session.options.meshShaderOptions))); if (_this6.session.options.materials.shadows) { mesh.castShadow = true; mesh.receiveShadow = true; } mesh.position.set((max[0] + min[0]) / 2, (max[1] + min[1]) / 2, (max[2] + min[2]) / 2); container.reset(mesh).add(mesh); } // If none exists, create empty waiting list entry from item if (!_this6.waiting[item]) _this6.waiting[item] = []; // Register item on the waiting-list _this6.waiting[item].push(function (primitive) { // Delete bounds mesh && mesh.destroyAsync(); // Create real clone, finally createClone({ root: root, parent: parent, clones: clones, container: container, primitive: primitive, item: item }); }); } else createClone({ root: root, parent: parent, clones: clones, container: container, primitive: primitive, item: item }); }); _this6.updateView(); }, function (deletedItems) { return deletedItems.map(function (item) { var clone = clones[item]; // Remove clone from primitives var primitive = _this6.primitives[item]; if (primitive) primitive.references.splice(primitive.references.indexOf(clone), 1); delete clones[item]; return clone.destroyAsync(); }); }])); case 3: case 'end': return _context5.stop(); } } }, _callee5, _this6); })); return function () { return _ref6.apply(this, arguments); }; }(), // options { onRemove: function onRemove() { console.log('part is gone', container.name); (0, _values2.default)(clones).forEach(function (item) { return item.destroy(); }); clones = {}; container.destroy(); parent === _this6.pool && _this6.removePrimitives(); }, fireOnStart: true, unsubscribeOnUndefined: true }); return container; } }, { key: '_instanciateFeature', value: function _instanciateFeature(id, props) { var _featurePlugins$id = this.featurePlugins[id], parent = _featurePlugins$id.parent, feature = _featurePlugins$id.feature, persistent = _featurePlugins$id.persistent, pluginPrototype = _featurePlugins$id.pluginPrototype; // If activeSelection is on we must reset it !persistent && this.session.globals.activeSelection && this.store.dispatch(_globals.actions.setActiveSelection()); // Each plugin gets a distinct pool to draw into var pool = new THREE.Group(); pool.name = 'Instance'; pool.updateParentMaterials = false; pool.measurable = pluginPrototype.measurable; pool.name = feature.name; parent.add(pool); // Intanciate and link new plugin var plugin = new pluginPrototype(this.session, (0, _extends3.default)({ name: feature.name, feature: feature, pool: pool, connection: this }, props)); // Link plugins this.featurePlugins[id].plugin = plugin; this.store.dispatch(_connections.actions.linkPlugins(this.id, plugin.id)); return plugin; } }, { key: '_mapFeatures', value: function _mapFeatures(parent) { for (var _len3 = arguments.length, features = Array(_len3 > 1 ? _len3 - 1 : 0), _key4 = 1; _key4 < _len3; _key4++) { features[_key4 - 1] = arguments[_key4]; } var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = (0, _getIterator3.default)(features), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var id = _step.value; var feature = this.tree[id]; var type = feature.class; var pluginPrototype = this.session.featurePlugins[type]; if (!pluginPrototype && this.session.defaultFeaturePlugin) pluginPrototype = this.session.defaultFeaturePlugin; if (pluginPrototype) { // Map feature plugin this.featurePlugins[id] = { feature: feature, parent: parent.temporary, pluginPrototype: pluginPrototype, persistent: pluginPrototype.persistent }; if (pluginPrototype.persistent) { // Return persistent plugins this._instanciateFeature(id); } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } }, { key: '_unmapFeatures', value: function _unmapFeatures() { var _this7 = this; for (var _len4 = arguments.length, features = Array(_len4), _key5 = 0; _key5 < _len4; _key5++) { features[_key5] = arguments[_key5]; } this._destroyFeatures(features); features.forEach(function (id) { return delete _this7.featurePlugins[id]; }); } }, { key: '_destroyFeatures', value: function _destroyFeatures() { var _this8 = this; for (var _len5 = arguments.length, features = Array(_len5), _key6 = 0; _key6 < _len5; _key6++) { features[_key6] = arguments[_key6]; } var plugins = features.map(function (id) { return _this8.featurePlugins[id]; }).filter(function (data) { return data && data.plugin; }).map(function (data) { return data.plugin.id; }); if (plugins.length > 0) { this.store.dispatch(_connections.actions.unlinkPlugins(this.id, plugins)); } features.forEach(function (id) { // Find real plugin class var _ref7 = _this8.featurePlugins[id] || {}, plugin = _ref7.plugin, parent = _ref7.parent, persistent = _ref7.persistent; if (plugin) { if (!persistent) { delete _this8.featurePlugins[id].plugin; } parent.remove(plugin.pool); _this8.defer(function () { return _this8.store.dispatch(_plugins.actions.unregister(plugin.id)); }); } }); } }, { key: '_observeFeatures', value: function _observeFeatures(root) { var _this9 = this; var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.pool; //console.log("observeFeatures...") return this.observe( // selector function (state) { return (state.tree[root] || {}).features; }, // onChange function () { for (var _len6 = arguments.length, args = Array(_len6), _key7 = 0; _key7 < _len6; _key7++) { args[_key7] = arguments[_key7]; } _helpers.arrayDiff.apply(undefined, args.concat([function (newItems) { return _this9._mapFeatures.apply(_this9, [parent].concat((0, _toConsumableArray3.default)(newItems))); }, function (deletedItems) { return _this9._unmapFeatures.apply(_this9, (0, _toConsumableArray3.default)(deletedItems)); }])); }, // options { fireOnStart: true, unsubscribeOnUndefined: true }); } }, { key: '_resolveArray', value: function _resolveArray(array, state) { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = (0, _getIterator3.default)(array), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var member = _step2.value; if (member.type === 'id') { array[array.indexOf(member)] = this._get(member.value, state); } else if (member.type === 'array') { this._resolveArray(member, state); } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } }, { key: '__onDestroyed', value: function __onDestroyed() { var _this10 = this; (0, _values2.default)(this.primitives).forEach(function (item) { return item.destroy(); }); this.primitives = {}; (0, _values2.default)(this.session.plugins).forEach(function (plugin) { return plugin.connection === _this10.id && _this10.store.dispatch(_plugins.actions.unregister(plugin.id)); }); if (this.session.globals.activeConnection === this.id) { this.session.dispatch(_globals.actions.setActiveConnection()); } this.socket && this.socket.disconnect(); } }]); return Connection; }((0, _lifecycle2.default)(_base2.default, false)); exports.default = Connection; function createClone(_ref8) { var root = _ref8.root, parent = _ref8.parent, clones = _ref8.clones, container = _ref8.container, primitive = _ref8.primitive, item = _ref8.item; var clone = clones[item] = primitive.clone(); primitive.references.push(clone); // Calculate new deep ID var array = [root]; parent = container; while (parent && parent.userData && parent.userData.id) { array.push(parent.userData.id); parent = parent.parent; } array = array.reverse(); // deep clone materials; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = (0, _getIterator3.default)(clone.children.keys()), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var child = _step3.value; var c = clone.children[child]; var p = primitive.children[child]; if (c.material) { var isMultiMaterial = Array.isArray(c.material); if (isMultiMaterial) { for (var i = 0, l = c.material.length; i < l; i++) { var pMaterial = p.material[i]; var cMaterial = c.material[i] = pMaterial.clone(true); cMaterial.meta = (0, _extends3.default)({}, pMaterial.meta, { originalId: pMaterial.meta.id, id: [].concat((0, _toConsumableArray3.default)(array), [pMaterial.meta.id]).join(',') }); } } else { c.material = p.material.clone(true); c.material.meta = (0, _extends3.default)({}, p.material.meta); } } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } return container.reset(clone).add(clone); }