@2112-lab/central-plant 0.1.88 → 0.1.91
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 +302 -157
- 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/componentManager.js +5 -1
- package/dist/cjs/src/managers/scene/modelManager.js +53 -22
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +40 -39
- package/dist/cjs/src/utils/ioDeviceUtils.js +163 -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/componentManager.js +5 -1
- package/dist/esm/src/managers/scene/modelManager.js +53 -22
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +40 -39
- package/dist/esm/src/utils/ioDeviceUtils.js +159 -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
|
|
@@ -28556,6 +28560,162 @@ var BehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
28556
28560
|
}]);
|
|
28557
28561
|
}(BaseDisposable);
|
|
28558
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
|
+
* If a device model is not in cache, it will be preloaded first.
|
|
28574
|
+
*
|
|
28575
|
+
* @param {THREE.Object3D} componentModel - The parent component model
|
|
28576
|
+
* @param {Object} componentData - Component dictionary entry (has attachedDevices)
|
|
28577
|
+
* @param {Object} modelPreloader - ModelPreloader instance with cache and componentDictionary
|
|
28578
|
+
* @param {string} parentComponentId - The parent component's UUID
|
|
28579
|
+
* @returns {Promise<void>}
|
|
28580
|
+
*/
|
|
28581
|
+
function attachIODevicesToComponent(_x, _x2, _x3, _x4) {
|
|
28582
|
+
return _attachIODevicesToComponent.apply(this, arguments);
|
|
28583
|
+
}
|
|
28584
|
+
function _attachIODevicesToComponent() {
|
|
28585
|
+
_attachIODevicesToComponent = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
28586
|
+
var attachedDevices, _i, _Object$entries, _Object$entries$_i, attachmentId, attachment, _modelPreloader$compo, _deviceData$ioConfig, _deviceData$ioConfig2, _deviceData$ioConfig3, _attachment$attachmen, deviceData, cachedDevice, _modelPreloader$loadi, deviceModel, pos, _t, _t2;
|
|
28587
|
+
return _regenerator().w(function (_context) {
|
|
28588
|
+
while (1) switch (_context.n) {
|
|
28589
|
+
case 0:
|
|
28590
|
+
attachedDevices = componentData.attachedDevices;
|
|
28591
|
+
if (!(!attachedDevices || Object.keys(attachedDevices).length === 0)) {
|
|
28592
|
+
_context.n = 1;
|
|
28593
|
+
break;
|
|
28594
|
+
}
|
|
28595
|
+
return _context.a(2);
|
|
28596
|
+
case 1:
|
|
28597
|
+
console.log("\uD83D\uDD0C attachIODevicesToComponent(): Attaching ".concat(Object.keys(attachedDevices).length, " IO devices to smart component"));
|
|
28598
|
+
_i = 0, _Object$entries = Object.entries(attachedDevices);
|
|
28599
|
+
case 2:
|
|
28600
|
+
if (!(_i < _Object$entries.length)) {
|
|
28601
|
+
_context.n = 14;
|
|
28602
|
+
break;
|
|
28603
|
+
}
|
|
28604
|
+
_Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), attachmentId = _Object$entries$_i[0], attachment = _Object$entries$_i[1];
|
|
28605
|
+
_context.p = 3;
|
|
28606
|
+
deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
28607
|
+
if (!(!deviceData || !deviceData.modelKey)) {
|
|
28608
|
+
_context.n = 4;
|
|
28609
|
+
break;
|
|
28610
|
+
}
|
|
28611
|
+
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary, skipping"));
|
|
28612
|
+
return _context.a(3, 13);
|
|
28613
|
+
case 4:
|
|
28614
|
+
// Try to get from cache first
|
|
28615
|
+
cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId); // If not in cache, try to preload it
|
|
28616
|
+
if (cachedDevice) {
|
|
28617
|
+
_context.n = 10;
|
|
28618
|
+
break;
|
|
28619
|
+
}
|
|
28620
|
+
console.log("\uD83D\uDD04 IO device model not in cache, preloading: ".concat(deviceData.modelKey));
|
|
28621
|
+
_context.p = 5;
|
|
28622
|
+
if (!((_modelPreloader$loadi = modelPreloader.loadingPromises) !== null && _modelPreloader$loadi !== void 0 && _modelPreloader$loadi.has(deviceData.modelKey))) {
|
|
28623
|
+
_context.n = 7;
|
|
28624
|
+
break;
|
|
28625
|
+
}
|
|
28626
|
+
_context.n = 6;
|
|
28627
|
+
return modelPreloader.loadingPromises.get(deviceData.modelKey);
|
|
28628
|
+
case 6:
|
|
28629
|
+
_context.n = 8;
|
|
28630
|
+
break;
|
|
28631
|
+
case 7:
|
|
28632
|
+
_context.n = 8;
|
|
28633
|
+
return modelPreloader.preloadSingleModel(deviceData.modelKey);
|
|
28634
|
+
case 8:
|
|
28635
|
+
cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
28636
|
+
_context.n = 10;
|
|
28637
|
+
break;
|
|
28638
|
+
case 9:
|
|
28639
|
+
_context.p = 9;
|
|
28640
|
+
_t = _context.v;
|
|
28641
|
+
console.warn("\u26A0\uFE0F Failed to preload IO device model ".concat(deviceData.modelKey, ":"), _t);
|
|
28642
|
+
case 10:
|
|
28643
|
+
if (cachedDevice) {
|
|
28644
|
+
_context.n = 11;
|
|
28645
|
+
break;
|
|
28646
|
+
}
|
|
28647
|
+
console.warn("\u26A0\uFE0F IO device model could not be loaded: ".concat(deviceData.modelKey, ", skipping"));
|
|
28648
|
+
return _context.a(3, 13);
|
|
28649
|
+
case 11:
|
|
28650
|
+
// Clone so each component instance owns its own io-device subtree and materials.
|
|
28651
|
+
// Without this, all placed copies of the same smart component share the cached
|
|
28652
|
+
// object, causing material mutations (from behaviors) to bleed across instances.
|
|
28653
|
+
deviceModel = cachedDevice.clone();
|
|
28654
|
+
deviceModel.traverse(function (child) {
|
|
28655
|
+
if (child.isMesh && child.material) {
|
|
28656
|
+
child.material = Array.isArray(child.material) ? child.material.map(function (m) {
|
|
28657
|
+
return m.clone();
|
|
28658
|
+
}) : child.material.clone();
|
|
28659
|
+
}
|
|
28660
|
+
});
|
|
28661
|
+
|
|
28662
|
+
// Name the device model
|
|
28663
|
+
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
28664
|
+
|
|
28665
|
+
// Set user data for identification — include ioConfig data points so the
|
|
28666
|
+
// component tooltip can render state displays without an extra lookup.
|
|
28667
|
+
deviceModel.userData = {
|
|
28668
|
+
objectType: 'io-device',
|
|
28669
|
+
deviceId: attachment.deviceId,
|
|
28670
|
+
attachmentId: attachmentId,
|
|
28671
|
+
attachmentLabel: attachment.attachmentLabel,
|
|
28672
|
+
parentComponentId: parentComponentId,
|
|
28673
|
+
deviceName: deviceData.name || '',
|
|
28674
|
+
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
28675
|
+
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
28676
|
+
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) || [],
|
|
28677
|
+
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
28678
|
+
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output',
|
|
28679
|
+
// Signal wiring sourced from this attachment (for state propagation reference)
|
|
28680
|
+
signalOutputs: attachment.signalOutputs || []
|
|
28681
|
+
};
|
|
28682
|
+
|
|
28683
|
+
// Position at the attachment point
|
|
28684
|
+
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
28685
|
+
pos = attachment.attachmentPoint.position;
|
|
28686
|
+
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
28687
|
+
}
|
|
28688
|
+
|
|
28689
|
+
// IO device models are authored at the same real-world unit scale
|
|
28690
|
+
// as the host component, so keep them at their natural (1:1) size.
|
|
28691
|
+
// Note: attachmentPoint.scale is the connector marker sphere size,
|
|
28692
|
+
// NOT a desired device model scale.
|
|
28693
|
+
deviceModel.scale.setScalar(1);
|
|
28694
|
+
|
|
28695
|
+
// Add as child of the component
|
|
28696
|
+
componentModel.add(deviceModel);
|
|
28697
|
+
console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
|
|
28698
|
+
position: deviceModel.position,
|
|
28699
|
+
scale: deviceModel.scale
|
|
28700
|
+
});
|
|
28701
|
+
_context.n = 13;
|
|
28702
|
+
break;
|
|
28703
|
+
case 12:
|
|
28704
|
+
_context.p = 12;
|
|
28705
|
+
_t2 = _context.v;
|
|
28706
|
+
console.error("\u274C Error attaching IO device ".concat(attachment.deviceId, ":"), _t2);
|
|
28707
|
+
case 13:
|
|
28708
|
+
_i++;
|
|
28709
|
+
_context.n = 2;
|
|
28710
|
+
break;
|
|
28711
|
+
case 14:
|
|
28712
|
+
return _context.a(2);
|
|
28713
|
+
}
|
|
28714
|
+
}, _callee, null, [[5, 9], [3, 12]]);
|
|
28715
|
+
}));
|
|
28716
|
+
return _attachIODevicesToComponent.apply(this, arguments);
|
|
28717
|
+
}
|
|
28718
|
+
|
|
28559
28719
|
var ModelManager = /*#__PURE__*/function () {
|
|
28560
28720
|
function ModelManager(sceneViewer) {
|
|
28561
28721
|
_classCallCheck(this, ModelManager);
|
|
@@ -28639,17 +28799,25 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28639
28799
|
libraryModel.add(connector);
|
|
28640
28800
|
});
|
|
28641
28801
|
|
|
28802
|
+
// Attach IO devices for smart components (import flow)
|
|
28803
|
+
if (!(componentData.isSmart && componentData.attachedDevices)) {
|
|
28804
|
+
_context.n = 4;
|
|
28805
|
+
break;
|
|
28806
|
+
}
|
|
28807
|
+
_context.n = 4;
|
|
28808
|
+
return attachIODevicesToComponent(libraryModel, componentData, modelPreloader, originalProps.uuid);
|
|
28809
|
+
case 4:
|
|
28642
28810
|
// Replace mesh in scene
|
|
28643
28811
|
this._replaceMeshInScene(targetMesh, libraryModel, originalProps.parent, component);
|
|
28644
28812
|
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"));
|
|
28645
28813
|
return _context.a(2, libraryModel);
|
|
28646
|
-
case
|
|
28647
|
-
_context.p =
|
|
28814
|
+
case 5:
|
|
28815
|
+
_context.p = 5;
|
|
28648
28816
|
_t = _context.v;
|
|
28649
28817
|
console.error("\u274C Error loading ".concat((_jsonEntry$userData4 = jsonEntry.userData) === null || _jsonEntry$userData4 === void 0 ? void 0 : _jsonEntry$userData4.libraryId, " GLB model:"), _t);
|
|
28650
28818
|
return _context.a(2, targetMesh);
|
|
28651
28819
|
}
|
|
28652
|
-
}, _callee, this, [[1,
|
|
28820
|
+
}, _callee, this, [[1, 5]]);
|
|
28653
28821
|
}));
|
|
28654
28822
|
function loadLibraryModel(_x, _x2, _x3) {
|
|
28655
28823
|
return _loadLibraryModel.apply(this, arguments);
|
|
@@ -28715,7 +28883,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28715
28883
|
value: (function () {
|
|
28716
28884
|
var _getLibraryModel2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(modelKey, libraryId) {
|
|
28717
28885
|
var _this2 = this;
|
|
28718
|
-
var gltfScene, preloaderStatus, modelPath, gltf, _t2, _t3;
|
|
28886
|
+
var gltfScene, preloaderStatus, modelPath, gltf, _t2, _t3, _t4;
|
|
28719
28887
|
return _regenerator().w(function (_context2) {
|
|
28720
28888
|
while (1) switch (_context2.n) {
|
|
28721
28889
|
case 0:
|
|
@@ -28752,25 +28920,47 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28752
28920
|
console.warn("\u26A0\uFE0F Preloading failed:", _t2);
|
|
28753
28921
|
case 6:
|
|
28754
28922
|
_context2.p = 6;
|
|
28923
|
+
if (!modelPreloader.urlResolver) {
|
|
28924
|
+
_context2.n = 11;
|
|
28925
|
+
break;
|
|
28926
|
+
}
|
|
28927
|
+
_context2.p = 7;
|
|
28928
|
+
_context2.n = 8;
|
|
28929
|
+
return modelPreloader.urlResolver(modelKey);
|
|
28930
|
+
case 8:
|
|
28931
|
+
modelPath = _context2.v;
|
|
28932
|
+
console.log("\uD83D\uDD17 Resolved URL for ".concat(modelKey));
|
|
28933
|
+
_context2.n = 10;
|
|
28934
|
+
break;
|
|
28935
|
+
case 9:
|
|
28936
|
+
_context2.p = 9;
|
|
28937
|
+
_t3 = _context2.v;
|
|
28938
|
+
console.warn("\u26A0\uFE0F URL resolver failed for ".concat(modelKey, ", falling back to local path:"), _t3);
|
|
28755
28939
|
modelPath = "".concat(modelPreloader.modelsBasePath).concat(modelKey);
|
|
28940
|
+
case 10:
|
|
28941
|
+
_context2.n = 12;
|
|
28942
|
+
break;
|
|
28943
|
+
case 11:
|
|
28944
|
+
modelPath = "".concat(modelPreloader.modelsBasePath).concat(modelKey);
|
|
28945
|
+
case 12:
|
|
28756
28946
|
console.log("\uD83D\uDCC2 Fallback loading from: ".concat(modelPath));
|
|
28757
|
-
_context2.n =
|
|
28947
|
+
_context2.n = 13;
|
|
28758
28948
|
return new Promise(function (resolve, reject) {
|
|
28759
28949
|
_this2.sceneViewer.gltfLoader.load(modelPath, resolve, undefined, reject);
|
|
28760
28950
|
});
|
|
28761
|
-
case
|
|
28951
|
+
case 13:
|
|
28762
28952
|
gltf = _context2.v;
|
|
28763
28953
|
if (libraryId) {
|
|
28764
28954
|
modelPreloader.cacheModel(modelKey, gltf.scene.clone(), libraryId);
|
|
28765
28955
|
}
|
|
28766
28956
|
return _context2.a(2, gltf.scene);
|
|
28767
|
-
case
|
|
28768
|
-
_context2.p =
|
|
28769
|
-
|
|
28770
|
-
console.error("Failed to load model ".concat(modelKey, ":"),
|
|
28957
|
+
case 14:
|
|
28958
|
+
_context2.p = 14;
|
|
28959
|
+
_t4 = _context2.v;
|
|
28960
|
+
console.error("Failed to load model ".concat(modelKey, ":"), _t4);
|
|
28771
28961
|
return _context2.a(2, null);
|
|
28772
28962
|
}
|
|
28773
|
-
}, _callee2, null, [[6,
|
|
28963
|
+
}, _callee2, null, [[7, 9], [6, 14], [2, 5]]);
|
|
28774
28964
|
}));
|
|
28775
28965
|
function _getLibraryModel(_x4, _x5) {
|
|
28776
28966
|
return _getLibraryModel2.apply(this, arguments);
|
|
@@ -28869,7 +29059,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28869
29059
|
key: "verifyModelPreloaderCache",
|
|
28870
29060
|
value: (function () {
|
|
28871
29061
|
var _verifyModelPreloaderCache = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
28872
|
-
var preloaderStatus,
|
|
29062
|
+
var preloaderStatus, _t5;
|
|
28873
29063
|
return _regenerator().w(function (_context3) {
|
|
28874
29064
|
while (1) switch (_context3.n) {
|
|
28875
29065
|
case 0:
|
|
@@ -28892,8 +29082,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28892
29082
|
break;
|
|
28893
29083
|
case 3:
|
|
28894
29084
|
_context3.p = 3;
|
|
28895
|
-
|
|
28896
|
-
console.warn('⚠️ Model preloading failed, some models may load directly:',
|
|
29085
|
+
_t5 = _context3.v;
|
|
29086
|
+
console.warn('⚠️ Model preloading failed, some models may load directly:', _t5);
|
|
28897
29087
|
case 4:
|
|
28898
29088
|
return _context3.a(2, preloaderStatus);
|
|
28899
29089
|
}
|
|
@@ -28912,7 +29102,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
28912
29102
|
key: "preloadMissingModels",
|
|
28913
29103
|
value: (function () {
|
|
28914
29104
|
var _preloadMissingModels = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(data, componentDictionary) {
|
|
28915
|
-
var _data$scene, _data$scene2, requiredModels, preloaderStatus, cachedModels, missingModels, basePath, modelUrls, _iterator, _step, modelKey,
|
|
29105
|
+
var _data$scene, _data$scene2, requiredModels, preloaderStatus, cachedModels, missingModels, basePath, modelUrls, _iterator, _step, modelKey, _t6, _t7;
|
|
28916
29106
|
return _regenerator().w(function (_context4) {
|
|
28917
29107
|
while (1) switch (_context4.n) {
|
|
28918
29108
|
case 0:
|
|
@@ -29007,8 +29197,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29007
29197
|
break;
|
|
29008
29198
|
case 7:
|
|
29009
29199
|
_context4.p = 7;
|
|
29010
|
-
|
|
29011
|
-
console.warn("\u274C Failed to preload missing model ".concat(modelKey, ":"),
|
|
29200
|
+
_t6 = _context4.v;
|
|
29201
|
+
console.warn("\u274C Failed to preload missing model ".concat(modelKey, ":"), _t6);
|
|
29012
29202
|
case 8:
|
|
29013
29203
|
_context4.n = 4;
|
|
29014
29204
|
break;
|
|
@@ -29017,8 +29207,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29017
29207
|
break;
|
|
29018
29208
|
case 10:
|
|
29019
29209
|
_context4.p = 10;
|
|
29020
|
-
|
|
29021
|
-
_iterator.e(
|
|
29210
|
+
_t7 = _context4.v;
|
|
29211
|
+
_iterator.e(_t7);
|
|
29022
29212
|
case 11:
|
|
29023
29213
|
_context4.p = 11;
|
|
29024
29214
|
_iterator.f();
|
|
@@ -29123,7 +29313,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29123
29313
|
key: "loadComponentDictionary",
|
|
29124
29314
|
value: (function () {
|
|
29125
29315
|
var _loadComponentDictionary = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
|
|
29126
|
-
var response, dict,
|
|
29316
|
+
var response, dict, _t8;
|
|
29127
29317
|
return _regenerator().w(function (_context6) {
|
|
29128
29318
|
while (1) switch (_context6.n) {
|
|
29129
29319
|
case 0:
|
|
@@ -29141,8 +29331,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
29141
29331
|
return _context6.a(2, dict);
|
|
29142
29332
|
case 3:
|
|
29143
29333
|
_context6.p = 3;
|
|
29144
|
-
|
|
29145
|
-
console.warn('⚠️ Could not load component dictionary:',
|
|
29334
|
+
_t8 = _context6.v;
|
|
29335
|
+
console.warn('⚠️ Could not load component dictionary:', _t8);
|
|
29146
29336
|
return _context6.a(2, {});
|
|
29147
29337
|
}
|
|
29148
29338
|
}, _callee6, null, [[0, 3]]);
|
|
@@ -29938,7 +30128,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
29938
30128
|
return createSceneMaterials;
|
|
29939
30129
|
}()
|
|
29940
30130
|
/**
|
|
29941
|
-
* Helper function to create geometries
|
|
30131
|
+
* Helper function to create geometries for connectors and gateways
|
|
30132
|
+
* Components use GLB geometry directly, no placeholder needed
|
|
29942
30133
|
*/
|
|
29943
30134
|
)
|
|
29944
30135
|
}, {
|
|
@@ -29953,7 +30144,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
29953
30144
|
return geometries;
|
|
29954
30145
|
}
|
|
29955
30146
|
|
|
29956
|
-
// Create geometries
|
|
30147
|
+
// Create geometries only for connectors and gateways (components use GLB geometry)
|
|
29957
30148
|
data.scene.children.forEach(function (child) {
|
|
29958
30149
|
var _child$userData, _child$userData2;
|
|
29959
30150
|
// Skip manual segments - they create their own geometry
|
|
@@ -29962,42 +30153,28 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
29962
30153
|
console.log("\u23ED\uFE0F Skipping geometry creation for manual segment: ".concat(child.uuid));
|
|
29963
30154
|
return;
|
|
29964
30155
|
}
|
|
29965
|
-
if ((_child$userData2 = child.userData) !== null && _child$userData2 !== void 0 && _child$userData2.libraryId && componentDictionary[child.userData.libraryId]) {
|
|
29966
|
-
var component = componentDictionary[child.userData.libraryId];
|
|
29967
|
-
var boundingBox = component.boundingBox;
|
|
29968
30156
|
|
|
29969
|
-
|
|
29970
|
-
|
|
30157
|
+
// Skip components - they will use GLB geometry directly
|
|
30158
|
+
if ((_child$userData2 = child.userData) !== null && _child$userData2 !== void 0 && _child$userData2.libraryId) {
|
|
30159
|
+
return;
|
|
30160
|
+
}
|
|
29971
30161
|
|
|
29972
|
-
|
|
29973
|
-
|
|
29974
|
-
|
|
29975
|
-
|
|
29976
|
-
//
|
|
29977
|
-
|
|
29978
|
-
|
|
29979
|
-
|
|
29980
|
-
|
|
29981
|
-
if (
|
|
29982
|
-
//
|
|
29983
|
-
var
|
|
29984
|
-
|
|
29985
|
-
|
|
29986
|
-
// Match computed gateway size (0.15) for gateways, keep 0.1 for connectors
|
|
29987
|
-
var sphereRadius = isGateway ? 0.15 : 0.1;
|
|
29988
|
-
geometries[geometryKey] = new THREE__namespace.SphereGeometry(sphereRadius, 16, 16);
|
|
29989
|
-
console.log("\uD83D\uDD2E Created shared sphere geometry for ".concat(isGateway ? 'gateways' : 'connectors', " (radius: ").concat(sphereRadius, ")"));
|
|
29990
|
-
}
|
|
30162
|
+
// For non-library objects (connectors, gateways), create shared sphere geometry
|
|
30163
|
+
var isConnectorOrGateway = child.uuid && (child.uuid.toLowerCase().includes('connector') || child.uuid.toLowerCase().includes('gateway'));
|
|
30164
|
+
console.log("createSceneGeometries child:", child);
|
|
30165
|
+
if (isConnectorOrGateway) {
|
|
30166
|
+
// Check if position exists and is not at origin
|
|
30167
|
+
if (child.position && !(child.position.x == 0 && child.position.y == 0 && child.position.z == 0)) {
|
|
30168
|
+
// Determine if this is a gateway or connector
|
|
30169
|
+
var isGateway = child.uuid.toLowerCase().includes('gateway');
|
|
30170
|
+
var geometryKey = isGateway ? 'GATEWAY_SPHERE' : 'CONNECTOR_GATEWAY_SPHERE';
|
|
30171
|
+
if (!geometries[geometryKey]) {
|
|
30172
|
+
// Match computed gateway size (0.15) for gateways, keep 0.1 for connectors
|
|
30173
|
+
var sphereRadius = isGateway ? 0.15 : 0.1;
|
|
30174
|
+
geometries[geometryKey] = new THREE__namespace.SphereGeometry(sphereRadius, 16, 16);
|
|
30175
|
+
console.log("\uD83D\uDD2E Created shared sphere geometry for ".concat(isGateway ? 'gateways' : 'connectors', " (radius: ").concat(sphereRadius, ")"));
|
|
29991
30176
|
}
|
|
29992
30177
|
}
|
|
29993
|
-
// else {
|
|
29994
|
-
// // Default fallback geometry
|
|
29995
|
-
// const geometryKey = child.geometry || 'FALLBACK_BOX'
|
|
29996
|
-
// if (!geometries[geometryKey]) {
|
|
29997
|
-
// geometries[geometryKey] = new THREE.BoxGeometry(1, 1, 1)
|
|
29998
|
-
// console.log(`📦 Created fallback box geometry`)
|
|
29999
|
-
// }
|
|
30000
|
-
// }
|
|
30001
30178
|
}
|
|
30002
30179
|
});
|
|
30003
30180
|
return geometries;
|
|
@@ -30761,7 +30938,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
30761
30938
|
key: "_createBasicSceneObjects",
|
|
30762
30939
|
value: (function () {
|
|
30763
30940
|
var _createBasicSceneObjects2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
30764
|
-
var
|
|
30941
|
+
var _this$sceneViewer$cen,
|
|
30942
|
+
_this4 = this;
|
|
30765
30943
|
var componentDictionary, _yield$this$createSce, materials, crosscubeTextureSet, geometries, libraryObjectsToReplace;
|
|
30766
30944
|
return _regenerator().w(function (_context6) {
|
|
30767
30945
|
while (1) switch (_context6.n) {
|
|
@@ -30772,20 +30950,33 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
30772
30950
|
}
|
|
30773
30951
|
throw new Error('Invalid scene data structure: data.scene.children must be an array');
|
|
30774
30952
|
case 1:
|
|
30953
|
+
// Use the extended component dictionary (includes S3 components) if available,
|
|
30954
|
+
// otherwise fall back to loading from static file
|
|
30955
|
+
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;
|
|
30956
|
+
if (componentDictionary) {
|
|
30957
|
+
_context6.n = 3;
|
|
30958
|
+
break;
|
|
30959
|
+
}
|
|
30960
|
+
console.log('⚠️ Extended dictionary not available, loading from static file');
|
|
30775
30961
|
_context6.n = 2;
|
|
30776
30962
|
return this.modelManager.loadComponentDictionary();
|
|
30777
30963
|
case 2:
|
|
30778
30964
|
componentDictionary = _context6.v;
|
|
30965
|
+
_context6.n = 4;
|
|
30966
|
+
break;
|
|
30967
|
+
case 3:
|
|
30968
|
+
console.log("\u2705 Using extended component dictionary (".concat(Object.keys(componentDictionary).length, " components)"));
|
|
30969
|
+
case 4:
|
|
30779
30970
|
// Inject connector children from component dictionary into scene data
|
|
30780
30971
|
this._injectConnectorChildrenFromDictionary(data, componentDictionary);
|
|
30781
30972
|
|
|
30782
30973
|
// Ensure models are preloaded
|
|
30783
|
-
_context6.n =
|
|
30974
|
+
_context6.n = 5;
|
|
30784
30975
|
return this.modelManager.preloadMissingModels(data, componentDictionary);
|
|
30785
|
-
case
|
|
30786
|
-
_context6.n =
|
|
30976
|
+
case 5:
|
|
30977
|
+
_context6.n = 6;
|
|
30787
30978
|
return this.createSceneMaterials(data);
|
|
30788
|
-
case
|
|
30979
|
+
case 6:
|
|
30789
30980
|
_yield$this$createSce = _context6.v;
|
|
30790
30981
|
materials = _yield$this$createSce.materials;
|
|
30791
30982
|
crosscubeTextureSet = _yield$this$createSce.crosscubeTextureSet;
|
|
@@ -36527,7 +36718,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36527
36718
|
|
|
36528
36719
|
// Add attached IO device models for smart components
|
|
36529
36720
|
if (componentData.isSmart && componentData.attachedDevices) {
|
|
36530
|
-
|
|
36721
|
+
attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
|
|
36531
36722
|
}
|
|
36532
36723
|
|
|
36533
36724
|
// Notify the component manager about the new component
|
|
@@ -36580,95 +36771,6 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36580
36771
|
}
|
|
36581
36772
|
}
|
|
36582
36773
|
|
|
36583
|
-
/**
|
|
36584
|
-
* Attach IO device models to a smart component from cached models.
|
|
36585
|
-
* Each device referenced in componentData.attachedDevices is looked up
|
|
36586
|
-
* in the model preloader cache, cloned, positioned, and added as a child.
|
|
36587
|
-
* @param {THREE.Object3D} componentModel - The parent component model
|
|
36588
|
-
* @param {Object} componentData - Component dictionary entry (has attachedDevices)
|
|
36589
|
-
* @param {Object} modelPreloader - ModelPreloader instance
|
|
36590
|
-
* @param {string} parentComponentId - The parent component's UUID
|
|
36591
|
-
* @private
|
|
36592
|
-
*/
|
|
36593
|
-
}, {
|
|
36594
|
-
key: "_attachIODevicesToComponent",
|
|
36595
|
-
value: function _attachIODevicesToComponent(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
36596
|
-
var attachedDevices = componentData.attachedDevices;
|
|
36597
|
-
console.log("\uD83D\uDD0C addComponent(): Attaching ".concat(Object.keys(attachedDevices).length, " IO devices to smart component"));
|
|
36598
|
-
for (var _i = 0, _Object$entries = Object.entries(attachedDevices); _i < _Object$entries.length; _i++) {
|
|
36599
|
-
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
36600
|
-
attachmentId = _Object$entries$_i[0],
|
|
36601
|
-
attachment = _Object$entries$_i[1];
|
|
36602
|
-
try {
|
|
36603
|
-
var _modelPreloader$compo, _deviceData$ioConfig, _deviceData$ioConfig2, _deviceData$ioConfig3, _attachment$attachmen;
|
|
36604
|
-
var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
36605
|
-
if (!deviceData || !deviceData.modelKey) {
|
|
36606
|
-
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary, skipping"));
|
|
36607
|
-
continue;
|
|
36608
|
-
}
|
|
36609
|
-
var cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
36610
|
-
if (!cachedDevice) {
|
|
36611
|
-
console.warn("\u26A0\uFE0F IO device model not in cache: ".concat(deviceData.modelKey, ", skipping"));
|
|
36612
|
-
continue;
|
|
36613
|
-
}
|
|
36614
|
-
|
|
36615
|
-
// Clone so each component instance owns its own io-device subtree and materials.
|
|
36616
|
-
// Without this, all placed copies of the same smart component share the cached
|
|
36617
|
-
// object, causing material mutations (from behaviors) to bleed across instances.
|
|
36618
|
-
var deviceModel = cachedDevice.clone();
|
|
36619
|
-
deviceModel.traverse(function (child) {
|
|
36620
|
-
if (child.isMesh && child.material) {
|
|
36621
|
-
child.material = Array.isArray(child.material) ? child.material.map(function (m) {
|
|
36622
|
-
return m.clone();
|
|
36623
|
-
}) : child.material.clone();
|
|
36624
|
-
}
|
|
36625
|
-
});
|
|
36626
|
-
|
|
36627
|
-
// Name the device model
|
|
36628
|
-
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
36629
|
-
|
|
36630
|
-
// Set user data for identification — include ioConfig data points so the
|
|
36631
|
-
// component tooltip can render state displays without an extra lookup.
|
|
36632
|
-
deviceModel.userData = {
|
|
36633
|
-
objectType: 'io-device',
|
|
36634
|
-
deviceId: attachment.deviceId,
|
|
36635
|
-
attachmentId: attachmentId,
|
|
36636
|
-
attachmentLabel: attachment.attachmentLabel,
|
|
36637
|
-
parentComponentId: parentComponentId,
|
|
36638
|
-
deviceName: deviceData.name || '',
|
|
36639
|
-
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
36640
|
-
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
36641
|
-
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) || [],
|
|
36642
|
-
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
36643
|
-
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output',
|
|
36644
|
-
// Signal wiring sourced from this attachment (for state propagation reference)
|
|
36645
|
-
signalOutputs: attachment.signalOutputs || []
|
|
36646
|
-
};
|
|
36647
|
-
|
|
36648
|
-
// Position at the attachment point
|
|
36649
|
-
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
36650
|
-
var pos = attachment.attachmentPoint.position;
|
|
36651
|
-
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
36652
|
-
}
|
|
36653
|
-
|
|
36654
|
-
// IO device models are authored at the same real-world unit scale
|
|
36655
|
-
// as the host component, so keep them at their natural (1:1) size.
|
|
36656
|
-
// Note: attachmentPoint.scale is the connector marker sphere size,
|
|
36657
|
-
// NOT a desired device model scale.
|
|
36658
|
-
deviceModel.scale.setScalar(1);
|
|
36659
|
-
|
|
36660
|
-
// Add as child of the component
|
|
36661
|
-
componentModel.add(deviceModel);
|
|
36662
|
-
console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
|
|
36663
|
-
position: deviceModel.position,
|
|
36664
|
-
scale: deviceModel.scale
|
|
36665
|
-
});
|
|
36666
|
-
} catch (err) {
|
|
36667
|
-
console.error("\u274C Error attaching IO device ".concat(attachment.deviceId, ":"), err);
|
|
36668
|
-
}
|
|
36669
|
-
}
|
|
36670
|
-
}
|
|
36671
|
-
|
|
36672
36774
|
/**
|
|
36673
36775
|
* Delete a component from the scene by componentId (internal implementation)
|
|
36674
36776
|
* @param {string} componentId - The UUID of the component to delete
|
|
@@ -36774,7 +36876,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
36774
36876
|
* Initialize the CentralPlant manager
|
|
36775
36877
|
*
|
|
36776
36878
|
* @constructor
|
|
36777
|
-
* @version 0.1.
|
|
36879
|
+
* @version 0.1.91
|
|
36778
36880
|
* @updated 2025-10-22
|
|
36779
36881
|
*
|
|
36780
36882
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -38274,6 +38376,50 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38274
38376
|
}
|
|
38275
38377
|
return removeComponentFromDictionary;
|
|
38276
38378
|
}()
|
|
38379
|
+
/**
|
|
38380
|
+
* Get library IDs from scene data that are missing from the component dictionary
|
|
38381
|
+
* @param {Object} sceneData - Scene JSON data to analyze
|
|
38382
|
+
* @returns {string[]} Array of library IDs that are not in the current component dictionary
|
|
38383
|
+
* @description Analyzes scene data to find components whose libraryId is not present in the
|
|
38384
|
+
* component dictionary. This is useful for detecting S3 components that need to be fetched
|
|
38385
|
+
* before importing a scene.
|
|
38386
|
+
* @example
|
|
38387
|
+
* // Check for missing components before import
|
|
38388
|
+
* const missingIds = centralPlant.getMissingLibraryIds(sceneJson);
|
|
38389
|
+
* if (missingIds.length > 0) {
|
|
38390
|
+
* // Fetch missing S3 components
|
|
38391
|
+
* await fetchS3Components(missingIds);
|
|
38392
|
+
* await centralPlant.extendComponentDictionary(fetchedComponents);
|
|
38393
|
+
* }
|
|
38394
|
+
* // Now safe to import
|
|
38395
|
+
* await centralPlant.importScene(sceneJson);
|
|
38396
|
+
*/
|
|
38397
|
+
)
|
|
38398
|
+
}, {
|
|
38399
|
+
key: "getMissingLibraryIds",
|
|
38400
|
+
value: function getMissingLibraryIds(sceneData) {
|
|
38401
|
+
var _sceneData$scene, _this$managers$compon;
|
|
38402
|
+
if (!(sceneData !== null && sceneData !== void 0 && (_sceneData$scene = sceneData.scene) !== null && _sceneData$scene !== void 0 && _sceneData$scene.children) || !Array.isArray(sceneData.scene.children)) {
|
|
38403
|
+
return [];
|
|
38404
|
+
}
|
|
38405
|
+
var componentDictionary = ((_this$managers$compon = this.managers.componentDataManager) === null || _this$managers$compon === void 0 ? void 0 : _this$managers$compon.componentDictionary) || {};
|
|
38406
|
+
var missingIds = [];
|
|
38407
|
+
sceneData.scene.children.forEach(function (child) {
|
|
38408
|
+
var _child$userData;
|
|
38409
|
+
var libraryId = (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.libraryId;
|
|
38410
|
+
if (libraryId && !componentDictionary[libraryId]) {
|
|
38411
|
+
// Only add unique IDs
|
|
38412
|
+
if (!missingIds.includes(libraryId)) {
|
|
38413
|
+
missingIds.push(libraryId);
|
|
38414
|
+
}
|
|
38415
|
+
}
|
|
38416
|
+
});
|
|
38417
|
+
if (missingIds.length > 0) {
|
|
38418
|
+
console.log("\uD83D\uDD0D Found ".concat(missingIds.length, " missing library IDs in scene data:"), missingIds);
|
|
38419
|
+
}
|
|
38420
|
+
return missingIds;
|
|
38421
|
+
}
|
|
38422
|
+
|
|
38277
38423
|
/**
|
|
38278
38424
|
* Select an object (component, connector, or gateway) in the scene by its ID
|
|
38279
38425
|
* @param {string} objectId - The UUID or name of the object to select
|
|
@@ -38310,7 +38456,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38310
38456
|
* centralPlant.selectComponent(targetObject.uuid);
|
|
38311
38457
|
* }
|
|
38312
38458
|
*/
|
|
38313
|
-
)
|
|
38314
38459
|
}, {
|
|
38315
38460
|
key: "selectComponent",
|
|
38316
38461
|
value: function selectComponent(objectId) {
|
|
@@ -38339,8 +38484,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38339
38484
|
// If still not found, try finding by originalUuid in userData
|
|
38340
38485
|
if (!targetObject) {
|
|
38341
38486
|
this.sceneViewer.scene.traverse(function (child) {
|
|
38342
|
-
var _child$
|
|
38343
|
-
if (((_child$
|
|
38487
|
+
var _child$userData2;
|
|
38488
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === objectId) {
|
|
38344
38489
|
targetObject = child;
|
|
38345
38490
|
return;
|
|
38346
38491
|
}
|