awv3
Version:
⚡ AWV3 embedded CAD
758 lines (612 loc) • 32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.handleResult = 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, 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 = 29;
break;
case 8:
if (!(object.command === "Endpoint")) {
_context5.next = 12;
break;
}
// Scaled endpoints
context.results.push({
command: 'Result',
from: 'ip',
result: object
});
_context5.next = 29;
break;
case 12:
if (!(object.command === "Blob")) {
_context5.next = 19;
break;
}
// Pass options to worker
object.options = (0, _extends3.default)({}, context.options, {
callback: undefined,
materials: (0, _extends3.default)({}, context.options.materials, {
envMap: undefined,
edgeColor: undefined,
lines: undefined,
meshes: undefined
})
});
// Process package in worker threads
core = _factory2.default.getFreeCore();
_context5.next = 17;
return core.post(object, function (data) {
return parseGeometry(data, context);
});
case 17:
_context5.next = 29;
break;
case 19:
if (!(context.resolve && object.command === "Result" && object.from === "EndFrame" && object.transactionID === context.id)) {
_context5.next = 28;
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 = 23;
return _promise2.default.all(context.promises);
case 23:
results = _context5.sent;
context = mergeContext(context);
tempResolve(context);
_context5.next = 29;
break;
case 28:
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 29:
resolve(context);
case 30:
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 _factory = require('../worker/factory');
var _factory2 = _interopRequireDefault(_factory);
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] : "";
var materials = options.materials || {};
delete options.materials;
// Set defaults
options = (0, _extends3.default)({
callback: typeof options === 'function' ? options : function () {
return null;
},
materials: (0, _extends3.default)({
multi: false,
compress: false,
edgeColor: undefined,
edgeOpacity: undefined,
shadows: false,
envMap: null,
lines: {
shader: THREE.LineBasicMaterial,
options: {
transparent: true,
fog: false
}
},
meshes: {
shader: THREE.MeshPhongMaterial,
options: {
transparent: true,
fog: false,
polygonOffset: true,
polygonOffsetFactor: 1,
polygonOffsetUnits: 1,
emissive: new THREE.Color(0),
reflectivity: 0.0
}
}
}, materials),
id: options.id || (0, _uuidV2.default)()
}, options);
return {
// Session guid
session: "",
// 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,
color = _data$properties.color,
min = _data$properties.min,
max = _data$properties.max,
opacity = _data$properties.opacity,
meta = _data$properties.meta;
var model = new _object2.default();
model.userData = { id: data.id, meta: meta };
data.properties.color = new THREE.Color(color[0] / 255, color[1] / 255, color[2] / 255);
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 });
}
}
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 });
}
}
// 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 });
}
} 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 });
}