awv3
Version:
⚡ AWV3 embedded CAD
607 lines (524 loc) • 18.9 kB
JavaScript
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _extends from "@babel/runtime/helpers/extends";
import _createClass from "@babel/runtime/helpers/createClass";
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import isEqual from 'lodash/isEqual';
import pack from 'awv3-protocol/pack';
import Element from './element';
import { reducer } from './store/index.js';
import { actions as globalActions } from './store/globals';
import { actions as elementActions } from './store/elements';
import { base as connectionBase, actions as connectionActions } from './store/connections';
import { base as pluginBase } from './store/plugins';
import { createObserver, Pool, ObjectPrototype } from './helpers';
import Selector from './selector';
import Connection from './connection';
import Defaults from '../core/defaults';
var Session =
/*#__PURE__*/
function () {
function Session(options) {
var _this = this;
if (options === void 0) {
options = {};
}
this.options = _extends({
throttle: 500,
pool: Pool,
objectPrototype: ObjectPrototype
}, Defaults.all, options);
var composeEnhancers = this.options.debug && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose;
this.store = options.store || createStore(reducer, composeEnhancers(applyMiddleware(thunk
/*, logger*/
))); // Support hot reloading reducers
if (process.env.NODE_ENV !== 'production' && !options.store && module.hot) {
module.hot.accept(['./store/globals', './store/plugins', './store/elements', './store/connections', './store/index'], function () {
return _this.store.replaceReducer(require('./store/index.js').reducer);
});
}
this.pool = new Pool({
session: this,
name: 'session.pool'
});
this.defaultFeaturePlugin;
this.featurePlugins = {};
this.materials = {};
this.layerNames = [];
this.observe = createObserver(this.store, this.getState.bind(this)); // Global observers
this.observe(function (state) {
return state.globals.activeConnection;
}, observeActiveConnection.bind(this));
options.resources && this.addResources(options.resources);
options.featurePlugins && this.registerFeaturePlugins(options.featurePlugins);
options.defaultFeaturePlugin && this.registerDefaultFeaturePlugins(options.defaultFeaturePlugin); // Add a global keylistener that will forward events to a plugins console
var keydownEventHandler = keydownEvent.bind(this);
document.addEventListener('keydown', keydownEventHandler); // Link view
if (this.options.view) {
this.view = this.options.view;
this.view.scene.add(this.pool);
} else {
this.pool.viewFound().then(function (view) {
return _this.view = view;
});
} // Add default connection for convenience
if (this.options.defaultConnection) {
var connection = this.addConnection('default');
if (this.options.url && this.options.protocol) connection.on('connected', function (connection) {
return _this.options.defaultConnection(connection);
});else this.options.defaultConnection(connection);
}
this.observe(function (state) {
return state.globals.camera;
}, function (state) {
return _this.pool.view.camera.orthographic = state === 'orthographic';
});
this.observe(function (state) {
return state.globals.day;
}, function (day) {
return day ? document.body.classList.remove('night') : document.body.classList.add('night');
}, {
fireOnStart: true
});
this.selector = undefined;
this.observe(function (state) {
return state.globals.activeSelection;
}, function (id) {
_this.selector && _this.selector.destroy();
_this.selector = undefined;
if (id) {
var _this$elements$id = _this.elements[id],
items = _this$elements$id.items,
types = _this$elements$id.types,
limit = _this$elements$id.limit,
_this$elements$id$pro = _this$elements$id.properties,
properties = _this$elements$id$pro === void 0 ? _this.globals.selection : _this$elements$id$pro,
basic = _this$elements$id.basic,
selectObjects = _this$elements$id.selectObjects;
_this.selector = new Selector(_this, {
ids: items,
types: types,
limit: limit,
properties: properties,
basic: basic,
selectObjects: selectObjects
});
_this.selector.on('changed', function (items, old) {
return !isEqual(items, old) && _this.store.dispatch(elementActions.update(id, {
items: items
}));
}, {
sync: true
});
}
});
}
var _proto = Session.prototype;
_proto.showLayer = function showLayer(args) {
var _this2 = this;
if (args === void 0) {
args = [];
}
var concernedMaterials = 0;
this.layerNames = Array.isArray(args) ? args : [args];
this.pool.traverse(function (obj) {
if (obj.material) {
obj.getMaterials().forEach(function (mat) {
mat.visible = mat.meta ? _this2.layerNames.length == 0 || _this2.layerNames.indexOf(mat.meta.layer) > -1 : mat.visible;
if (mat.visible) concernedMaterials++;
});
}
});
this.pool.view.invalidate();
return concernedMaterials;
};
_proto.isVisibleLayer = function isVisibleLayer(layerName) {
if (this.layerNames.length === 0 || this.layerNames.indexOf(layerName) > -1) return true;
return false;
};
_proto.getState = function getState() {
return this.store.getState() || {};
};
_proto.dispatch = function dispatch(action) {
return this.store.dispatch(action);
};
_proto.registerDefaultFeaturePlugin = function registerDefaultFeaturePlugin(prototype) {
this.defaultFeaturePlugin = prototype;
};
_proto.registerFeaturePlugins = function registerFeaturePlugins(map) {
this.featurePlugins = _extends({}, this.featurePlugins, map);
};
_proto.resolveFeaturePlugin =
/*#__PURE__*/
function () {
var _resolveFeaturePlugin = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee(promise) {
var _ref,
plugin,
_len,
args,
_key,
_args = arguments;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return promise;
case 2:
_ref = _context.sent;
plugin = _ref.default;
for (_len = _args.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = _args[_key];
}
this.registerFeaturePlugins(args.reduce(function (prev, key) {
var _extends2;
return _extends({}, prev, (_extends2 = {}, _extends2[key] = plugin, _extends2));
}, {}));
case 6:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function resolveFeaturePlugin(_x) {
return _resolveFeaturePlugin.apply(this, arguments);
};
}();
_proto.resolveDefaultFeaturePlugin =
/*#__PURE__*/
function () {
var _resolveDefaultFeaturePlugin = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee2(promise) {
var _ref2, Plugin;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_context2.next = 2;
return promise;
case 2:
_ref2 = _context2.sent;
Plugin = _ref2.default;
this.registerDefaultFeaturePlugin(Plugin);
case 5:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
return function resolveDefaultFeaturePlugin(_x2) {
return _resolveDefaultFeaturePlugin.apply(this, arguments);
};
}();
_proto.resolveGlobalPlugins =
/*#__PURE__*/
function () {
var _resolveGlobalPlugins = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee3() {
var _len2,
promises,
_key2,
plugins,
_args3 = arguments;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
for (_len2 = _args3.length, promises = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
promises[_key2] = _args3[_key2];
}
_context3.next = 3;
return Promise.all(promises);
case 3:
_context3.t0 = function (_ref3) {
var Plugin = _ref3.default;
return new Plugin(session).id;
};
plugins = _context3.sent.map(_context3.t0);
session.dispatch(globalActions.linkPlugins(plugins));
case 6:
case "end":
return _context3.stop();
}
}
}, _callee3, this);
}));
return function resolveGlobalPlugins() {
return _resolveGlobalPlugins.apply(this, arguments);
};
}();
_proto.findFeaturePlugin = function findFeaturePlugin(criteria) {
var plugin = Object.entries(this.featurePlugins).find(criteria);
if (plugin) return plugin[1];
};
_proto.findGlobalPlugin = function findGlobalPlugin(criteria) {
for (var _iterator = this.globals.plugins, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref4;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref4 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref4 = _i.value;
}
var _key3 = _ref4;
var plug = this.plugins[_key3];
if (criteria(plug)) return plug;
}
};
_proto.addResources = function addResources(map) {
this.dispatch(globalActions.addResources(map));
};
_proto.addConnection = function addConnection(name) {
// Remove extension, if any ...
name = name.match(/([^:\\/]*?)(?:\.([^ :\\/.]*))?$/)[1]; // Create new connection class
var connection = new Connection(this, {
name: name
});
this.store.dispatch(globalActions.setActiveConnection(connection.id));
return connection;
};
_proto.open = function open(files, onInitConnection, onOpen) {
var _this3 = this;
files = Array.from(files);
var promise = Promise.all(files.map(function (file) {
return new Promise(function (res) {
var name = file.name.substr(0, file.name.lastIndexOf('.'));
var extension = file.name.substr(file.name.lastIndexOf('.') + 1);
var reader = new FileReader();
reader.onload = function (event) {
var data = pack(event.target.result);
var connection = _this3.addConnection(file.name);
connection.on('connected',
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee4() {
var result;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
if (!onInitConnection) {
_context4.next = 3;
break;
}
_context4.next = 3;
return onInitConnection(connection);
case 3:
_context4.next = 5;
return _this3.store.dispatch(connectionActions.load(connection.id, data, extension));
case 5:
result = _context4.sent;
connection.pool.view && connection.pool.view.updateBounds().controls.focus().zoom();
res(_extends({}, result, {
connection: connection
}));
case 8:
case "end":
return _context4.stop();
}
}
}, _callee4, this);
})));
};
reader.readAsArrayBuffer(file);
});
}));
if (onOpen) onOpen(promise, this);
return promise;
};
_proto.closeAllConnections = function closeAllConnections() {
var _this4 = this;
Object.keys(this.connections).forEach(function (id) {
return _this4.dispatch(connectionActions.unregister(id));
});
};
_proto.resolveResource = function resolveResource(name, plugin) {
var resource;
var scope = this.plugins[plugin];
if (scope) resource = scope.resources[name];
if (!resource) resource = this.globals.resources[name];
return resource;
};
_createClass(Session, [{
key: "scene",
get: function get() {
return this.pool.scene;
}
}, {
key: "state",
get: function get() {
return this.getState();
}
}, {
key: "globals",
get: function get() {
return this.state.globals;
}
}, {
key: "plugins",
get: function get() {
return this.state.plugins;
}
}, {
key: "elements",
get: function get() {
return this.state.elements;
}
}, {
key: "connections",
get: function get() {
return this.state.connections;
}
}, {
key: "collections",
get: function get() {
return this.state.collections;
} // Computed props
}, {
key: "activeConnection",
get: function get() {
return this.state.connections[this.state.globals.activeConnection];
}
}, {
key: "activePlugin",
get: function get() {
var _this5 = this;
return this.plugins[this.activeConnection.plugins.find(function (item) {
return _this5.plugins[item].feature === _this5.activeConnection.activeFeature;
})];
}
}, {
key: "tree",
get: function get() {
return this.activeConnection.tree;
}
}, {
key: "activeConnectionClass",
get: function get() {
return connectionBase.references[this.globals.activeConnection];
}
}, {
key: "activePluginClass",
get: function get() {
return pluginBase.references[this.activePlugin.id];
}
}, {
key: "report",
get: function get() {
var r = {};
console.log('%cSession', 'font-size: 20px; font-weight: 600;');
console.table({
tree: Object.keys(this.activeConnectionClass.tree).length,
primitives: Object.keys(this.activeConnectionClass.primitives).length,
waiting: Object.keys(this.activeConnectionClass.waiting).length,
featurePlugins: Object.keys(this.activeConnectionClass.featurePlugins).length
});
r = {};
console.log('%cObjects', 'font-size: 20px; font-weight: 600;');
console.table(this.pool.traverse(function (i) {
return r[i.type] = r[i.type] === undefined ? 1 : r[i.type] + 1;
}) || r);
console.log('%cMemory', 'font-size: 20px; font-weight: 600;');
console.table(session.pool.view.renderer.gl.info.memory);
console.log('%cRender', 'font-size: 20px; font-weight: 600;');
console.table(session.pool.view.renderer.gl.info.render);
console.log('%cPrograms', 'font-size: 20px; font-weight: 600;');
console.table(session.pool.view.renderer.gl.info.programs, ['code', 'usedTimes']);
r = {};
console.log('%cMaterials', 'font-size: 20px; font-weight: 600;');
console.table(this.pool.traverseMaterials(function (m) {
return r[m.type] = r[m.type] === undefined ? 1 : r[m.type] + 1;
}) || r);
console.log('%cGraph', 'font-size: 20px; font-weight: 600;');
sceneGraph(this.pool);
}
}]);
return Session;
}();
export { Session as default };
function sceneGraph(target, level) {
if (level === void 0) {
level = 0;
}
target.children.forEach(function (child) {
console.log(new Array(level).fill(' ').join(''), child.name || child.type);
sceneGraph(child, level + 2);
});
}
function checkElements(session, elements) {
for (var _iterator2 = elements, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref6;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref6 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref6 = _i2.value;
}
var _key4 = _ref6;
var element = session.elements[_key4];
if (element.type === Element.Type.Console) {
session.store.dispatch(elementActions.update(element.id, {
focus: true
}));
session.store.dispatch(elementActions.event(element.id, event));
return true;
} else if (element.type === Element.Type.Group && checkElements(session, element.children)) return true;
}
return false;
}
function keydownEvent(event) {
var target = event.target;
if (!(target instanceof HTMLInputElement)) {
for (var key in this.plugins) {
var plugin = this.plugins[key];
if (plugin.enabled && !plugin.collapsed && checkElements(this, plugin.elements)) return;
}
}
}
function observeActiveConnection(_x3, _x4) {
return _observeActiveConnection.apply(this, arguments);
}
function _observeActiveConnection() {
_observeActiveConnection = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee5(id, previous) {
var activeConnection;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
if (previous) this.pool.removeAsync(connectionBase.references[previous].pool);
if (!id) {
_context5.next = 9;
break;
}
activeConnection = connectionBase.references[id];
_context5.next = 5;
return this.pool.addAsync(activeConnection.pool);
case 5:
_context5.next = 7;
return this.pool.viewFound();
case 7:
this.pool.view.updateBounds();
this.pool.view.controls.focus().zoom();
case 9:
case "end":
return _context5.stop();
}
}
}, _callee5, this);
}));
return _observeActiveConnection.apply(this, arguments);
}