@2112-lab/central-plant 0.1.87 → 0.1.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle/index.js +241 -155
- package/dist/cjs/src/core/centralPlant.js +47 -4
- package/dist/cjs/src/core/centralPlantInternals.js +2 -90
- package/dist/cjs/src/core/centralPlantValidator.js +1 -1
- package/dist/cjs/src/managers/components/componentDataManager.js +4 -1
- package/dist/cjs/src/managers/components/componentManager.js +5 -1
- package/dist/cjs/src/managers/scene/modelManager.js +47 -19
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +40 -39
- package/dist/cjs/src/utils/ioDeviceUtils.js +104 -0
- package/dist/esm/src/core/centralPlant.js +47 -4
- package/dist/esm/src/core/centralPlantInternals.js +3 -91
- package/dist/esm/src/core/centralPlantValidator.js +1 -1
- package/dist/esm/src/managers/components/componentDataManager.js +4 -1
- package/dist/esm/src/managers/components/componentManager.js +5 -1
- package/dist/esm/src/managers/scene/modelManager.js +47 -19
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +40 -39
- package/dist/esm/src/utils/ioDeviceUtils.js +100 -0
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -1980,7 +1980,7 @@ var CentralPlantValidator = /*#__PURE__*/function () {
|
|
|
1980
1980
|
key: "validateImportedSceneData",
|
|
1981
1981
|
value: function validateImportedSceneData(sceneData) {
|
|
1982
1982
|
var results = [];
|
|
1983
|
-
var hardcodedVersion = "2.
|
|
1983
|
+
var hardcodedVersion = "2.3";
|
|
1984
1984
|
|
|
1985
1985
|
// Version validation - MUST be the value of hardcodedVersion
|
|
1986
1986
|
if (!sceneData.version || sceneData.version !== hardcodedVersion) {
|
|
@@ -18749,12 +18749,16 @@ var ComponentManager = /*#__PURE__*/function () {
|
|
|
18749
18749
|
componentMesh.position.set(position.x, position.y, position.z);
|
|
18750
18750
|
|
|
18751
18751
|
// Set userData for the component including dimensions
|
|
18752
|
-
componentMesh.userData = _objectSpread2({
|
|
18752
|
+
componentMesh.userData = _objectSpread2(_objectSpread2({
|
|
18753
18753
|
libraryId: componentData.libraryId,
|
|
18754
18754
|
objectType: 'component',
|
|
18755
18755
|
originalUuid: uuid
|
|
18756
18756
|
}, ((_gltfScene$userData = gltfScene.userData) === null || _gltfScene$userData === void 0 ? void 0 : _gltfScene$userData.dimensions) && {
|
|
18757
18757
|
dimensions: gltfScene.userData.dimensions
|
|
18758
|
+
}), libraryComponent.isS3Component && {
|
|
18759
|
+
isS3Component: true,
|
|
18760
|
+
s3Path: libraryComponent.s3Path,
|
|
18761
|
+
componentKey: libraryComponent.componentKey
|
|
18758
18762
|
});
|
|
18759
18763
|
|
|
18760
18764
|
// Also ensure dimensions are preserved in the userData
|
|
@@ -19792,6 +19796,7 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
19792
19796
|
id: key,
|
|
19793
19797
|
name: component.name,
|
|
19794
19798
|
type: ((_component$metadata = component.metadata) === null || _component$metadata === void 0 ? void 0 : _component$metadata.type) || 'Component',
|
|
19799
|
+
assetType: component.assetType || null,
|
|
19795
19800
|
category: component.category,
|
|
19796
19801
|
modelKey: component.modelKey,
|
|
19797
19802
|
modelType: component.modelType,
|
|
@@ -19800,10 +19805,12 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
19800
19805
|
// Preserve S3 metadata
|
|
19801
19806
|
isS3Component: component.isS3Component,
|
|
19802
19807
|
s3Path: component.s3Path,
|
|
19803
|
-
preLoad: component.preLoad
|
|
19808
|
+
preLoad: component.preLoad,
|
|
19809
|
+
preCache: component.preCache
|
|
19804
19810
|
};
|
|
19805
19811
|
return _objectSpread2(_objectSpread2({}, baseData), {}, {
|
|
19806
19812
|
metadata: component.metadata || {},
|
|
19813
|
+
ioConfig: component.ioConfig || null,
|
|
19807
19814
|
boundingBox: component.boundingBox || null,
|
|
19808
19815
|
adaptedBoundingBox: component.adaptedBoundingBox || null,
|
|
19809
19816
|
children: component.children || [],
|
|
@@ -28553,6 +28560,103 @@ var BehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
28553
28560
|
}]);
|
|
28554
28561
|
}(BaseDisposable);
|
|
28555
28562
|
|
|
28563
|
+
/**
|
|
28564
|
+
* IO Device Utilities
|
|
28565
|
+
* Shared utility functions for attaching IO devices to smart components.
|
|
28566
|
+
* Used by both drag-and-drop (addComponent) and import (loadLibraryModel) flows.
|
|
28567
|
+
*/
|
|
28568
|
+
|
|
28569
|
+
/**
|
|
28570
|
+
* Attach IO device models to a smart component from cached models.
|
|
28571
|
+
* Each device referenced in componentData.attachedDevices is looked up
|
|
28572
|
+
* in the model preloader cache, cloned, positioned, and added as a child.
|
|
28573
|
+
*
|
|
28574
|
+
* @param {THREE.Object3D} componentModel - The parent component model
|
|
28575
|
+
* @param {Object} componentData - Component dictionary entry (has attachedDevices)
|
|
28576
|
+
* @param {Object} modelPreloader - ModelPreloader instance with cache and componentDictionary
|
|
28577
|
+
* @param {string} parentComponentId - The parent component's UUID
|
|
28578
|
+
* @returns {void}
|
|
28579
|
+
*/
|
|
28580
|
+
function attachIODevicesToComponent(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
28581
|
+
var attachedDevices = componentData.attachedDevices;
|
|
28582
|
+
if (!attachedDevices || Object.keys(attachedDevices).length === 0) {
|
|
28583
|
+
return;
|
|
28584
|
+
}
|
|
28585
|
+
console.log("\uD83D\uDD0C attachIODevicesToComponent(): Attaching ".concat(Object.keys(attachedDevices).length, " IO devices to smart component"));
|
|
28586
|
+
for (var _i = 0, _Object$entries = Object.entries(attachedDevices); _i < _Object$entries.length; _i++) {
|
|
28587
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
28588
|
+
attachmentId = _Object$entries$_i[0],
|
|
28589
|
+
attachment = _Object$entries$_i[1];
|
|
28590
|
+
try {
|
|
28591
|
+
var _modelPreloader$compo, _deviceData$ioConfig, _deviceData$ioConfig2, _deviceData$ioConfig3, _attachment$attachmen;
|
|
28592
|
+
var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
28593
|
+
if (!deviceData || !deviceData.modelKey) {
|
|
28594
|
+
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary, skipping"));
|
|
28595
|
+
continue;
|
|
28596
|
+
}
|
|
28597
|
+
var cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
28598
|
+
if (!cachedDevice) {
|
|
28599
|
+
console.warn("\u26A0\uFE0F IO device model not in cache: ".concat(deviceData.modelKey, ", skipping"));
|
|
28600
|
+
continue;
|
|
28601
|
+
}
|
|
28602
|
+
|
|
28603
|
+
// Clone so each component instance owns its own io-device subtree and materials.
|
|
28604
|
+
// Without this, all placed copies of the same smart component share the cached
|
|
28605
|
+
// object, causing material mutations (from behaviors) to bleed across instances.
|
|
28606
|
+
var deviceModel = cachedDevice.clone();
|
|
28607
|
+
deviceModel.traverse(function (child) {
|
|
28608
|
+
if (child.isMesh && child.material) {
|
|
28609
|
+
child.material = Array.isArray(child.material) ? child.material.map(function (m) {
|
|
28610
|
+
return m.clone();
|
|
28611
|
+
}) : child.material.clone();
|
|
28612
|
+
}
|
|
28613
|
+
});
|
|
28614
|
+
|
|
28615
|
+
// Name the device model
|
|
28616
|
+
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
28617
|
+
|
|
28618
|
+
// Set user data for identification — include ioConfig data points so the
|
|
28619
|
+
// component tooltip can render state displays without an extra lookup.
|
|
28620
|
+
deviceModel.userData = {
|
|
28621
|
+
objectType: 'io-device',
|
|
28622
|
+
deviceId: attachment.deviceId,
|
|
28623
|
+
attachmentId: attachmentId,
|
|
28624
|
+
attachmentLabel: attachment.attachmentLabel,
|
|
28625
|
+
parentComponentId: parentComponentId,
|
|
28626
|
+
deviceName: deviceData.name || '',
|
|
28627
|
+
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
28628
|
+
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
28629
|
+
dataPoints: ((_deviceData$ioConfig = deviceData.ioConfig) === null || _deviceData$ioConfig === void 0 ? void 0 : _deviceData$ioConfig.states) || ((_deviceData$ioConfig2 = deviceData.ioConfig) === null || _deviceData$ioConfig2 === void 0 ? void 0 : _deviceData$ioConfig2.dataPoints) || [],
|
|
28630
|
+
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
28631
|
+
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output',
|
|
28632
|
+
// Signal wiring sourced from this attachment (for state propagation reference)
|
|
28633
|
+
signalOutputs: attachment.signalOutputs || []
|
|
28634
|
+
};
|
|
28635
|
+
|
|
28636
|
+
// Position at the attachment point
|
|
28637
|
+
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
28638
|
+
var pos = attachment.attachmentPoint.position;
|
|
28639
|
+
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
28640
|
+
}
|
|
28641
|
+
|
|
28642
|
+
// IO device models are authored at the same real-world unit scale
|
|
28643
|
+
// as the host component, so keep them at their natural (1:1) size.
|
|
28644
|
+
// Note: attachmentPoint.scale is the connector marker sphere size,
|
|
28645
|
+
// NOT a desired device model scale.
|
|
28646
|
+
deviceModel.scale.setScalar(1);
|
|
28647
|
+
|
|
28648
|
+
// Add as child of the component
|
|
28649
|
+
componentModel.add(deviceModel);
|
|
28650
|
+
console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
|
|
28651
|
+
position: deviceModel.position,
|
|
28652
|
+
scale: deviceModel.scale
|
|
28653
|
+
});
|
|
28654
|
+
} catch (err) {
|
|
28655
|
+
console.error("\u274C Error attaching IO device ".concat(attachment.deviceId, ":"), err);
|
|
28656
|
+
}
|
|
28657
|
+
}
|
|
28658
|
+
}
|
|
28659
|
+
|
|
28556
28660
|
var ModelManager = /*#__PURE__*/function () {
|
|
28557
28661
|
function ModelManager(sceneViewer) {
|
|
28558
28662
|
_classCallCheck(this, ModelManager);
|
|
@@ -28636,6 +28740,11 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28636
28740
|
libraryModel.add(connector);
|
|
28637
28741
|
});
|
|
28638
28742
|
|
|
28743
|
+
// Attach IO devices for smart components (import flow)
|
|
28744
|
+
if (componentData.isSmart && componentData.attachedDevices) {
|
|
28745
|
+
attachIODevicesToComponent(libraryModel, componentData, modelPreloader, originalProps.uuid);
|
|
28746
|
+
}
|
|
28747
|
+
|
|
28639
28748
|
// Replace mesh in scene
|
|
28640
28749
|
this._replaceMeshInScene(targetMesh, libraryModel, originalProps.parent, component);
|
|
28641
28750
|
console.log("\uD83C\uDF89 ".concat((_jsonEntry$userData3 = jsonEntry.userData) === null || _jsonEntry$userData3 === void 0 ? void 0 : _jsonEntry$userData3.libraryId, " GLB model successfully rendered in scene"));
|
|
@@ -28712,7 +28821,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28712
28821
|
value: (function () {
|
|
28713
28822
|
var _getLibraryModel2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(modelKey, libraryId) {
|
|
28714
28823
|
var _this2 = this;
|
|
28715
|
-
var gltfScene, preloaderStatus, modelPath, gltf, _t2, _t3;
|
|
28824
|
+
var gltfScene, preloaderStatus, modelPath, gltf, _t2, _t3, _t4;
|
|
28716
28825
|
return _regenerator().w(function (_context2) {
|
|
28717
28826
|
while (1) switch (_context2.n) {
|
|
28718
28827
|
case 0:
|
|
@@ -28749,25 +28858,47 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28749
28858
|
console.warn("\u26A0\uFE0F Preloading failed:", _t2);
|
|
28750
28859
|
case 6:
|
|
28751
28860
|
_context2.p = 6;
|
|
28861
|
+
if (!modelPreloader.urlResolver) {
|
|
28862
|
+
_context2.n = 11;
|
|
28863
|
+
break;
|
|
28864
|
+
}
|
|
28865
|
+
_context2.p = 7;
|
|
28866
|
+
_context2.n = 8;
|
|
28867
|
+
return modelPreloader.urlResolver(modelKey);
|
|
28868
|
+
case 8:
|
|
28869
|
+
modelPath = _context2.v;
|
|
28870
|
+
console.log("\uD83D\uDD17 Resolved URL for ".concat(modelKey));
|
|
28871
|
+
_context2.n = 10;
|
|
28872
|
+
break;
|
|
28873
|
+
case 9:
|
|
28874
|
+
_context2.p = 9;
|
|
28875
|
+
_t3 = _context2.v;
|
|
28876
|
+
console.warn("\u26A0\uFE0F URL resolver failed for ".concat(modelKey, ", falling back to local path:"), _t3);
|
|
28877
|
+
modelPath = "".concat(modelPreloader.modelsBasePath).concat(modelKey);
|
|
28878
|
+
case 10:
|
|
28879
|
+
_context2.n = 12;
|
|
28880
|
+
break;
|
|
28881
|
+
case 11:
|
|
28752
28882
|
modelPath = "".concat(modelPreloader.modelsBasePath).concat(modelKey);
|
|
28883
|
+
case 12:
|
|
28753
28884
|
console.log("\uD83D\uDCC2 Fallback loading from: ".concat(modelPath));
|
|
28754
|
-
_context2.n =
|
|
28885
|
+
_context2.n = 13;
|
|
28755
28886
|
return new Promise(function (resolve, reject) {
|
|
28756
28887
|
_this2.sceneViewer.gltfLoader.load(modelPath, resolve, undefined, reject);
|
|
28757
28888
|
});
|
|
28758
|
-
case
|
|
28889
|
+
case 13:
|
|
28759
28890
|
gltf = _context2.v;
|
|
28760
28891
|
if (libraryId) {
|
|
28761
28892
|
modelPreloader.cacheModel(modelKey, gltf.scene.clone(), libraryId);
|
|
28762
28893
|
}
|
|
28763
28894
|
return _context2.a(2, gltf.scene);
|
|
28764
|
-
case
|
|
28765
|
-
_context2.p =
|
|
28766
|
-
|
|
28767
|
-
console.error("Failed to load model ".concat(modelKey, ":"),
|
|
28895
|
+
case 14:
|
|
28896
|
+
_context2.p = 14;
|
|
28897
|
+
_t4 = _context2.v;
|
|
28898
|
+
console.error("Failed to load model ".concat(modelKey, ":"), _t4);
|
|
28768
28899
|
return _context2.a(2, null);
|
|
28769
28900
|
}
|
|
28770
|
-
}, _callee2, null, [[6,
|
|
28901
|
+
}, _callee2, null, [[7, 9], [6, 14], [2, 5]]);
|
|
28771
28902
|
}));
|
|
28772
28903
|
function _getLibraryModel(_x4, _x5) {
|
|
28773
28904
|
return _getLibraryModel2.apply(this, arguments);
|
|
@@ -28866,7 +28997,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28866
28997
|
key: "verifyModelPreloaderCache",
|
|
28867
28998
|
value: (function () {
|
|
28868
28999
|
var _verifyModelPreloaderCache = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
28869
|
-
var preloaderStatus,
|
|
29000
|
+
var preloaderStatus, _t5;
|
|
28870
29001
|
return _regenerator().w(function (_context3) {
|
|
28871
29002
|
while (1) switch (_context3.n) {
|
|
28872
29003
|
case 0:
|
|
@@ -28889,8 +29020,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28889
29020
|
break;
|
|
28890
29021
|
case 3:
|
|
28891
29022
|
_context3.p = 3;
|
|
28892
|
-
|
|
28893
|
-
console.warn('⚠️ Model preloading failed, some models may load directly:',
|
|
29023
|
+
_t5 = _context3.v;
|
|
29024
|
+
console.warn('⚠️ Model preloading failed, some models may load directly:', _t5);
|
|
28894
29025
|
case 4:
|
|
28895
29026
|
return _context3.a(2, preloaderStatus);
|
|
28896
29027
|
}
|
|
@@ -28909,7 +29040,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28909
29040
|
key: "preloadMissingModels",
|
|
28910
29041
|
value: (function () {
|
|
28911
29042
|
var _preloadMissingModels = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(data, componentDictionary) {
|
|
28912
|
-
var _data$scene, _data$scene2, requiredModels, preloaderStatus, cachedModels, missingModels, basePath, modelUrls, _iterator, _step, modelKey,
|
|
29043
|
+
var _data$scene, _data$scene2, requiredModels, preloaderStatus, cachedModels, missingModels, basePath, modelUrls, _iterator, _step, modelKey, _t6, _t7;
|
|
28913
29044
|
return _regenerator().w(function (_context4) {
|
|
28914
29045
|
while (1) switch (_context4.n) {
|
|
28915
29046
|
case 0:
|
|
@@ -29004,8 +29135,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29004
29135
|
break;
|
|
29005
29136
|
case 7:
|
|
29006
29137
|
_context4.p = 7;
|
|
29007
|
-
|
|
29008
|
-
console.warn("\u274C Failed to preload missing model ".concat(modelKey, ":"),
|
|
29138
|
+
_t6 = _context4.v;
|
|
29139
|
+
console.warn("\u274C Failed to preload missing model ".concat(modelKey, ":"), _t6);
|
|
29009
29140
|
case 8:
|
|
29010
29141
|
_context4.n = 4;
|
|
29011
29142
|
break;
|
|
@@ -29014,8 +29145,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29014
29145
|
break;
|
|
29015
29146
|
case 10:
|
|
29016
29147
|
_context4.p = 10;
|
|
29017
|
-
|
|
29018
|
-
_iterator.e(
|
|
29148
|
+
_t7 = _context4.v;
|
|
29149
|
+
_iterator.e(_t7);
|
|
29019
29150
|
case 11:
|
|
29020
29151
|
_context4.p = 11;
|
|
29021
29152
|
_iterator.f();
|
|
@@ -29120,7 +29251,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29120
29251
|
key: "loadComponentDictionary",
|
|
29121
29252
|
value: (function () {
|
|
29122
29253
|
var _loadComponentDictionary = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
|
|
29123
|
-
var response, dict,
|
|
29254
|
+
var response, dict, _t8;
|
|
29124
29255
|
return _regenerator().w(function (_context6) {
|
|
29125
29256
|
while (1) switch (_context6.n) {
|
|
29126
29257
|
case 0:
|
|
@@ -29138,8 +29269,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29138
29269
|
return _context6.a(2, dict);
|
|
29139
29270
|
case 3:
|
|
29140
29271
|
_context6.p = 3;
|
|
29141
|
-
|
|
29142
|
-
console.warn('⚠️ Could not load component dictionary:',
|
|
29272
|
+
_t8 = _context6.v;
|
|
29273
|
+
console.warn('⚠️ Could not load component dictionary:', _t8);
|
|
29143
29274
|
return _context6.a(2, {});
|
|
29144
29275
|
}
|
|
29145
29276
|
}, _callee6, null, [[0, 3]]);
|
|
@@ -29935,7 +30066,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
29935
30066
|
return createSceneMaterials;
|
|
29936
30067
|
}()
|
|
29937
30068
|
/**
|
|
29938
|
-
* Helper function to create geometries
|
|
30069
|
+
* Helper function to create geometries for connectors and gateways
|
|
30070
|
+
* Components use GLB geometry directly, no placeholder needed
|
|
29939
30071
|
*/
|
|
29940
30072
|
)
|
|
29941
30073
|
}, {
|
|
@@ -29950,7 +30082,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
29950
30082
|
return geometries;
|
|
29951
30083
|
}
|
|
29952
30084
|
|
|
29953
|
-
// Create geometries
|
|
30085
|
+
// Create geometries only for connectors and gateways (components use GLB geometry)
|
|
29954
30086
|
data.scene.children.forEach(function (child) {
|
|
29955
30087
|
var _child$userData, _child$userData2;
|
|
29956
30088
|
// Skip manual segments - they create their own geometry
|
|
@@ -29959,42 +30091,28 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
29959
30091
|
console.log("\u23ED\uFE0F Skipping geometry creation for manual segment: ".concat(child.uuid));
|
|
29960
30092
|
return;
|
|
29961
30093
|
}
|
|
29962
|
-
if ((_child$userData2 = child.userData) !== null && _child$userData2 !== void 0 && _child$userData2.libraryId && componentDictionary[child.userData.libraryId]) {
|
|
29963
|
-
var component = componentDictionary[child.userData.libraryId];
|
|
29964
|
-
var boundingBox = component.boundingBox;
|
|
29965
30094
|
|
|
29966
|
-
|
|
29967
|
-
|
|
30095
|
+
// Skip components - they will use GLB geometry directly
|
|
30096
|
+
if ((_child$userData2 = child.userData) !== null && _child$userData2 !== void 0 && _child$userData2.libraryId) {
|
|
30097
|
+
return;
|
|
30098
|
+
}
|
|
29968
30099
|
|
|
29969
|
-
|
|
29970
|
-
|
|
29971
|
-
|
|
29972
|
-
|
|
29973
|
-
//
|
|
29974
|
-
|
|
29975
|
-
|
|
29976
|
-
|
|
29977
|
-
|
|
29978
|
-
if (
|
|
29979
|
-
//
|
|
29980
|
-
var
|
|
29981
|
-
|
|
29982
|
-
|
|
29983
|
-
// Match computed gateway size (0.15) for gateways, keep 0.1 for connectors
|
|
29984
|
-
var sphereRadius = isGateway ? 0.15 : 0.1;
|
|
29985
|
-
geometries[geometryKey] = new THREE__namespace.SphereGeometry(sphereRadius, 16, 16);
|
|
29986
|
-
console.log("\uD83D\uDD2E Created shared sphere geometry for ".concat(isGateway ? 'gateways' : 'connectors', " (radius: ").concat(sphereRadius, ")"));
|
|
29987
|
-
}
|
|
30100
|
+
// For non-library objects (connectors, gateways), create shared sphere geometry
|
|
30101
|
+
var isConnectorOrGateway = child.uuid && (child.uuid.toLowerCase().includes('connector') || child.uuid.toLowerCase().includes('gateway'));
|
|
30102
|
+
console.log("createSceneGeometries child:", child);
|
|
30103
|
+
if (isConnectorOrGateway) {
|
|
30104
|
+
// Check if position exists and is not at origin
|
|
30105
|
+
if (child.position && !(child.position.x == 0 && child.position.y == 0 && child.position.z == 0)) {
|
|
30106
|
+
// Determine if this is a gateway or connector
|
|
30107
|
+
var isGateway = child.uuid.toLowerCase().includes('gateway');
|
|
30108
|
+
var geometryKey = isGateway ? 'GATEWAY_SPHERE' : 'CONNECTOR_GATEWAY_SPHERE';
|
|
30109
|
+
if (!geometries[geometryKey]) {
|
|
30110
|
+
// Match computed gateway size (0.15) for gateways, keep 0.1 for connectors
|
|
30111
|
+
var sphereRadius = isGateway ? 0.15 : 0.1;
|
|
30112
|
+
geometries[geometryKey] = new THREE__namespace.SphereGeometry(sphereRadius, 16, 16);
|
|
30113
|
+
console.log("\uD83D\uDD2E Created shared sphere geometry for ".concat(isGateway ? 'gateways' : 'connectors', " (radius: ").concat(sphereRadius, ")"));
|
|
29988
30114
|
}
|
|
29989
30115
|
}
|
|
29990
|
-
// else {
|
|
29991
|
-
// // Default fallback geometry
|
|
29992
|
-
// const geometryKey = child.geometry || 'FALLBACK_BOX'
|
|
29993
|
-
// if (!geometries[geometryKey]) {
|
|
29994
|
-
// geometries[geometryKey] = new THREE.BoxGeometry(1, 1, 1)
|
|
29995
|
-
// console.log(`📦 Created fallback box geometry`)
|
|
29996
|
-
// }
|
|
29997
|
-
// }
|
|
29998
30116
|
}
|
|
29999
30117
|
});
|
|
30000
30118
|
return geometries;
|
|
@@ -30758,7 +30876,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
30758
30876
|
key: "_createBasicSceneObjects",
|
|
30759
30877
|
value: (function () {
|
|
30760
30878
|
var _createBasicSceneObjects2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
30761
|
-
var
|
|
30879
|
+
var _this$sceneViewer$cen,
|
|
30880
|
+
_this4 = this;
|
|
30762
30881
|
var componentDictionary, _yield$this$createSce, materials, crosscubeTextureSet, geometries, libraryObjectsToReplace;
|
|
30763
30882
|
return _regenerator().w(function (_context6) {
|
|
30764
30883
|
while (1) switch (_context6.n) {
|
|
@@ -30769,20 +30888,33 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
30769
30888
|
}
|
|
30770
30889
|
throw new Error('Invalid scene data structure: data.scene.children must be an array');
|
|
30771
30890
|
case 1:
|
|
30891
|
+
// Use the extended component dictionary (includes S3 components) if available,
|
|
30892
|
+
// otherwise fall back to loading from static file
|
|
30893
|
+
componentDictionary = (_this$sceneViewer$cen = this.sceneViewer.centralPlant) === null || _this$sceneViewer$cen === void 0 || (_this$sceneViewer$cen = _this$sceneViewer$cen.managers) === null || _this$sceneViewer$cen === void 0 || (_this$sceneViewer$cen = _this$sceneViewer$cen.componentDataManager) === null || _this$sceneViewer$cen === void 0 ? void 0 : _this$sceneViewer$cen.componentDictionary;
|
|
30894
|
+
if (componentDictionary) {
|
|
30895
|
+
_context6.n = 3;
|
|
30896
|
+
break;
|
|
30897
|
+
}
|
|
30898
|
+
console.log('⚠️ Extended dictionary not available, loading from static file');
|
|
30772
30899
|
_context6.n = 2;
|
|
30773
30900
|
return this.modelManager.loadComponentDictionary();
|
|
30774
30901
|
case 2:
|
|
30775
30902
|
componentDictionary = _context6.v;
|
|
30903
|
+
_context6.n = 4;
|
|
30904
|
+
break;
|
|
30905
|
+
case 3:
|
|
30906
|
+
console.log("\u2705 Using extended component dictionary (".concat(Object.keys(componentDictionary).length, " components)"));
|
|
30907
|
+
case 4:
|
|
30776
30908
|
// Inject connector children from component dictionary into scene data
|
|
30777
30909
|
this._injectConnectorChildrenFromDictionary(data, componentDictionary);
|
|
30778
30910
|
|
|
30779
30911
|
// Ensure models are preloaded
|
|
30780
|
-
_context6.n =
|
|
30912
|
+
_context6.n = 5;
|
|
30781
30913
|
return this.modelManager.preloadMissingModels(data, componentDictionary);
|
|
30782
|
-
case
|
|
30783
|
-
_context6.n =
|
|
30914
|
+
case 5:
|
|
30915
|
+
_context6.n = 6;
|
|
30784
30916
|
return this.createSceneMaterials(data);
|
|
30785
|
-
case
|
|
30917
|
+
case 6:
|
|
30786
30918
|
_yield$this$createSce = _context6.v;
|
|
30787
30919
|
materials = _yield$this$createSce.materials;
|
|
30788
30920
|
crosscubeTextureSet = _yield$this$createSce.crosscubeTextureSet;
|
|
@@ -36524,7 +36656,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36524
36656
|
|
|
36525
36657
|
// Add attached IO device models for smart components
|
|
36526
36658
|
if (componentData.isSmart && componentData.attachedDevices) {
|
|
36527
|
-
|
|
36659
|
+
attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
|
|
36528
36660
|
}
|
|
36529
36661
|
|
|
36530
36662
|
// Notify the component manager about the new component
|
|
@@ -36577,95 +36709,6 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36577
36709
|
}
|
|
36578
36710
|
}
|
|
36579
36711
|
|
|
36580
|
-
/**
|
|
36581
|
-
* Attach IO device models to a smart component from cached models.
|
|
36582
|
-
* Each device referenced in componentData.attachedDevices is looked up
|
|
36583
|
-
* in the model preloader cache, cloned, positioned, and added as a child.
|
|
36584
|
-
* @param {THREE.Object3D} componentModel - The parent component model
|
|
36585
|
-
* @param {Object} componentData - Component dictionary entry (has attachedDevices)
|
|
36586
|
-
* @param {Object} modelPreloader - ModelPreloader instance
|
|
36587
|
-
* @param {string} parentComponentId - The parent component's UUID
|
|
36588
|
-
* @private
|
|
36589
|
-
*/
|
|
36590
|
-
}, {
|
|
36591
|
-
key: "_attachIODevicesToComponent",
|
|
36592
|
-
value: function _attachIODevicesToComponent(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
36593
|
-
var attachedDevices = componentData.attachedDevices;
|
|
36594
|
-
console.log("\uD83D\uDD0C addComponent(): Attaching ".concat(Object.keys(attachedDevices).length, " IO devices to smart component"));
|
|
36595
|
-
for (var _i = 0, _Object$entries = Object.entries(attachedDevices); _i < _Object$entries.length; _i++) {
|
|
36596
|
-
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
36597
|
-
attachmentId = _Object$entries$_i[0],
|
|
36598
|
-
attachment = _Object$entries$_i[1];
|
|
36599
|
-
try {
|
|
36600
|
-
var _modelPreloader$compo, _deviceData$ioConfig, _deviceData$ioConfig2, _deviceData$ioConfig3, _attachment$attachmen;
|
|
36601
|
-
var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
36602
|
-
if (!deviceData || !deviceData.modelKey) {
|
|
36603
|
-
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary, skipping"));
|
|
36604
|
-
continue;
|
|
36605
|
-
}
|
|
36606
|
-
var cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
36607
|
-
if (!cachedDevice) {
|
|
36608
|
-
console.warn("\u26A0\uFE0F IO device model not in cache: ".concat(deviceData.modelKey, ", skipping"));
|
|
36609
|
-
continue;
|
|
36610
|
-
}
|
|
36611
|
-
|
|
36612
|
-
// Clone so each component instance owns its own io-device subtree and materials.
|
|
36613
|
-
// Without this, all placed copies of the same smart component share the cached
|
|
36614
|
-
// object, causing material mutations (from behaviors) to bleed across instances.
|
|
36615
|
-
var deviceModel = cachedDevice.clone();
|
|
36616
|
-
deviceModel.traverse(function (child) {
|
|
36617
|
-
if (child.isMesh && child.material) {
|
|
36618
|
-
child.material = Array.isArray(child.material) ? child.material.map(function (m) {
|
|
36619
|
-
return m.clone();
|
|
36620
|
-
}) : child.material.clone();
|
|
36621
|
-
}
|
|
36622
|
-
});
|
|
36623
|
-
|
|
36624
|
-
// Name the device model
|
|
36625
|
-
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
36626
|
-
|
|
36627
|
-
// Set user data for identification — include ioConfig data points so the
|
|
36628
|
-
// component tooltip can render state displays without an extra lookup.
|
|
36629
|
-
deviceModel.userData = {
|
|
36630
|
-
objectType: 'io-device',
|
|
36631
|
-
deviceId: attachment.deviceId,
|
|
36632
|
-
attachmentId: attachmentId,
|
|
36633
|
-
attachmentLabel: attachment.attachmentLabel,
|
|
36634
|
-
parentComponentId: parentComponentId,
|
|
36635
|
-
deviceName: deviceData.name || '',
|
|
36636
|
-
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
36637
|
-
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
36638
|
-
dataPoints: ((_deviceData$ioConfig = deviceData.ioConfig) === null || _deviceData$ioConfig === void 0 ? void 0 : _deviceData$ioConfig.states) || ((_deviceData$ioConfig2 = deviceData.ioConfig) === null || _deviceData$ioConfig2 === void 0 ? void 0 : _deviceData$ioConfig2.dataPoints) || [],
|
|
36639
|
-
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
36640
|
-
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output',
|
|
36641
|
-
// Signal wiring sourced from this attachment (for state propagation reference)
|
|
36642
|
-
signalOutputs: attachment.signalOutputs || []
|
|
36643
|
-
};
|
|
36644
|
-
|
|
36645
|
-
// Position at the attachment point
|
|
36646
|
-
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
36647
|
-
var pos = attachment.attachmentPoint.position;
|
|
36648
|
-
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
36649
|
-
}
|
|
36650
|
-
|
|
36651
|
-
// IO device models are authored at the same real-world unit scale
|
|
36652
|
-
// as the host component, so keep them at their natural (1:1) size.
|
|
36653
|
-
// Note: attachmentPoint.scale is the connector marker sphere size,
|
|
36654
|
-
// NOT a desired device model scale.
|
|
36655
|
-
deviceModel.scale.setScalar(1);
|
|
36656
|
-
|
|
36657
|
-
// Add as child of the component
|
|
36658
|
-
componentModel.add(deviceModel);
|
|
36659
|
-
console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
|
|
36660
|
-
position: deviceModel.position,
|
|
36661
|
-
scale: deviceModel.scale
|
|
36662
|
-
});
|
|
36663
|
-
} catch (err) {
|
|
36664
|
-
console.error("\u274C Error attaching IO device ".concat(attachment.deviceId, ":"), err);
|
|
36665
|
-
}
|
|
36666
|
-
}
|
|
36667
|
-
}
|
|
36668
|
-
|
|
36669
36712
|
/**
|
|
36670
36713
|
* Delete a component from the scene by componentId (internal implementation)
|
|
36671
36714
|
* @param {string} componentId - The UUID of the component to delete
|
|
@@ -36771,7 +36814,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
36771
36814
|
* Initialize the CentralPlant manager
|
|
36772
36815
|
*
|
|
36773
36816
|
* @constructor
|
|
36774
|
-
* @version 0.1.
|
|
36817
|
+
* @version 0.1.90
|
|
36775
36818
|
* @updated 2025-10-22
|
|
36776
36819
|
*
|
|
36777
36820
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -38271,6 +38314,50 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38271
38314
|
}
|
|
38272
38315
|
return removeComponentFromDictionary;
|
|
38273
38316
|
}()
|
|
38317
|
+
/**
|
|
38318
|
+
* Get library IDs from scene data that are missing from the component dictionary
|
|
38319
|
+
* @param {Object} sceneData - Scene JSON data to analyze
|
|
38320
|
+
* @returns {string[]} Array of library IDs that are not in the current component dictionary
|
|
38321
|
+
* @description Analyzes scene data to find components whose libraryId is not present in the
|
|
38322
|
+
* component dictionary. This is useful for detecting S3 components that need to be fetched
|
|
38323
|
+
* before importing a scene.
|
|
38324
|
+
* @example
|
|
38325
|
+
* // Check for missing components before import
|
|
38326
|
+
* const missingIds = centralPlant.getMissingLibraryIds(sceneJson);
|
|
38327
|
+
* if (missingIds.length > 0) {
|
|
38328
|
+
* // Fetch missing S3 components
|
|
38329
|
+
* await fetchS3Components(missingIds);
|
|
38330
|
+
* await centralPlant.extendComponentDictionary(fetchedComponents);
|
|
38331
|
+
* }
|
|
38332
|
+
* // Now safe to import
|
|
38333
|
+
* await centralPlant.importScene(sceneJson);
|
|
38334
|
+
*/
|
|
38335
|
+
)
|
|
38336
|
+
}, {
|
|
38337
|
+
key: "getMissingLibraryIds",
|
|
38338
|
+
value: function getMissingLibraryIds(sceneData) {
|
|
38339
|
+
var _sceneData$scene, _this$managers$compon;
|
|
38340
|
+
if (!(sceneData !== null && sceneData !== void 0 && (_sceneData$scene = sceneData.scene) !== null && _sceneData$scene !== void 0 && _sceneData$scene.children) || !Array.isArray(sceneData.scene.children)) {
|
|
38341
|
+
return [];
|
|
38342
|
+
}
|
|
38343
|
+
var componentDictionary = ((_this$managers$compon = this.managers.componentDataManager) === null || _this$managers$compon === void 0 ? void 0 : _this$managers$compon.componentDictionary) || {};
|
|
38344
|
+
var missingIds = [];
|
|
38345
|
+
sceneData.scene.children.forEach(function (child) {
|
|
38346
|
+
var _child$userData;
|
|
38347
|
+
var libraryId = (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.libraryId;
|
|
38348
|
+
if (libraryId && !componentDictionary[libraryId]) {
|
|
38349
|
+
// Only add unique IDs
|
|
38350
|
+
if (!missingIds.includes(libraryId)) {
|
|
38351
|
+
missingIds.push(libraryId);
|
|
38352
|
+
}
|
|
38353
|
+
}
|
|
38354
|
+
});
|
|
38355
|
+
if (missingIds.length > 0) {
|
|
38356
|
+
console.log("\uD83D\uDD0D Found ".concat(missingIds.length, " missing library IDs in scene data:"), missingIds);
|
|
38357
|
+
}
|
|
38358
|
+
return missingIds;
|
|
38359
|
+
}
|
|
38360
|
+
|
|
38274
38361
|
/**
|
|
38275
38362
|
* Select an object (component, connector, or gateway) in the scene by its ID
|
|
38276
38363
|
* @param {string} objectId - The UUID or name of the object to select
|
|
@@ -38307,7 +38394,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38307
38394
|
* centralPlant.selectComponent(targetObject.uuid);
|
|
38308
38395
|
* }
|
|
38309
38396
|
*/
|
|
38310
|
-
)
|
|
38311
38397
|
}, {
|
|
38312
38398
|
key: "selectComponent",
|
|
38313
38399
|
value: function selectComponent(objectId) {
|
|
@@ -38336,8 +38422,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38336
38422
|
// If still not found, try finding by originalUuid in userData
|
|
38337
38423
|
if (!targetObject) {
|
|
38338
38424
|
this.sceneViewer.scene.traverse(function (child) {
|
|
38339
|
-
var _child$
|
|
38340
|
-
if (((_child$
|
|
38425
|
+
var _child$userData2;
|
|
38426
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === objectId) {
|
|
38341
38427
|
targetObject = child;
|
|
38342
38428
|
return;
|
|
38343
38429
|
}
|