import { Reporter } from '../reporter/reporter.js';
import { Connector } from '../package/connector/connector.js';
import { ConnectorType } from '../package/connector/connector_type.js';
import { ConnectionType } from '../package/connector/connection_type.js';
import { ComponentTree } from '../component/component_tree.js';
import { Quaternion } from '../../node_modules/three/build/three.module.js';
import { Connectable } from './connectable.js';
/** Connection between two connector instances */
class Connection extends Connectable {
/**
* @param {Reporter} reporter
* @param {Object} settings
* @param {UUID} [settings.id]
* @param {string} [settings.name]
* @param {Object} settings.from
* @param {Connectable} settings.from.connectable
* @param {Connector} settings.from.connector
* @param {Object} settings.to
* @param {Connectable} settings.to.connectable
* @param {Connector} settings.to.connector
* @param {Quaternion} [settings.quaternion]
*/
constructor ( reporter, settings )
{
if ( settings.blockInstances ) {
delete settings.blockInstances;
}
super(
reporter,
settings
);
// old fashioned sanity checking
for ( let side of [ 'from', 'to']) {
if ( ! settings[ side ] ) {
throw new Error( `Missing "${side}" object`);
}
if (! ( settings[ side ].connectable instanceof Connectable)) {
if ( ! settings[ side ].connectable ) {
throw new Error( `Missing a ${side}.connectable.`);
}
else {
throw new Error( `${side}.connectable is not a Connectable, but a ${settings[ side ].connectable.constructor.name}.`);
}
}
if (! ( settings[ side ].connector instanceof Connector)) {
if ( ! settings[ side ].connector ) {
throw new Error( `Missing ${side}.connector.`);
}
else {
throw new Error( `${side}.connector is not a Connector, but a ${settings[ side ].connector.constructor.name}.`);
}
}
if ( ! settings[ side ].connectable.block.dependsDirectlyOn( settings[ side ].connector )) {
throw new Error( `Entry ${side} connector is not a dependency of block` );
}
if ( settings.quaternion && ! settings.quaternion instanceof Quaternion ) {
throw new Error( `.quaternion is not a Quaternion but a ${settings.quaternion.constructor.name}`)
}
}
if ( ! settings.quaternion ) {
this.quaternion = Connection.defaultQuaternion;
}
this.inverseQuaternion = this.quaternion.clone().invert()
if ( settings.from.connectable === settings.to.connectable) {
throw new Error( `Connections to and from blocks are the same.`);
}
this.connectors = [ settings.from.connector, settings.to.connector ];
this.connectorTypes = [ settings.from.connector.type, settings.to.connector.type ];
this.connectables = [settings.from.connectable, settings.to.connectable ];
// mf typescript
if ( ! this.from ) {
this.from = settings.from;
}
if ( ! this.to ) {
this.to = settings.to;
}
}
static _exportName = {
singular: 'connection',
plural: 'connections'
};
/** @type {ExportLevel} */
static _exportLevel = 'inline';
static connectorTemplateSetting = 'connectionType';
// Quaternion [x, y, z, w]
// [ 0, 0, 0, 1 ] - Identity quaternion, no rotation,
// [ 1, 0, 0, 0 ] - 180° turn around X axis,
// [ 0, 1, 0, 0 ] - 180° turn around Y axis,
// [ 0, 0, 0, 1 ] - 180° turn around Z axis,
static baseQuaternion = new Quaternion(0, 1, 0, 0);
static defaultQuaternion = new Quaternion(0,0,0,1);
static treeLock = false;
/**
* @type {Array<Connectable>}
*/
connectables;
/**
* @type {Array<Connector>}
*/
connectors;
/**
* @type {Array<ConnectorType>}
*/
connectorTypes;
/** @type {ComponentTree} */
_tree;
/** @type {ConnectionType} */
type;
_onTreeSet() {
for ( let side of [ 'from', 'to']) {
const connectableExportName = this._settings[ side ].connectable.exportName;
if ( ( ! this._tree[ connectableExportName ] ) || ( ! this._tree[ connectableExportName ].includes( this._settings[ side ].connectable))) {
throw new Error( `${side} ${connectableExportName} is not specified in the tree (${this._settings[ side ].connectable.label}).` );
}
}
// console.log( this._tree.inclusive.connectionTypes)
if ( ! this._tree.inclusive.connectionTypes ) {
throw new Error( `No connection types defined in tree` );
}
const connectionType = this._tree.inclusive.connectionTypes.find( connectionType =>
( connectionType.connectorTypes[ 0 ] === this.connectorTypes[ 0 ] && connectionType.connectorTypes[ 1 ] === this.connectorTypes[ 1 ] )
||
( connectionType.connectorTypes[ 0 ] === this.connectorTypes[ 1 ] && connectionType.connectorTypes[ 1 ] === this.connectorTypes[ 0 ] )
);
if ( ! connectionType ) {
console.error( this._tree.inclusive.connectionTypes);
throw new Error( `Missing this connection's type in tree.pkg [${this.connectorTypes[0].label} <-> ${this.connectorTypes[1].label}]` );
}
this.type = connectionType;
if ( this.type.parent) {
if (this.connectorTypes[ 0 ] === this.connectorTypes[ 1 ]) {
throw new Error(`${this.type.label} defines a parent/child relationship, but both connectors have the same type in ${this.label}`);
}
}
this.connectorTemplate = connectionType;
super._onTreeSet();
}
_onTreeUnset() {
super._onTreeUnset();
this.type = undefined;
}
/**
* Checks whether a connector or blockInstance is part of this connection
* @param {Component} component
* @returns {Boolean}
*/
connects(component) {
if ( component instanceof Connectable ) {
return this._settings.from.connectable === component || this._settings.to.connectable === component;
}
else if ( component instanceof Connector ) {
return this._settings.from.connector === component || this._settings.to.connector === component;
}
return false;
}
/**
* @returns {}
*/
_build(part,quality,dependencies) {
this._setContent(part,quality,'-');
}
// /**
// * @returns {ParsedConnectionString}
// */
// toJSON() {
// return {
// UUID: this.UUID,
// from: this.fromConnector.toJSON(),
// to: this.toConnector.toJSON(),
// }
// }
}
export { Connection }