@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
|
@@ -19,7 +19,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
19
19
|
* Initialize the CentralPlant manager
|
|
20
20
|
*
|
|
21
21
|
* @constructor
|
|
22
|
-
* @version 0.1.
|
|
22
|
+
* @version 0.1.90
|
|
23
23
|
* @updated 2025-10-22
|
|
24
24
|
*
|
|
25
25
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -1519,6 +1519,50 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1519
1519
|
}
|
|
1520
1520
|
return removeComponentFromDictionary;
|
|
1521
1521
|
}()
|
|
1522
|
+
/**
|
|
1523
|
+
* Get library IDs from scene data that are missing from the component dictionary
|
|
1524
|
+
* @param {Object} sceneData - Scene JSON data to analyze
|
|
1525
|
+
* @returns {string[]} Array of library IDs that are not in the current component dictionary
|
|
1526
|
+
* @description Analyzes scene data to find components whose libraryId is not present in the
|
|
1527
|
+
* component dictionary. This is useful for detecting S3 components that need to be fetched
|
|
1528
|
+
* before importing a scene.
|
|
1529
|
+
* @example
|
|
1530
|
+
* // Check for missing components before import
|
|
1531
|
+
* const missingIds = centralPlant.getMissingLibraryIds(sceneJson);
|
|
1532
|
+
* if (missingIds.length > 0) {
|
|
1533
|
+
* // Fetch missing S3 components
|
|
1534
|
+
* await fetchS3Components(missingIds);
|
|
1535
|
+
* await centralPlant.extendComponentDictionary(fetchedComponents);
|
|
1536
|
+
* }
|
|
1537
|
+
* // Now safe to import
|
|
1538
|
+
* await centralPlant.importScene(sceneJson);
|
|
1539
|
+
*/
|
|
1540
|
+
)
|
|
1541
|
+
}, {
|
|
1542
|
+
key: "getMissingLibraryIds",
|
|
1543
|
+
value: function getMissingLibraryIds(sceneData) {
|
|
1544
|
+
var _sceneData$scene, _this$managers$compon;
|
|
1545
|
+
if (!(sceneData !== null && sceneData !== void 0 && (_sceneData$scene = sceneData.scene) !== null && _sceneData$scene !== void 0 && _sceneData$scene.children) || !Array.isArray(sceneData.scene.children)) {
|
|
1546
|
+
return [];
|
|
1547
|
+
}
|
|
1548
|
+
var componentDictionary = ((_this$managers$compon = this.managers.componentDataManager) === null || _this$managers$compon === void 0 ? void 0 : _this$managers$compon.componentDictionary) || {};
|
|
1549
|
+
var missingIds = [];
|
|
1550
|
+
sceneData.scene.children.forEach(function (child) {
|
|
1551
|
+
var _child$userData;
|
|
1552
|
+
var libraryId = (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.libraryId;
|
|
1553
|
+
if (libraryId && !componentDictionary[libraryId]) {
|
|
1554
|
+
// Only add unique IDs
|
|
1555
|
+
if (!missingIds.includes(libraryId)) {
|
|
1556
|
+
missingIds.push(libraryId);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
});
|
|
1560
|
+
if (missingIds.length > 0) {
|
|
1561
|
+
console.log("\uD83D\uDD0D Found ".concat(missingIds.length, " missing library IDs in scene data:"), missingIds);
|
|
1562
|
+
}
|
|
1563
|
+
return missingIds;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1522
1566
|
/**
|
|
1523
1567
|
* Select an object (component, connector, or gateway) in the scene by its ID
|
|
1524
1568
|
* @param {string} objectId - The UUID or name of the object to select
|
|
@@ -1555,7 +1599,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1555
1599
|
* centralPlant.selectComponent(targetObject.uuid);
|
|
1556
1600
|
* }
|
|
1557
1601
|
*/
|
|
1558
|
-
)
|
|
1559
1602
|
}, {
|
|
1560
1603
|
key: "selectComponent",
|
|
1561
1604
|
value: function selectComponent(objectId) {
|
|
@@ -1584,8 +1627,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1584
1627
|
// If still not found, try finding by originalUuid in userData
|
|
1585
1628
|
if (!targetObject) {
|
|
1586
1629
|
this.sceneViewer.scene.traverse(function (child) {
|
|
1587
|
-
var _child$
|
|
1588
|
-
if (((_child$
|
|
1630
|
+
var _child$userData2;
|
|
1631
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === objectId) {
|
|
1589
1632
|
targetObject = child;
|
|
1590
1633
|
return;
|
|
1591
1634
|
}
|
|
@@ -27,6 +27,7 @@ var sceneTooltipsManager = require('../managers/scene/sceneTooltipsManager.js');
|
|
|
27
27
|
var componentTooltipManager = require('../managers/scene/componentTooltipManager.js');
|
|
28
28
|
var viewport2DManager = require('../managers/scene/viewport2DManager.js');
|
|
29
29
|
var nameUtils = require('../utils/nameUtils.js');
|
|
30
|
+
var ioDeviceUtils = require('../utils/ioDeviceUtils.js');
|
|
30
31
|
var modelPreloader = require('../rendering/modelPreloader.js');
|
|
31
32
|
|
|
32
33
|
function _interopNamespace(e) {
|
|
@@ -1078,7 +1079,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1078
1079
|
|
|
1079
1080
|
// Add attached IO device models for smart components
|
|
1080
1081
|
if (componentData.isSmart && componentData.attachedDevices) {
|
|
1081
|
-
|
|
1082
|
+
ioDeviceUtils.attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
|
|
1082
1083
|
}
|
|
1083
1084
|
|
|
1084
1085
|
// Notify the component manager about the new component
|
|
@@ -1131,95 +1132,6 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1131
1132
|
}
|
|
1132
1133
|
}
|
|
1133
1134
|
|
|
1134
|
-
/**
|
|
1135
|
-
* Attach IO device models to a smart component from cached models.
|
|
1136
|
-
* Each device referenced in componentData.attachedDevices is looked up
|
|
1137
|
-
* in the model preloader cache, cloned, positioned, and added as a child.
|
|
1138
|
-
* @param {THREE.Object3D} componentModel - The parent component model
|
|
1139
|
-
* @param {Object} componentData - Component dictionary entry (has attachedDevices)
|
|
1140
|
-
* @param {Object} modelPreloader - ModelPreloader instance
|
|
1141
|
-
* @param {string} parentComponentId - The parent component's UUID
|
|
1142
|
-
* @private
|
|
1143
|
-
*/
|
|
1144
|
-
}, {
|
|
1145
|
-
key: "_attachIODevicesToComponent",
|
|
1146
|
-
value: function _attachIODevicesToComponent(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
1147
|
-
var attachedDevices = componentData.attachedDevices;
|
|
1148
|
-
console.log("\uD83D\uDD0C addComponent(): Attaching ".concat(Object.keys(attachedDevices).length, " IO devices to smart component"));
|
|
1149
|
-
for (var _i = 0, _Object$entries = Object.entries(attachedDevices); _i < _Object$entries.length; _i++) {
|
|
1150
|
-
var _Object$entries$_i = _rollupPluginBabelHelpers.slicedToArray(_Object$entries[_i], 2),
|
|
1151
|
-
attachmentId = _Object$entries$_i[0],
|
|
1152
|
-
attachment = _Object$entries$_i[1];
|
|
1153
|
-
try {
|
|
1154
|
-
var _modelPreloader$compo, _deviceData$ioConfig, _deviceData$ioConfig2, _deviceData$ioConfig3, _attachment$attachmen;
|
|
1155
|
-
var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
1156
|
-
if (!deviceData || !deviceData.modelKey) {
|
|
1157
|
-
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary, skipping"));
|
|
1158
|
-
continue;
|
|
1159
|
-
}
|
|
1160
|
-
var cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
1161
|
-
if (!cachedDevice) {
|
|
1162
|
-
console.warn("\u26A0\uFE0F IO device model not in cache: ".concat(deviceData.modelKey, ", skipping"));
|
|
1163
|
-
continue;
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
// Clone so each component instance owns its own io-device subtree and materials.
|
|
1167
|
-
// Without this, all placed copies of the same smart component share the cached
|
|
1168
|
-
// object, causing material mutations (from behaviors) to bleed across instances.
|
|
1169
|
-
var deviceModel = cachedDevice.clone();
|
|
1170
|
-
deviceModel.traverse(function (child) {
|
|
1171
|
-
if (child.isMesh && child.material) {
|
|
1172
|
-
child.material = Array.isArray(child.material) ? child.material.map(function (m) {
|
|
1173
|
-
return m.clone();
|
|
1174
|
-
}) : child.material.clone();
|
|
1175
|
-
}
|
|
1176
|
-
});
|
|
1177
|
-
|
|
1178
|
-
// Name the device model
|
|
1179
|
-
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
1180
|
-
|
|
1181
|
-
// Set user data for identification — include ioConfig data points so the
|
|
1182
|
-
// component tooltip can render state displays without an extra lookup.
|
|
1183
|
-
deviceModel.userData = {
|
|
1184
|
-
objectType: 'io-device',
|
|
1185
|
-
deviceId: attachment.deviceId,
|
|
1186
|
-
attachmentId: attachmentId,
|
|
1187
|
-
attachmentLabel: attachment.attachmentLabel,
|
|
1188
|
-
parentComponentId: parentComponentId,
|
|
1189
|
-
deviceName: deviceData.name || '',
|
|
1190
|
-
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
1191
|
-
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
1192
|
-
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) || [],
|
|
1193
|
-
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
1194
|
-
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output',
|
|
1195
|
-
// Signal wiring sourced from this attachment (for state propagation reference)
|
|
1196
|
-
signalOutputs: attachment.signalOutputs || []
|
|
1197
|
-
};
|
|
1198
|
-
|
|
1199
|
-
// Position at the attachment point
|
|
1200
|
-
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
1201
|
-
var pos = attachment.attachmentPoint.position;
|
|
1202
|
-
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
// IO device models are authored at the same real-world unit scale
|
|
1206
|
-
// as the host component, so keep them at their natural (1:1) size.
|
|
1207
|
-
// Note: attachmentPoint.scale is the connector marker sphere size,
|
|
1208
|
-
// NOT a desired device model scale.
|
|
1209
|
-
deviceModel.scale.setScalar(1);
|
|
1210
|
-
|
|
1211
|
-
// Add as child of the component
|
|
1212
|
-
componentModel.add(deviceModel);
|
|
1213
|
-
console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
|
|
1214
|
-
position: deviceModel.position,
|
|
1215
|
-
scale: deviceModel.scale
|
|
1216
|
-
});
|
|
1217
|
-
} catch (err) {
|
|
1218
|
-
console.error("\u274C Error attaching IO device ".concat(attachment.deviceId, ":"), err);
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
1135
|
/**
|
|
1224
1136
|
* Delete a component from the scene by componentId (internal implementation)
|
|
1225
1137
|
* @param {string} componentId - The UUID of the component to delete
|
|
@@ -821,7 +821,7 @@ var CentralPlantValidator = /*#__PURE__*/function () {
|
|
|
821
821
|
key: "validateImportedSceneData",
|
|
822
822
|
value: function validateImportedSceneData(sceneData) {
|
|
823
823
|
var results = [];
|
|
824
|
-
var hardcodedVersion = "2.
|
|
824
|
+
var hardcodedVersion = "2.3";
|
|
825
825
|
|
|
826
826
|
// Version validation - MUST be the value of hardcodedVersion
|
|
827
827
|
if (!sceneData.version || sceneData.version !== hardcodedVersion) {
|
|
@@ -845,6 +845,7 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
845
845
|
id: key,
|
|
846
846
|
name: component.name,
|
|
847
847
|
type: ((_component$metadata = component.metadata) === null || _component$metadata === void 0 ? void 0 : _component$metadata.type) || 'Component',
|
|
848
|
+
assetType: component.assetType || null,
|
|
848
849
|
category: component.category,
|
|
849
850
|
modelKey: component.modelKey,
|
|
850
851
|
modelType: component.modelType,
|
|
@@ -853,10 +854,12 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
853
854
|
// Preserve S3 metadata
|
|
854
855
|
isS3Component: component.isS3Component,
|
|
855
856
|
s3Path: component.s3Path,
|
|
856
|
-
preLoad: component.preLoad
|
|
857
|
+
preLoad: component.preLoad,
|
|
858
|
+
preCache: component.preCache
|
|
857
859
|
};
|
|
858
860
|
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, baseData), {}, {
|
|
859
861
|
metadata: component.metadata || {},
|
|
862
|
+
ioConfig: component.ioConfig || null,
|
|
860
863
|
boundingBox: component.boundingBox || null,
|
|
861
864
|
adaptedBoundingBox: component.adaptedBoundingBox || null,
|
|
862
865
|
children: component.children || [],
|
|
@@ -97,12 +97,16 @@ var ComponentManager = /*#__PURE__*/function () {
|
|
|
97
97
|
componentMesh.position.set(position.x, position.y, position.z);
|
|
98
98
|
|
|
99
99
|
// Set userData for the component including dimensions
|
|
100
|
-
componentMesh.userData = _rollupPluginBabelHelpers.objectSpread2({
|
|
100
|
+
componentMesh.userData = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({
|
|
101
101
|
libraryId: componentData.libraryId,
|
|
102
102
|
objectType: 'component',
|
|
103
103
|
originalUuid: uuid
|
|
104
104
|
}, ((_gltfScene$userData = gltfScene.userData) === null || _gltfScene$userData === void 0 ? void 0 : _gltfScene$userData.dimensions) && {
|
|
105
105
|
dimensions: gltfScene.userData.dimensions
|
|
106
|
+
}), libraryComponent.isS3Component && {
|
|
107
|
+
isS3Component: true,
|
|
108
|
+
s3Path: libraryComponent.s3Path,
|
|
109
|
+
componentKey: libraryComponent.componentKey
|
|
106
110
|
});
|
|
107
111
|
|
|
108
112
|
// Also ensure dimensions are preserved in the userData
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
6
|
var THREE = require('three');
|
|
7
|
+
var ioDeviceUtils = require('../../utils/ioDeviceUtils.js');
|
|
7
8
|
var modelPreloader = require('../../rendering/modelPreloader.js');
|
|
8
9
|
|
|
9
10
|
function _interopNamespace(e) {
|
|
@@ -109,6 +110,11 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
109
110
|
libraryModel.add(connector);
|
|
110
111
|
});
|
|
111
112
|
|
|
113
|
+
// Attach IO devices for smart components (import flow)
|
|
114
|
+
if (componentData.isSmart && componentData.attachedDevices) {
|
|
115
|
+
ioDeviceUtils.attachIODevicesToComponent(libraryModel, componentData, modelPreloader["default"], originalProps.uuid);
|
|
116
|
+
}
|
|
117
|
+
|
|
112
118
|
// Replace mesh in scene
|
|
113
119
|
this._replaceMeshInScene(targetMesh, libraryModel, originalProps.parent, component);
|
|
114
120
|
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"));
|
|
@@ -185,7 +191,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
185
191
|
value: (function () {
|
|
186
192
|
var _getLibraryModel2 = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee2(modelKey, libraryId) {
|
|
187
193
|
var _this2 = this;
|
|
188
|
-
var gltfScene, preloaderStatus, modelPath, gltf, _t2, _t3;
|
|
194
|
+
var gltfScene, preloaderStatus, modelPath, gltf, _t2, _t3, _t4;
|
|
189
195
|
return _rollupPluginBabelHelpers.regenerator().w(function (_context2) {
|
|
190
196
|
while (1) switch (_context2.n) {
|
|
191
197
|
case 0:
|
|
@@ -222,25 +228,47 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
222
228
|
console.warn("\u26A0\uFE0F Preloading failed:", _t2);
|
|
223
229
|
case 6:
|
|
224
230
|
_context2.p = 6;
|
|
231
|
+
if (!modelPreloader["default"].urlResolver) {
|
|
232
|
+
_context2.n = 11;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
_context2.p = 7;
|
|
236
|
+
_context2.n = 8;
|
|
237
|
+
return modelPreloader["default"].urlResolver(modelKey);
|
|
238
|
+
case 8:
|
|
239
|
+
modelPath = _context2.v;
|
|
240
|
+
console.log("\uD83D\uDD17 Resolved URL for ".concat(modelKey));
|
|
241
|
+
_context2.n = 10;
|
|
242
|
+
break;
|
|
243
|
+
case 9:
|
|
244
|
+
_context2.p = 9;
|
|
245
|
+
_t3 = _context2.v;
|
|
246
|
+
console.warn("\u26A0\uFE0F URL resolver failed for ".concat(modelKey, ", falling back to local path:"), _t3);
|
|
247
|
+
modelPath = "".concat(modelPreloader["default"].modelsBasePath).concat(modelKey);
|
|
248
|
+
case 10:
|
|
249
|
+
_context2.n = 12;
|
|
250
|
+
break;
|
|
251
|
+
case 11:
|
|
225
252
|
modelPath = "".concat(modelPreloader["default"].modelsBasePath).concat(modelKey);
|
|
253
|
+
case 12:
|
|
226
254
|
console.log("\uD83D\uDCC2 Fallback loading from: ".concat(modelPath));
|
|
227
|
-
_context2.n =
|
|
255
|
+
_context2.n = 13;
|
|
228
256
|
return new Promise(function (resolve, reject) {
|
|
229
257
|
_this2.sceneViewer.gltfLoader.load(modelPath, resolve, undefined, reject);
|
|
230
258
|
});
|
|
231
|
-
case
|
|
259
|
+
case 13:
|
|
232
260
|
gltf = _context2.v;
|
|
233
261
|
if (libraryId) {
|
|
234
262
|
modelPreloader["default"].cacheModel(modelKey, gltf.scene.clone(), libraryId);
|
|
235
263
|
}
|
|
236
264
|
return _context2.a(2, gltf.scene);
|
|
237
|
-
case
|
|
238
|
-
_context2.p =
|
|
239
|
-
|
|
240
|
-
console.error("Failed to load model ".concat(modelKey, ":"),
|
|
265
|
+
case 14:
|
|
266
|
+
_context2.p = 14;
|
|
267
|
+
_t4 = _context2.v;
|
|
268
|
+
console.error("Failed to load model ".concat(modelKey, ":"), _t4);
|
|
241
269
|
return _context2.a(2, null);
|
|
242
270
|
}
|
|
243
|
-
}, _callee2, null, [[6,
|
|
271
|
+
}, _callee2, null, [[7, 9], [6, 14], [2, 5]]);
|
|
244
272
|
}));
|
|
245
273
|
function _getLibraryModel(_x4, _x5) {
|
|
246
274
|
return _getLibraryModel2.apply(this, arguments);
|
|
@@ -339,7 +367,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
339
367
|
key: "verifyModelPreloaderCache",
|
|
340
368
|
value: (function () {
|
|
341
369
|
var _verifyModelPreloaderCache = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee3() {
|
|
342
|
-
var preloaderStatus,
|
|
370
|
+
var preloaderStatus, _t5;
|
|
343
371
|
return _rollupPluginBabelHelpers.regenerator().w(function (_context3) {
|
|
344
372
|
while (1) switch (_context3.n) {
|
|
345
373
|
case 0:
|
|
@@ -362,8 +390,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
362
390
|
break;
|
|
363
391
|
case 3:
|
|
364
392
|
_context3.p = 3;
|
|
365
|
-
|
|
366
|
-
console.warn('⚠️ Model preloading failed, some models may load directly:',
|
|
393
|
+
_t5 = _context3.v;
|
|
394
|
+
console.warn('⚠️ Model preloading failed, some models may load directly:', _t5);
|
|
367
395
|
case 4:
|
|
368
396
|
return _context3.a(2, preloaderStatus);
|
|
369
397
|
}
|
|
@@ -382,7 +410,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
382
410
|
key: "preloadMissingModels",
|
|
383
411
|
value: (function () {
|
|
384
412
|
var _preloadMissingModels = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee4(data, componentDictionary) {
|
|
385
|
-
var _data$scene, _data$scene2, requiredModels, preloaderStatus, cachedModels, missingModels, basePath, modelUrls, _iterator, _step, modelKey,
|
|
413
|
+
var _data$scene, _data$scene2, requiredModels, preloaderStatus, cachedModels, missingModels, basePath, modelUrls, _iterator, _step, modelKey, _t6, _t7;
|
|
386
414
|
return _rollupPluginBabelHelpers.regenerator().w(function (_context4) {
|
|
387
415
|
while (1) switch (_context4.n) {
|
|
388
416
|
case 0:
|
|
@@ -477,8 +505,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
477
505
|
break;
|
|
478
506
|
case 7:
|
|
479
507
|
_context4.p = 7;
|
|
480
|
-
|
|
481
|
-
console.warn("\u274C Failed to preload missing model ".concat(modelKey, ":"),
|
|
508
|
+
_t6 = _context4.v;
|
|
509
|
+
console.warn("\u274C Failed to preload missing model ".concat(modelKey, ":"), _t6);
|
|
482
510
|
case 8:
|
|
483
511
|
_context4.n = 4;
|
|
484
512
|
break;
|
|
@@ -487,8 +515,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
487
515
|
break;
|
|
488
516
|
case 10:
|
|
489
517
|
_context4.p = 10;
|
|
490
|
-
|
|
491
|
-
_iterator.e(
|
|
518
|
+
_t7 = _context4.v;
|
|
519
|
+
_iterator.e(_t7);
|
|
492
520
|
case 11:
|
|
493
521
|
_context4.p = 11;
|
|
494
522
|
_iterator.f();
|
|
@@ -593,7 +621,7 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
593
621
|
key: "loadComponentDictionary",
|
|
594
622
|
value: (function () {
|
|
595
623
|
var _loadComponentDictionary = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee6() {
|
|
596
|
-
var response, dict,
|
|
624
|
+
var response, dict, _t8;
|
|
597
625
|
return _rollupPluginBabelHelpers.regenerator().w(function (_context6) {
|
|
598
626
|
while (1) switch (_context6.n) {
|
|
599
627
|
case 0:
|
|
@@ -611,8 +639,8 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
611
639
|
return _context6.a(2, dict);
|
|
612
640
|
case 3:
|
|
613
641
|
_context6.p = 3;
|
|
614
|
-
|
|
615
|
-
console.warn('⚠️ Could not load component dictionary:',
|
|
642
|
+
_t8 = _context6.v;
|
|
643
|
+
console.warn('⚠️ Could not load component dictionary:', _t8);
|
|
616
644
|
return _context6.a(2, {});
|
|
617
645
|
}
|
|
618
646
|
}, _callee6, null, [[0, 3]]);
|
|
@@ -212,7 +212,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
212
212
|
return createSceneMaterials;
|
|
213
213
|
}()
|
|
214
214
|
/**
|
|
215
|
-
* Helper function to create geometries
|
|
215
|
+
* Helper function to create geometries for connectors and gateways
|
|
216
|
+
* Components use GLB geometry directly, no placeholder needed
|
|
216
217
|
*/
|
|
217
218
|
)
|
|
218
219
|
}, {
|
|
@@ -227,7 +228,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
227
228
|
return geometries;
|
|
228
229
|
}
|
|
229
230
|
|
|
230
|
-
// Create geometries
|
|
231
|
+
// Create geometries only for connectors and gateways (components use GLB geometry)
|
|
231
232
|
data.scene.children.forEach(function (child) {
|
|
232
233
|
var _child$userData, _child$userData2;
|
|
233
234
|
// Skip manual segments - they create their own geometry
|
|
@@ -236,42 +237,28 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
236
237
|
console.log("\u23ED\uFE0F Skipping geometry creation for manual segment: ".concat(child.uuid));
|
|
237
238
|
return;
|
|
238
239
|
}
|
|
239
|
-
if ((_child$userData2 = child.userData) !== null && _child$userData2 !== void 0 && _child$userData2.libraryId && componentDictionary[child.userData.libraryId]) {
|
|
240
|
-
var component = componentDictionary[child.userData.libraryId];
|
|
241
|
-
var boundingBox = component.boundingBox;
|
|
242
240
|
|
|
243
|
-
|
|
244
|
-
|
|
241
|
+
// Skip components - they will use GLB geometry directly
|
|
242
|
+
if ((_child$userData2 = child.userData) !== null && _child$userData2 !== void 0 && _child$userData2.libraryId) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
245
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if (
|
|
256
|
-
//
|
|
257
|
-
var
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
// Match computed gateway size (0.15) for gateways, keep 0.1 for connectors
|
|
261
|
-
var sphereRadius = isGateway ? 0.15 : 0.1;
|
|
262
|
-
geometries[geometryKey] = new THREE__namespace.SphereGeometry(sphereRadius, 16, 16);
|
|
263
|
-
console.log("\uD83D\uDD2E Created shared sphere geometry for ".concat(isGateway ? 'gateways' : 'connectors', " (radius: ").concat(sphereRadius, ")"));
|
|
264
|
-
}
|
|
246
|
+
// For non-library objects (connectors, gateways), create shared sphere geometry
|
|
247
|
+
var isConnectorOrGateway = child.uuid && (child.uuid.toLowerCase().includes('connector') || child.uuid.toLowerCase().includes('gateway'));
|
|
248
|
+
console.log("createSceneGeometries child:", child);
|
|
249
|
+
if (isConnectorOrGateway) {
|
|
250
|
+
// Check if position exists and is not at origin
|
|
251
|
+
if (child.position && !(child.position.x == 0 && child.position.y == 0 && child.position.z == 0)) {
|
|
252
|
+
// Determine if this is a gateway or connector
|
|
253
|
+
var isGateway = child.uuid.toLowerCase().includes('gateway');
|
|
254
|
+
var geometryKey = isGateway ? 'GATEWAY_SPHERE' : 'CONNECTOR_GATEWAY_SPHERE';
|
|
255
|
+
if (!geometries[geometryKey]) {
|
|
256
|
+
// Match computed gateway size (0.15) for gateways, keep 0.1 for connectors
|
|
257
|
+
var sphereRadius = isGateway ? 0.15 : 0.1;
|
|
258
|
+
geometries[geometryKey] = new THREE__namespace.SphereGeometry(sphereRadius, 16, 16);
|
|
259
|
+
console.log("\uD83D\uDD2E Created shared sphere geometry for ".concat(isGateway ? 'gateways' : 'connectors', " (radius: ").concat(sphereRadius, ")"));
|
|
265
260
|
}
|
|
266
261
|
}
|
|
267
|
-
// else {
|
|
268
|
-
// // Default fallback geometry
|
|
269
|
-
// const geometryKey = child.geometry || 'FALLBACK_BOX'
|
|
270
|
-
// if (!geometries[geometryKey]) {
|
|
271
|
-
// geometries[geometryKey] = new THREE.BoxGeometry(1, 1, 1)
|
|
272
|
-
// console.log(`📦 Created fallback box geometry`)
|
|
273
|
-
// }
|
|
274
|
-
// }
|
|
275
262
|
}
|
|
276
263
|
});
|
|
277
264
|
return geometries;
|
|
@@ -1035,7 +1022,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1035
1022
|
key: "_createBasicSceneObjects",
|
|
1036
1023
|
value: (function () {
|
|
1037
1024
|
var _createBasicSceneObjects2 = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee6(data) {
|
|
1038
|
-
var
|
|
1025
|
+
var _this$sceneViewer$cen,
|
|
1026
|
+
_this4 = this;
|
|
1039
1027
|
var componentDictionary, _yield$this$createSce, materials, crosscubeTextureSet, geometries, libraryObjectsToReplace;
|
|
1040
1028
|
return _rollupPluginBabelHelpers.regenerator().w(function (_context6) {
|
|
1041
1029
|
while (1) switch (_context6.n) {
|
|
@@ -1046,20 +1034,33 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1046
1034
|
}
|
|
1047
1035
|
throw new Error('Invalid scene data structure: data.scene.children must be an array');
|
|
1048
1036
|
case 1:
|
|
1037
|
+
// Use the extended component dictionary (includes S3 components) if available,
|
|
1038
|
+
// otherwise fall back to loading from static file
|
|
1039
|
+
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;
|
|
1040
|
+
if (componentDictionary) {
|
|
1041
|
+
_context6.n = 3;
|
|
1042
|
+
break;
|
|
1043
|
+
}
|
|
1044
|
+
console.log('⚠️ Extended dictionary not available, loading from static file');
|
|
1049
1045
|
_context6.n = 2;
|
|
1050
1046
|
return this.modelManager.loadComponentDictionary();
|
|
1051
1047
|
case 2:
|
|
1052
1048
|
componentDictionary = _context6.v;
|
|
1049
|
+
_context6.n = 4;
|
|
1050
|
+
break;
|
|
1051
|
+
case 3:
|
|
1052
|
+
console.log("\u2705 Using extended component dictionary (".concat(Object.keys(componentDictionary).length, " components)"));
|
|
1053
|
+
case 4:
|
|
1053
1054
|
// Inject connector children from component dictionary into scene data
|
|
1054
1055
|
this._injectConnectorChildrenFromDictionary(data, componentDictionary);
|
|
1055
1056
|
|
|
1056
1057
|
// Ensure models are preloaded
|
|
1057
|
-
_context6.n =
|
|
1058
|
+
_context6.n = 5;
|
|
1058
1059
|
return this.modelManager.preloadMissingModels(data, componentDictionary);
|
|
1059
|
-
case
|
|
1060
|
-
_context6.n =
|
|
1060
|
+
case 5:
|
|
1061
|
+
_context6.n = 6;
|
|
1061
1062
|
return this.createSceneMaterials(data);
|
|
1062
|
-
case
|
|
1063
|
+
case 6:
|
|
1063
1064
|
_yield$this$createSce = _context6.v;
|
|
1064
1065
|
materials = _yield$this$createSce.materials;
|
|
1065
1066
|
crosscubeTextureSet = _yield$this$createSce.crosscubeTextureSet;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* IO Device Utilities
|
|
9
|
+
* Shared utility functions for attaching IO devices to smart components.
|
|
10
|
+
* Used by both drag-and-drop (addComponent) and import (loadLibraryModel) flows.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Attach IO device models to a smart component from cached models.
|
|
15
|
+
* Each device referenced in componentData.attachedDevices is looked up
|
|
16
|
+
* in the model preloader cache, cloned, positioned, and added as a child.
|
|
17
|
+
*
|
|
18
|
+
* @param {THREE.Object3D} componentModel - The parent component model
|
|
19
|
+
* @param {Object} componentData - Component dictionary entry (has attachedDevices)
|
|
20
|
+
* @param {Object} modelPreloader - ModelPreloader instance with cache and componentDictionary
|
|
21
|
+
* @param {string} parentComponentId - The parent component's UUID
|
|
22
|
+
* @returns {void}
|
|
23
|
+
*/
|
|
24
|
+
function attachIODevicesToComponent(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
25
|
+
var attachedDevices = componentData.attachedDevices;
|
|
26
|
+
if (!attachedDevices || Object.keys(attachedDevices).length === 0) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log("\uD83D\uDD0C attachIODevicesToComponent(): Attaching ".concat(Object.keys(attachedDevices).length, " IO devices to smart component"));
|
|
30
|
+
for (var _i = 0, _Object$entries = Object.entries(attachedDevices); _i < _Object$entries.length; _i++) {
|
|
31
|
+
var _Object$entries$_i = _rollupPluginBabelHelpers.slicedToArray(_Object$entries[_i], 2),
|
|
32
|
+
attachmentId = _Object$entries$_i[0],
|
|
33
|
+
attachment = _Object$entries$_i[1];
|
|
34
|
+
try {
|
|
35
|
+
var _modelPreloader$compo, _deviceData$ioConfig, _deviceData$ioConfig2, _deviceData$ioConfig3, _attachment$attachmen;
|
|
36
|
+
var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
37
|
+
if (!deviceData || !deviceData.modelKey) {
|
|
38
|
+
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary, skipping"));
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
var cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
42
|
+
if (!cachedDevice) {
|
|
43
|
+
console.warn("\u26A0\uFE0F IO device model not in cache: ".concat(deviceData.modelKey, ", skipping"));
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Clone so each component instance owns its own io-device subtree and materials.
|
|
48
|
+
// Without this, all placed copies of the same smart component share the cached
|
|
49
|
+
// object, causing material mutations (from behaviors) to bleed across instances.
|
|
50
|
+
var deviceModel = cachedDevice.clone();
|
|
51
|
+
deviceModel.traverse(function (child) {
|
|
52
|
+
if (child.isMesh && child.material) {
|
|
53
|
+
child.material = Array.isArray(child.material) ? child.material.map(function (m) {
|
|
54
|
+
return m.clone();
|
|
55
|
+
}) : child.material.clone();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Name the device model
|
|
60
|
+
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
61
|
+
|
|
62
|
+
// Set user data for identification — include ioConfig data points so the
|
|
63
|
+
// component tooltip can render state displays without an extra lookup.
|
|
64
|
+
deviceModel.userData = {
|
|
65
|
+
objectType: 'io-device',
|
|
66
|
+
deviceId: attachment.deviceId,
|
|
67
|
+
attachmentId: attachmentId,
|
|
68
|
+
attachmentLabel: attachment.attachmentLabel,
|
|
69
|
+
parentComponentId: parentComponentId,
|
|
70
|
+
deviceName: deviceData.name || '',
|
|
71
|
+
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
72
|
+
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
73
|
+
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) || [],
|
|
74
|
+
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
75
|
+
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output',
|
|
76
|
+
// Signal wiring sourced from this attachment (for state propagation reference)
|
|
77
|
+
signalOutputs: attachment.signalOutputs || []
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Position at the attachment point
|
|
81
|
+
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
82
|
+
var pos = attachment.attachmentPoint.position;
|
|
83
|
+
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// IO device models are authored at the same real-world unit scale
|
|
87
|
+
// as the host component, so keep them at their natural (1:1) size.
|
|
88
|
+
// Note: attachmentPoint.scale is the connector marker sphere size,
|
|
89
|
+
// NOT a desired device model scale.
|
|
90
|
+
deviceModel.scale.setScalar(1);
|
|
91
|
+
|
|
92
|
+
// Add as child of the component
|
|
93
|
+
componentModel.add(deviceModel);
|
|
94
|
+
console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
|
|
95
|
+
position: deviceModel.position,
|
|
96
|
+
scale: deviceModel.scale
|
|
97
|
+
});
|
|
98
|
+
} catch (err) {
|
|
99
|
+
console.error("\u274C Error attaching IO device ".concat(attachment.deviceId, ":"), err);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
exports.attachIODevicesToComponent = attachIODevicesToComponent;
|