UNPKG

awv3

Version:
607 lines (524 loc) 18.9 kB
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); }