UNPKG

awv3

Version:
759 lines (625 loc) 32.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleResult = exports.default = undefined; var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); var _getIterator2 = require('babel-runtime/core-js/get-iterator'); var _getIterator3 = _interopRequireDefault(_getIterator2); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var handleResult = exports.handleResult = function () { var _ref5 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee6() { var _this3 = this; var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Error.log('Context undefined'); var object = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Error.log('Object undefined'); var promise; return _regenerator2.default.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: promise = new _promise2.default(function () { var _ref6 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee5(resolve) { var length, core, result, tempResolve, results, json; return _regenerator2.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: if (object.type === 'Buffer' && !!object.data) { // Node Buffer object = Uint8Array.from(object.data); } if (object instanceof Uint8Array) { // Wrap binary data into json Blob object = { command: 'Blob', type: 'Binary', data: object }; } if (typeof object === 'string' || object instanceof String) { // Plain text package length = object.length; object = JSON.parse(object); context.bytes += length; if (object.command !== 'Blob') context.bytesUncompressed += length; } if (!Array.isArray(object)) { _context5.next = 8; break; } _context5.next = 6; return _promise2.default.all(object.map(function (item) { return handleResult(context, item); })); case 6: _context5.next = 30; break; case 8: if (!(object.command === 'Endpoint')) { _context5.next = 12; break; } // Scaled endpoints context.results.push({ command: 'Result', from: 'ip', result: object }); _context5.next = 30; break; case 12: if (!(object.command === 'Blob')) { _context5.next = 20; break; } // Pass options to worker object.options = { materials: context.options.materials }; // Process package in worker threads core = _unpack2.default.getFreeCore(); _context5.next = 17; return core.post(object, function (data) { if (context.options.materials.lazy) requestAnimationFrame(function () { return parseGeometry(data, context); });else parseGeometry(data, context); }); case 17: result = _context5.sent; _context5.next = 30; break; case 20: if (!(context.resolve && object.command === 'Result' && object.from === 'EndFrame' && object.transactionID === context.id)) { _context5.next = 29; break; } // EndFrames are valid only for transactions that have explicit resolves marked in their respective contexts // Everything else will be resolved manually through context.promises tempResolve = context.resolve; _context5.next = 24; return _promise2.default.all(context.promises); case 24: results = _context5.sent; context = mergeContext(context); tempResolve(context); _context5.next = 30; break; case 29: if (object.command === 'Result' && object.from !== 'BeginFrame' && object.from !== 'EndFrame') { // Decode result, it *should* be JSON try { json = JSON.parse(object.result); object.result = json; } catch (e) {} context.results.push(object); } else if (object.command === 'Patch') { context.patches = [].concat((0, _toConsumableArray3.default)(context.patches), (0, _toConsumableArray3.default)(object.ops)); } else if (object.command === 'ErrorMessage') { // ClassCAD error messages context.errors.push(object.attributes); console.warn('ClassCAD > State: ' + object.attributes.errorState + ', Code: ' + object.attributes.errorCode + ', Message: ' + object.attributes.errorMessage); } case 30: resolve(context); case 31: case 'end': return _context5.stop(); } } }, _callee5, _this3); })); return function (_x14) { return _ref6.apply(this, arguments); }; }()); context.promises.push(promise); _context6.next = 4; return promise; case 4: return _context6.abrupt('return', _context6.sent); case 5: case 'end': return _context6.stop(); } } }, _callee6, this); })); return function handleResult() { return _ref5.apply(this, arguments); }; }(); exports.createContext = createContext; exports.mergeContext = mergeContext; exports.parseGeometry = parseGeometry; var _three = require('three'); var THREE = _interopRequireWildcard(_three); var _uuidV = require('uuid-v4'); var _uuidV2 = _interopRequireDefault(_uuidV); var _error = require('./error'); var Error = _interopRequireWildcard(_error); var _helpers = require('./helpers'); var _unpack = require('awv3-protocol/unpack'); var _unpack2 = _interopRequireDefault(_unpack); var _object = require('../three/object3'); var _object2 = _interopRequireDefault(_object); var _region = require('../three/region'); var _region2 = _interopRequireDefault(_region); var _defaults = require('./defaults'); var _defaults2 = _interopRequireDefault(_defaults); var _geometry = require('./geometry'); 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 }; } // options.pool = THREE.Object3D // options.factory = function() // options. // when a pool exists operations can be fulfilled without needing a complex factory // this applies to assemblies, or even connected classcad transmissions // operations should always be awaited, the geometry parser should return promises as well // structural elements should be visible and uncompressed, only geometry should go to the worker // if the structure is laid out clear it can be processed in sequence var Parser = function () { function Parser() { // ... (0, _classCallCheck3.default)(this, Parser); } (0, _createClass3.default)(Parser, [{ key: 'stream', value: function () { var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2() { var _this = this; var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Error.log('Url undefined'); var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var requests, results, context; return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: // Always assume an array requests = Array.isArray(url) ? url : [url]; // Map request-array into an array of promises and await them through Promises.all _context2.next = 3; return _promise2.default.all(requests.map(function () { var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(item) { var context, response; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: // This function is allowed to run async, each request must race // A for-of loop instead would run requests in sequence, but it would waste performance // Create context for each request context = createContext(options); // Request URL, wait until downloaded, then parse _context.next = 3; return fetch(item).then(function (r) { return r.json(); }); case 3: response = _context.sent; _context.next = 6; return handleResult(context, response); case 6: _context.next = 8; return _promise2.default.all(context.promises); case 8: context.mapitem = item; // Return result return _context.abrupt('return', context); case 10: case 'end': return _context.stop(); } } }, _callee, _this); })); return function (_x3) { return _ref2.apply(this, arguments); }; }())); case 3: results = _context2.sent; // All promises have been fulfilled, return results context = mergeContext(results); context.options.callback({ type: Parser.Factory.Finished, context: context }); return _context2.abrupt('return', context); case 7: case 'end': return _context2.stop(); } } }, _callee2, this); })); function stream() { return _ref.apply(this, arguments); } return stream; }() // Same pattern as above }, { key: 'parse', value: function () { var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee4() { var _this2 = this; var blob = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Error.log('Blob undefined'); var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var requests, results, context; return _regenerator2.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: requests = Array.isArray(blob) ? blob : [blob]; _context4.next = 3; return _promise2.default.all(requests.map(function () { var _ref4 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(item) { var context; return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: context = createContext(options); _context3.next = 3; return handleResult(context, item); case 3: _context3.next = 5; return _promise2.default.all(context.promises); case 5: return _context3.abrupt('return', context); case 6: case 'end': return _context3.stop(); } } }, _callee3, _this2); })); return function (_x6) { return _ref4.apply(this, arguments); }; }())); case 3: results = _context4.sent; context = mergeContext(results); context.options.callback({ type: Parser.Factory.Finished, context: context }); return _context4.abrupt('return', context); case 7: case 'end': return _context4.stop(); } } }, _callee4, this); })); function parse() { return _ref3.apply(this, arguments); } return parse; }() }]); return Parser; }(); // TODO // 1. doesn't need to be coupled to canvas AT ALL // 2. Canvas events should be renamed to broadcasts to make sense exports.default = Parser; Parser.Factory = { Blob: 'Blob', Link: 'Link', Assembly: 'Assembly', Part: 'Part', Model: 'Model', Mesh: 'Mesh', Line: 'Line', Cone: 'Cone', Vertex: 'Vertex', Csys: 'Csys', Text: 'Text', Transform: 'Transform', Remove: 'Remove', Started: 'Started', Finished: 'Finished' }; function createContext() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var resolve = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var reject = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var command = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ''; // Set defaults options = (0, _extends3.default)({ callback: typeof options === 'function' ? options : function () { return null; }, session: undefined, id: (0, _uuidV2.default)() }, _defaults2.default.all, options); return { // Transaction ID id: options.id, // Transaction resolve resolve: resolve, // Transaction reject reject: reject, // All generated promises promises: [], // Hint for mapping results later command: command || '', // Options options: options, // An array of context objects, for instance when several urls are parsed at once array: [], // Part hashtable using load-time hints like filenames map: {}, // An array of resulting 3D models models: [], // An array of JSON patches patches: [], // An array of ClassCAD results results: [], // An array of ClassCAD error messages errors: [], // Bytes processed (compressed) bytes: 0, // Bytes processed (uncompressed) bytesUncompressed: 0, // Timer socketTime: null, // Parsing time time: 0 }; } function mergeContext() { var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Error.log('Context undefined'); if (Array.isArray(context)) { if (context.length === 1) return mergeContext(context[0]);else { var result = createContext(); result.array = context; return mergeContext(result); } } delete context.resolve; delete context.reject; delete context.promises; delete context.mapitem; if (context.array.length > 0 && context.models.length === 0) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = (0, _getIterator3.default)(context.array), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var part = _step.value; if (!!part.mapitem) context.map[part.mapitem] = part; var partContext = mergeContext(part); partContext.models.forEach(function (model) { return context.models.push(model); }); partContext.patches.forEach(function (patch) { return context.patches.push(patch); }); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } context.firstModel = undefined; if (context.models.length > 0) context.firstModel = context.models[0]; context.firstResult = undefined; if (context.results.length > 0) context.firstResult = context.results[0].result; return context; } function parseGeometry(data, context) { var models = context.models, options = context.options; var _data$properties = data.properties, min = _data$properties.min, max = _data$properties.max, meta = _data$properties.meta, material = _data$properties.material; var color = material.color, emissive = material.emissive, opacity = material.opacity, map = material.map; var model = new THREE.Group(); model.name = 'geometry'; model.userData = { id: data.id, meta: meta }; if (color) { data.properties.material.color = new THREE.Color(color[0] / 255, color[1] / 255, color[2] / 255); } if (emissive) { data.properties.material.emissive = new THREE.Color(emissive[0] / 255, emissive[1] / 255, emissive[2] / 255); } if (map && options.session) { var _map = null; if (data.properties.material.map) { var key = data.properties.material.map; _map = options.session.materials[key]; if (!_map) { var path = session.globals.resources[key]; _map = options.session.materials[key] = new THREE.TextureLoader().setCrossOrigin('anonymous').load(path); _map.wrapS = THREE.RepeatWrapping; _map.wrapT = THREE.RepeatWrapping; } } data.properties.material.map = _map; } if (!!min && !!max) { data.properties.box = new THREE.Box3(new (Function.prototype.bind.apply(THREE.Vector3, [null].concat((0, _toConsumableArray3.default)(min))))(), new (Function.prototype.bind.apply(THREE.Vector3, [null].concat((0, _toConsumableArray3.default)(max))))()); data.properties.sphere = data.properties.box.getBoundingSphere(); model.bounds = model.bounds || { box: new THREE.Box3(), sphere: new THREE.Sphere() }; model.bounds.box = data.properties.box; model.bounds.sphere = data.properties.sphere; } if (data.mesh !== undefined) { var mesh = (0, _geometry.parseMesh)(data, context); if (mesh) { model.add(mesh); options.callback({ type: Parser.Factory.Mesh, model: model, data: mesh, meta: mesh.meta, material: mesh.material }); } } if (data.line !== undefined) { var _mesh = (0, _geometry.parseLine)(data, context); if (_mesh) { model.add(_mesh); options.callback({ type: Parser.Factory.Line, model: model, data: _mesh, meta: _mesh.meta, material: _mesh.material }); } } // cones if (!!data.cones) { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = (0, _getIterator3.default)(data.cones), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var _cone = _step2.value; options.callback({ type: Parser.Factory.Cone, model: model, data: _cone, meta: _cone.meta, material: _cone.material }); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } // vertices if (!!data.vertices) { var _mesh2 = new _region2.default(); var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = (0, _getIterator3.default)(data.vertices), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var vertex = _step3.value; _mesh2.points.push({ id: vertex.id, meta: (0, _extends3.default)({}, vertex.meta, { type: 'point', position: new (Function.prototype.bind.apply(THREE.Vector3, [null].concat((0, _toConsumableArray3.default)(vertex.p))))(), layer: data.properties.layer }) }); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } options.callback({ type: Parser.Factory.Vertex, model: model, data: _mesh2 }); model.add(_mesh2); } // csys if (!!data.coordinateSystems) { var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = (0, _getIterator3.default)(data.coordinateSystems), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var _csys = _step4.value; options.callback({ type: Parser.Factory.Csys, model: model, data: _csys, meta: _csys.meta }); } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } } //text if (!!data.text) { var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = (0, _getIterator3.default)(data.text), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var _text = _step5.value; options.callback({ type: Parser.Factory.Text, model: model, data: _text, meta: _text.meta }); } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } }models.push(model); options.callback({ type: Parser.Factory.Model, model: model, data: data, meta: meta }); }