UNPKG

awv3

Version:
164 lines (149 loc) 6.5 kB
import * as THREE from 'three'; import Lifecycle from './lifecycle.js'; import { halt } from '../core/error'; import { actions } from './store/plugins'; import { actions as elementActions } from './store/elements'; import { actions as globalActions } from './store/globals'; import { actions as connectionActions, base as connectionBase } from './store/connections'; import { base as pluginBase } from './store/plugins'; import { createObserver } from './helpers'; import Element from './element'; import { Group, Button, Spacer, Divider } from './elements'; export default class Plugin extends Lifecycle() { static persistent = false; static measurable = false; constructor(session = halt('plugin must be initialized with a session'), { feature, connection, pool, ...props }) { super(session, actions, state => state.plugins[this.id], { type: '', name: '', title: '', resources: {}, icon: undefined, enabled: false, active: false, collapsed: true, closeable: true, parent: undefined, elements: [], feature: feature ? feature.id : false, connection: connection ? connection.id : undefined, managed: true, ...props, }); // If a parent exists (which mean this is a linked plugin, invoked by a parent plugin) if (this.parent) { let parentPlugin = pluginBase.references[this.parent]; // And if the parent is a feature, it gets to store its own pool under the parent, while // it is allowed to pose as a feature plugin itself if (parentPlugin.feature) { feature = parentPlugin; connection = parentPlugin.connection; this.pool = new THREE.Group(); this.pool.updateParentMaterials = false; this.pool.measurable = false; this.pool.name = `plugin.linked_pool.${this.type}${this.name ? '+' + this.name : ''}`; feature.pool.add(this.pool); } } if (feature) { Object.defineProperty(this, 'feature', { get: () => feature.id }); Object.defineProperty(this, 'connection', { get: () => connection }); if (!this.parent) { this.pool = pool; this.reset = new Button(this, { name: 'Reset', color: 'black', flex: 0 }); this.apply = new Button(this, { name: 'Apply', color: 'blue', flex: 0 }); this.addElement( new Group(this, { index: 10000000, children: [ new Divider(this), new Spacer(this), new Group(this, { format: Group.Format.Rows, flexDirection: 'row-reverse', children: [this.apply, new Spacer(this), this.reset], }), ], }), ); } } else { Object.defineProperty(this, 'connection', { get: () => connectionBase.references[this.session.globals.activeConnection], }); this.pool = new THREE.Group(); this.pool.updateParentMaterials = false; this.pool.measurable = false; this.pool.name = `plugin.pool.${this.type}${this.name ? '+' + this.name : ''}`; this.session.pool.temporary.add(this.pool); } // this.tree refers to the connections tree Object.defineProperty(this, 'tree', { get: () => this.connection.tree }); Object.defineProperty(this, 'root', { get: () => this.tree[this.tree.root] }); Object.defineProperty(this, 'view', { get: () => this.pool.view }); // Internal observer for enabled state, gets cleared after destroy // The enabled flag has to be kept locally as the destroyed event can be dispatched // without calling destroy() directly, leaving the linked state empty this.__enabled = this.enabled; this.__enabledUnsubscribe = this.observe( // selector state => state.enabled, // onChanged (enabled, prev) => { this.__enabled = enabled; if (enabled !== prev) { if (enabled) { this.onEnabled(); } else { this.onDisabled(); } } !enabled && this.removeSubscriptions(); }, // options { manager: undefined }, ); } addElement(...elements) { elements.forEach(element => this.store.dispatch(actions.addElement(this.id, element instanceof Element ? element.id : element)), ); } removeElement(element) { this.store.dispatch(actions.removeElement(this.id, element instanceof Element ? element.id : element)); } destroyElements() { this.store.dispatch( elementActions.unregister( Object.keys(this.session.elements).filter(id => this.session.elements[id].plugin === this.id), ), ); } resetElements() { this.store.dispatch( elementActions.merge(this.dependencies.reduce((prev, obj) => ({ ...prev, [obj.id]: obj.props }), {})), ); } createToolbar(keys, cb, columns = 7) { let children = []; for (let count = 0; count < keys.length / columns; count++) { children.push( new Group(this, { format: Group.Format.Buttons, margin: count == keys.length / columns - 1, children: cb(keys.slice(count * columns, Math.min(count * columns + columns, keys.length))), }), ); } return new Group(this, { children }); } onEnabled() {} onDisabled() {} __onDestroyed() { this.store.dispatch(globalActions.unlinkPlugins(this.id)); if (this.connection) this.store.dispatch(connectionActions.unlinkPlugins(this.connection.id, this.id)); this.__enabledUnsubscribe(); this.__enabled && this.onDisabled(); this.pool && this.pool.destroy(); } }