import { Reporter } from '../reporter/reporter.js';
import { buildMateMap } from '../lib.js';
import { Block } from './block/block.js';
import { ConnectorType } from './connector/connector_type.js';
import { Connector } from './connector/connector.js';
import { ThemeGroup } from './theme/theme_group.js';
import { Theme } from './theme/theme.js';
import { ConnectionType } from './connector/connection_type.js';
import { BlockCategory } from './block/block_category.js';
import { WrappedMaterial } from './material/wrapped_material.js';
import { WrappedMesh } from './mesh/wrapped_mesh.js';
import { MeshGroup } from './mesh/mesh_group.js';
import { WrappedImage } from './image/wrapped_image.js';
import { MaterialSet } from './material/material_set.js';
import { WrappedTexture } from './wrapped_texture.js';
import { MaterialCategoryType } from './material/material_category_type.js';
import { MaterialCategory } from './material/material_category.js';
import { ComponentTree } from '../component/component_tree.js';
import { BuildableComponent } from './component/buildable_component.js';
import { GeometryFile } from './geometry/geometry_file.js';
import { Geometry } from './geometry/geometry.js';
import { GLTF } from './mesh/gltf.js';
import { EXR } from './image/exr.js';
import { EnvironmentMap } from './environment_map.js';
import { PositionedMesh } from '../package/mesh/positioned_mesh.js'
import { PositionedMeshGroup } from '../package/mesh/positioned_mesh_group.js'
import { BlockCategoryType } from './block/block_category_type.js';
import { BlockSet } from './block/block_set.js';
import { Configuration } from '../configurator/configuration.js';
import { Project } from '../project.js';
connectors: Connector
/**
* @todo
* Add jsdoc constructor
* Analysis functions:
* - loadable component with missing sizes
* - total loading size
*/
/** Loads, caches and augments product package data. */
class Package extends ComponentTree {
/**
* @param {Reporter} reporter
*/
constructor(reporter, settings, instructions = {}) {
// console.log(settings)
super(
reporter,
settings,
{
import: Package.importInstructions,
...instructions
}
);
this.addEvent( 'mate-map-update' );
this.addEvent( 'connectors-by-type-update' );
this.addEvent( 'material-sets-by-material-update' );
// console.log(this.label, this._events);
if ( instructions.loader ) {
this.loader = instructions.loader;
}
this.on('change', ({cls}) => {
// console.log( 'Change event, classes:', cls)
if (cls.includes(Connector) || cls.includes(ConnectorType) || cls.includes( ConnectionType)) {
this.updateConnectorTypeMateMap();
}
else if ([WrappedMaterial, MaterialSet, MaterialCategory].includes(cls)) {
this.updateMaterialSetsByMaterial();
}
});
this.updateConnectorTypeMateMap();
this.updateMaterialSetsByMaterial();
}
static _exportName = {
singular: 'package',
plural: 'packages'
};
static importInstructions = [
// {
// cls: PackageInfo
// },
// {
// cls: ConfigurationSettings
// },
// {
// cls: NavigationSettings
// },
{
cls: WrappedImage
},
{
cls: EXR
},
{
cls: WrappedTexture
},
{
cls: EnvironmentMap
},
{
cls: MaterialCategoryType
},
{
cls: MaterialCategory
},
{
cls: WrappedMaterial
},
{
cls: MaterialSet
},
{
cls: GeometryFile
},
{
cls: GLTF
},
{
cls: Geometry
},
{
cls: WrappedMesh
},
{
cls: PositionedMesh
},
{
cls: MeshGroup
},
{
cls: PositionedMeshGroup
},
{
cls: ThemeGroup
},
{
cls: Theme
},
{
cls: ConnectorType
},
{
cls: Connector
},
{
cls: BlockCategoryType
},
{
cls: BlockCategory
},
{
cls: Block
},
// {
// cls: PositionedBlock
// },
{
cls: BlockSet
},
{
cls: ConnectionType
},
{
cls: Configuration
}
];
// link only the blocks, and the components that are not dependencies
// not all the "settings"
_autoLink() {
const dependUpon = ['blocks', 'connectionTypes'];
const blockSettings = {};
for ( let [ setting, val ] of Object.entries(this._settings)) {
if ( dependUpon.includes(setting)) {
blockSettings[setting] = val;
}
else if ( Array.isArray(val) ) {
// console.log('export only dep', setting, val)
this._exportOnlyDependencies[ setting ] = val;
}
}
// console.info(blockSettings);
super._autoLink(
blockSettings,
BuildableComponent.autogenIntegralInstruction(blockSettings)
);
}
/**
* @typedef {Object} ConnectorTypeMates
* @property {Array<ConnectionType>} connectionTypes - ConnectionTypes in which this connector type is a mate
* @property {Array<ConnectorType>} mateConnectorTypes - ConnectorTypes that can mate with this connector type
* @property {Array<Connector>} mateConnectors - Connectors that can mate with this connector type
*/
/**
* Object that has a list of potential mate type per connector types
* and a reference to all relevant AllowedConnectionTypes per potential
* mate type
* @type {Map.<ConnectorType,ConnectorTypeMates>}
*/
connectorTypeMateMap = new Map();
updateConnectorTypeMateMap() {
this.report({ msg: 'Updating mate map' });
// console.warn( 'Update mate map', this.settings.connectorTypes)
this.connectorTypeMateMap = buildMateMap(this._settings);
// console.log( 'emit mate-map-update', Object.keys( this._events[ 'mate-map-update']), this.label);
this.emit('mate-map-update', this.connectorTypeMateMap);
// console.log('emit', this.label, this._events, this._events['mate-map-update'])
return this.connectorTypeMateMap;
}
/**
* @type {Object<ConnectorType,Array<Connector>>}
*/
connectorsByType = {};
updateConnectorsByType() {
for (let type of this.connectorTypes) {
this.connectorsByType = this.connectors.filter(con => con.settings.type === type);
}
this.emit('connectors-by-type-update', this.connectorsByType);
}
/**
* The material sets in which each material is present
* @type {Object<WrappedMaterial,Array<MaterialSet>>}
*/
materialSetsByMaterial = {};
updateMaterialSetsByMaterial() {
const index = {};
for (let material of this.materials) {
index[material] = [];
for (let materialSet of this.materialSets) {
if (materialSet.has(material)) {
index[material].push(materialSet);
}
}
}
this.materialSetsByMaterial = index;
this.emit('material-sets-by-material-update', this.materialSetsByMaterial);
}
async _build(part, quality, dependencies) {
// console.log(dependencies)
this._status[part][quality].setState('loading');
switch (part) {
case 'UI':
if (this._settings.thumbnail) {
this._setContent('UI', quality, this._settings.thumbnail.content.main[quality]);
}
else {
await this._setContent('UI', quality, Project.defaultImages.missing.cloneNode(true));
}
break;
case 'main':
// console.log(dependencies)
this._setContent(part, quality, dependencies);
break;
default:
this._setContent(part, quality, null);
break;
}
return this;
}
}
export { Package }