@2112-lab/central-plant 0.1.76 → 0.1.78
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 +656 -75
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/core/centralPlantInternals.js +73 -0
- package/dist/cjs/src/managers/controls/componentDragManager.js +145 -32
- package/dist/cjs/src/managers/controls/transformControlsManager.js +22 -30
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +52 -8
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +41 -4
- package/dist/cjs/src/utils/boundingBoxUtils.js +356 -0
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/core/centralPlantInternals.js +74 -1
- package/dist/esm/src/managers/controls/componentDragManager.js +146 -33
- package/dist/esm/src/managers/controls/transformControlsManager.js +22 -30
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +52 -8
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +41 -4
- package/dist/esm/src/utils/boundingBoxUtils.js +329 -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.78
|
|
23
23
|
* @updated 2025-10-22
|
|
24
24
|
*
|
|
25
25
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -1055,6 +1055,11 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1055
1055
|
});
|
|
1056
1056
|
}
|
|
1057
1057
|
|
|
1058
|
+
// Add attached IO device models for smart components
|
|
1059
|
+
if (componentData.isSmart && componentData.attachedDevices) {
|
|
1060
|
+
this._attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1058
1063
|
// Notify the component manager about the new component
|
|
1059
1064
|
if (componentManager.registerComponent) {
|
|
1060
1065
|
componentManager.registerComponent(componentModel);
|
|
@@ -1105,6 +1110,74 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1105
1110
|
}
|
|
1106
1111
|
}
|
|
1107
1112
|
|
|
1113
|
+
/**
|
|
1114
|
+
* Attach IO device models to a smart component from cached models.
|
|
1115
|
+
* Each device referenced in componentData.attachedDevices is looked up
|
|
1116
|
+
* in the model preloader cache, cloned, positioned, and added as a child.
|
|
1117
|
+
* @param {THREE.Object3D} componentModel - The parent component model
|
|
1118
|
+
* @param {Object} componentData - Component dictionary entry (has attachedDevices)
|
|
1119
|
+
* @param {Object} modelPreloader - ModelPreloader instance
|
|
1120
|
+
* @param {string} parentComponentId - The parent component's UUID
|
|
1121
|
+
* @private
|
|
1122
|
+
*/
|
|
1123
|
+
}, {
|
|
1124
|
+
key: "_attachIODevicesToComponent",
|
|
1125
|
+
value: function _attachIODevicesToComponent(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
1126
|
+
var attachedDevices = componentData.attachedDevices;
|
|
1127
|
+
console.log("\uD83D\uDD0C addComponent(): Attaching ".concat(Object.keys(attachedDevices).length, " IO devices to smart component"));
|
|
1128
|
+
for (var _i = 0, _Object$entries = Object.entries(attachedDevices); _i < _Object$entries.length; _i++) {
|
|
1129
|
+
var _Object$entries$_i = _rollupPluginBabelHelpers.slicedToArray(_Object$entries[_i], 2),
|
|
1130
|
+
attachmentId = _Object$entries$_i[0],
|
|
1131
|
+
attachment = _Object$entries$_i[1];
|
|
1132
|
+
try {
|
|
1133
|
+
var _modelPreloader$compo, _attachment$attachmen;
|
|
1134
|
+
var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
1135
|
+
if (!deviceData || !deviceData.modelKey) {
|
|
1136
|
+
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary, skipping"));
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
var deviceModel = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
1140
|
+
if (!deviceModel) {
|
|
1141
|
+
console.warn("\u26A0\uFE0F IO device model not in cache: ".concat(deviceData.modelKey, ", skipping"));
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// Name the device model
|
|
1146
|
+
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
1147
|
+
|
|
1148
|
+
// Set user data for identification
|
|
1149
|
+
deviceModel.userData = {
|
|
1150
|
+
objectType: 'io-device',
|
|
1151
|
+
deviceId: attachment.deviceId,
|
|
1152
|
+
attachmentId: attachmentId,
|
|
1153
|
+
attachmentLabel: attachment.attachmentLabel,
|
|
1154
|
+
parentComponentId: parentComponentId
|
|
1155
|
+
};
|
|
1156
|
+
|
|
1157
|
+
// Position at the attachment point
|
|
1158
|
+
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
1159
|
+
var pos = attachment.attachmentPoint.position;
|
|
1160
|
+
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
// IO device models are authored at the same real-world unit scale
|
|
1164
|
+
// as the host component, so keep them at their natural (1:1) size.
|
|
1165
|
+
// Note: attachmentPoint.scale is the connector marker sphere size,
|
|
1166
|
+
// NOT a desired device model scale.
|
|
1167
|
+
deviceModel.scale.setScalar(1);
|
|
1168
|
+
|
|
1169
|
+
// Add as child of the component
|
|
1170
|
+
componentModel.add(deviceModel);
|
|
1171
|
+
console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
|
|
1172
|
+
position: deviceModel.position,
|
|
1173
|
+
scale: deviceModel.scale
|
|
1174
|
+
});
|
|
1175
|
+
} catch (err) {
|
|
1176
|
+
console.error("\u274C Error attaching IO device ".concat(attachment.deviceId, ":"), err);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1108
1181
|
/**
|
|
1109
1182
|
* Delete a component from the scene by componentId (internal implementation)
|
|
1110
1183
|
* @param {string} componentId - The UUID of the component to delete
|
|
@@ -191,7 +191,7 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
191
191
|
console.log("\uD83D\uDD0D ModelPreloader available:", !!modelPreloader);
|
|
192
192
|
console.log("\uD83D\uDD0D ComponentDictionary available:", !!(modelPreloader !== null && modelPreloader !== void 0 && modelPreloader.componentDictionary));
|
|
193
193
|
if (!(modelPreloader && modelPreloader.componentDictionary)) {
|
|
194
|
-
_context2.n =
|
|
194
|
+
_context2.n = 14;
|
|
195
195
|
break;
|
|
196
196
|
}
|
|
197
197
|
console.log("\uD83D\uDCDA Available dictionary keys:", Object.keys(modelPreloader.componentDictionary));
|
|
@@ -207,7 +207,7 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
207
207
|
});
|
|
208
208
|
}
|
|
209
209
|
if (!(componentData && componentData.modelKey)) {
|
|
210
|
-
_context2.n =
|
|
210
|
+
_context2.n = 12;
|
|
211
211
|
break;
|
|
212
212
|
}
|
|
213
213
|
// Try to get cached model first
|
|
@@ -247,7 +247,7 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
247
247
|
console.warn("\u26A0\uFE0F Failed to preload model ".concat(componentData.modelKey, ":"), _t2);
|
|
248
248
|
case 8:
|
|
249
249
|
if (!cachedModel) {
|
|
250
|
-
_context2.n =
|
|
250
|
+
_context2.n = 10;
|
|
251
251
|
break;
|
|
252
252
|
}
|
|
253
253
|
this.dragData.previewObject = cachedModel.clone();
|
|
@@ -258,6 +258,14 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
258
258
|
// Store original colors BEFORE making transparent
|
|
259
259
|
this._storeOriginalColors(this.dragData.previewObject);
|
|
260
260
|
|
|
261
|
+
// For smart components, load and attach IO device models to the preview
|
|
262
|
+
if (!(componentData.isSmart && componentData.attachedDevices)) {
|
|
263
|
+
_context2.n = 9;
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
_context2.n = 9;
|
|
267
|
+
return this._attachIODeviceModelsToPreview(this.dragData.previewObject, componentData, modelPreloader);
|
|
268
|
+
case 9:
|
|
261
269
|
// Make the preview semi-transparent
|
|
262
270
|
this._setPreviewTransparency(this.dragData.previewObject, 0.5);
|
|
263
271
|
this.dragData.previewObject.userData = {
|
|
@@ -271,19 +279,19 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
271
279
|
this.sceneViewer.scene.add(this.dragData.previewObject);
|
|
272
280
|
console.log("\u2705 Created ".concat(componentData.isS3Component ? 'S3' : 'static', " GLB preview object for: ").concat(componentId));
|
|
273
281
|
return _context2.a(2);
|
|
274
|
-
case 9:
|
|
275
|
-
console.warn("\u26A0\uFE0F Failed to load model for ".concat(componentId, ", will use fallback"));
|
|
276
282
|
case 10:
|
|
277
|
-
|
|
278
|
-
break;
|
|
283
|
+
console.warn("\u26A0\uFE0F Failed to load model for ".concat(componentId, ", will use fallback"));
|
|
279
284
|
case 11:
|
|
280
|
-
|
|
281
|
-
case 12:
|
|
282
|
-
_context2.n = 14;
|
|
285
|
+
_context2.n = 13;
|
|
283
286
|
break;
|
|
287
|
+
case 12:
|
|
288
|
+
console.warn("\u26A0\uFE0F No modelKey found for component ".concat(componentId));
|
|
284
289
|
case 13:
|
|
285
|
-
|
|
290
|
+
_context2.n = 15;
|
|
291
|
+
break;
|
|
286
292
|
case 14:
|
|
293
|
+
console.warn("\u26A0\uFE0F ModelPreloader or component dictionary not available");
|
|
294
|
+
case 15:
|
|
287
295
|
// Fallback: Create a simple preview mesh if model not available
|
|
288
296
|
geometry = new THREE__namespace.BoxGeometry(1, 1, 1);
|
|
289
297
|
material = new THREE__namespace.MeshPhysicalMaterial({
|
|
@@ -306,7 +314,7 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
306
314
|
this.dragData.previewObject.position.set(1000, 1000, 1000);
|
|
307
315
|
this.sceneViewer.scene.add(this.dragData.previewObject);
|
|
308
316
|
console.log("\u26A0\uFE0F Created fallback wireframe preview for: ".concat(componentId));
|
|
309
|
-
case
|
|
317
|
+
case 16:
|
|
310
318
|
return _context2.a(2);
|
|
311
319
|
}
|
|
312
320
|
}, _callee2, this, [[5, 7], [1, 3]]);
|
|
@@ -316,6 +324,111 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
316
324
|
}
|
|
317
325
|
return _createPreviewObject;
|
|
318
326
|
}()
|
|
327
|
+
/**
|
|
328
|
+
* Load and attach IO device models to a smart component preview
|
|
329
|
+
* @param {THREE.Object3D} parentObject - The parent preview object
|
|
330
|
+
* @param {Object} componentData - Component dictionary entry (must have attachedDevices)
|
|
331
|
+
* @param {Object} modelPreloader - ModelPreloader instance
|
|
332
|
+
* @private
|
|
333
|
+
*/
|
|
334
|
+
)
|
|
335
|
+
}, {
|
|
336
|
+
key: "_attachIODeviceModelsToPreview",
|
|
337
|
+
value: (function () {
|
|
338
|
+
var _attachIODeviceModelsToPreview2 = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee3(parentObject, componentData, modelPreloader) {
|
|
339
|
+
var _i, _Object$entries, _Object$entries$_i, attachmentId, attachment, _modelPreloader$compo, _attachment$attachmen, deviceData, cachedDevice, _modelPreloader$loadi, deviceModel, pos, _t3;
|
|
340
|
+
return _rollupPluginBabelHelpers.regenerator().w(function (_context3) {
|
|
341
|
+
while (1) switch (_context3.n) {
|
|
342
|
+
case 0:
|
|
343
|
+
if (componentData.attachedDevices) {
|
|
344
|
+
_context3.n = 1;
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
return _context3.a(2);
|
|
348
|
+
case 1:
|
|
349
|
+
_i = 0, _Object$entries = Object.entries(componentData.attachedDevices);
|
|
350
|
+
case 2:
|
|
351
|
+
if (!(_i < _Object$entries.length)) {
|
|
352
|
+
_context3.n = 12;
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
_Object$entries$_i = _rollupPluginBabelHelpers.slicedToArray(_Object$entries[_i], 2), attachmentId = _Object$entries$_i[0], attachment = _Object$entries$_i[1];
|
|
356
|
+
_context3.p = 3;
|
|
357
|
+
deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
|
|
358
|
+
if (!(!deviceData || !deviceData.modelKey)) {
|
|
359
|
+
_context3.n = 4;
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
console.warn("\u26A0\uFE0F IO device ".concat(attachment.deviceId, " not found in dictionary for preview"));
|
|
363
|
+
return _context3.a(3, 11);
|
|
364
|
+
case 4:
|
|
365
|
+
// Ensure device model is loaded
|
|
366
|
+
cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
367
|
+
if (cachedDevice) {
|
|
368
|
+
_context3.n = 8;
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
if (!((_modelPreloader$loadi = modelPreloader.loadingPromises) !== null && _modelPreloader$loadi !== void 0 && _modelPreloader$loadi.has(deviceData.modelKey))) {
|
|
372
|
+
_context3.n = 6;
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
_context3.n = 5;
|
|
376
|
+
return modelPreloader.loadingPromises.get(deviceData.modelKey);
|
|
377
|
+
case 5:
|
|
378
|
+
_context3.n = 7;
|
|
379
|
+
break;
|
|
380
|
+
case 6:
|
|
381
|
+
_context3.n = 7;
|
|
382
|
+
return modelPreloader.preloadSingleModel(deviceData.modelKey);
|
|
383
|
+
case 7:
|
|
384
|
+
cachedDevice = modelPreloader.getCachedModelWithDimensions(deviceData.modelKey, attachment.deviceId);
|
|
385
|
+
case 8:
|
|
386
|
+
if (cachedDevice) {
|
|
387
|
+
_context3.n = 9;
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
console.warn("\u26A0\uFE0F Could not load IO device model: ".concat(deviceData.modelKey));
|
|
391
|
+
return _context3.a(3, 11);
|
|
392
|
+
case 9:
|
|
393
|
+
deviceModel = cachedDevice.clone();
|
|
394
|
+
this._cloneMaterials(deviceModel);
|
|
395
|
+
this._storeOriginalColors(deviceModel);
|
|
396
|
+
deviceModel.userData = {
|
|
397
|
+
objectType: 'io-device',
|
|
398
|
+
deviceId: attachment.deviceId,
|
|
399
|
+
attachmentId: attachmentId,
|
|
400
|
+
attachmentLabel: attachment.attachmentLabel
|
|
401
|
+
};
|
|
402
|
+
if ((_attachment$attachmen = attachment.attachmentPoint) !== null && _attachment$attachmen !== void 0 && _attachment$attachmen.position) {
|
|
403
|
+
pos = attachment.attachmentPoint.position;
|
|
404
|
+
deviceModel.position.set(pos.x || 0, pos.y || 0, pos.z || 0);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// IO device models use their natural (1:1) scale — the stored
|
|
408
|
+
// attachmentPoint.scale value is for the connector marker sphere.
|
|
409
|
+
deviceModel.scale.setScalar(1);
|
|
410
|
+
parentObject.add(deviceModel);
|
|
411
|
+
console.log("\u2705 Attached IO device preview: ".concat(attachment.attachmentLabel || attachment.deviceId));
|
|
412
|
+
_context3.n = 11;
|
|
413
|
+
break;
|
|
414
|
+
case 10:
|
|
415
|
+
_context3.p = 10;
|
|
416
|
+
_t3 = _context3.v;
|
|
417
|
+
console.warn("\u26A0\uFE0F Could not attach IO device model ".concat(attachment.deviceId, " to preview:"), _t3);
|
|
418
|
+
case 11:
|
|
419
|
+
_i++;
|
|
420
|
+
_context3.n = 2;
|
|
421
|
+
break;
|
|
422
|
+
case 12:
|
|
423
|
+
return _context3.a(2);
|
|
424
|
+
}
|
|
425
|
+
}, _callee3, this, [[3, 10]]);
|
|
426
|
+
}));
|
|
427
|
+
function _attachIODeviceModelsToPreview(_x5, _x6, _x7) {
|
|
428
|
+
return _attachIODeviceModelsToPreview2.apply(this, arguments);
|
|
429
|
+
}
|
|
430
|
+
return _attachIODeviceModelsToPreview;
|
|
431
|
+
}()
|
|
319
432
|
/**
|
|
320
433
|
* Clone all materials in an object hierarchy to avoid shared material issues
|
|
321
434
|
* @param {THREE.Object3D} object - The object to clone materials for
|
|
@@ -463,8 +576,8 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
463
576
|
});
|
|
464
577
|
|
|
465
578
|
// Check for overlaps
|
|
466
|
-
for (var
|
|
467
|
-
var mesh = _sceneMeshes[
|
|
579
|
+
for (var _i2 = 0, _sceneMeshes = sceneMeshes; _i2 < _sceneMeshes.length; _i2++) {
|
|
580
|
+
var mesh = _sceneMeshes[_i2];
|
|
468
581
|
var meshBBox = new THREE__namespace.Box3().setFromObject(mesh);
|
|
469
582
|
if (previewBBox.intersectsBox(meshBBox)) {
|
|
470
583
|
console.log('⚠️ ComponentDragManager: Overlap detected with:', mesh.userData.objectType || mesh.name || mesh.uuid);
|
|
@@ -778,50 +891,50 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
778
891
|
var _this3 = this;
|
|
779
892
|
if (!element || !componentId) return;
|
|
780
893
|
var handleMouseDown = /*#__PURE__*/function () {
|
|
781
|
-
var _ref = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function
|
|
782
|
-
return _rollupPluginBabelHelpers.regenerator().w(function (
|
|
783
|
-
while (1) switch (
|
|
894
|
+
var _ref = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee4(event) {
|
|
895
|
+
return _rollupPluginBabelHelpers.regenerator().w(function (_context4) {
|
|
896
|
+
while (1) switch (_context4.n) {
|
|
784
897
|
case 0:
|
|
785
898
|
if (!(event.button !== 0)) {
|
|
786
|
-
|
|
899
|
+
_context4.n = 1;
|
|
787
900
|
break;
|
|
788
901
|
}
|
|
789
|
-
return
|
|
902
|
+
return _context4.a(2);
|
|
790
903
|
case 1:
|
|
791
904
|
// Only left mouse button
|
|
792
905
|
event.preventDefault();
|
|
793
|
-
|
|
906
|
+
_context4.n = 2;
|
|
794
907
|
return _this3.startComponentDrag(componentId, element, event);
|
|
795
908
|
case 2:
|
|
796
|
-
return
|
|
909
|
+
return _context4.a(2);
|
|
797
910
|
}
|
|
798
|
-
},
|
|
911
|
+
}, _callee4);
|
|
799
912
|
}));
|
|
800
|
-
return function handleMouseDown(
|
|
913
|
+
return function handleMouseDown(_x8) {
|
|
801
914
|
return _ref.apply(this, arguments);
|
|
802
915
|
};
|
|
803
916
|
}();
|
|
804
917
|
var handleTouchStart = /*#__PURE__*/function () {
|
|
805
|
-
var _ref2 = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function
|
|
806
|
-
return _rollupPluginBabelHelpers.regenerator().w(function (
|
|
807
|
-
while (1) switch (
|
|
918
|
+
var _ref2 = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee5(event) {
|
|
919
|
+
return _rollupPluginBabelHelpers.regenerator().w(function (_context5) {
|
|
920
|
+
while (1) switch (_context5.n) {
|
|
808
921
|
case 0:
|
|
809
922
|
if (!(event.touches.length !== 1)) {
|
|
810
|
-
|
|
923
|
+
_context5.n = 1;
|
|
811
924
|
break;
|
|
812
925
|
}
|
|
813
|
-
return
|
|
926
|
+
return _context5.a(2);
|
|
814
927
|
case 1:
|
|
815
928
|
// Only single touch
|
|
816
929
|
event.preventDefault();
|
|
817
|
-
|
|
930
|
+
_context5.n = 2;
|
|
818
931
|
return _this3.startComponentDrag(componentId, element, event);
|
|
819
932
|
case 2:
|
|
820
|
-
return
|
|
933
|
+
return _context5.a(2);
|
|
821
934
|
}
|
|
822
|
-
},
|
|
935
|
+
}, _callee5);
|
|
823
936
|
}));
|
|
824
|
-
return function handleTouchStart(
|
|
937
|
+
return function handleTouchStart(_x9) {
|
|
825
938
|
return _ref2.apply(this, arguments);
|
|
826
939
|
};
|
|
827
940
|
}();
|
|
@@ -6,6 +6,7 @@ var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHel
|
|
|
6
6
|
var THREE = require('three');
|
|
7
7
|
var transformControls = require('./transformControls.js');
|
|
8
8
|
var objectTypes = require('../../utils/objectTypes.js');
|
|
9
|
+
var boundingBoxUtils = require('../../utils/boundingBoxUtils.js');
|
|
9
10
|
|
|
10
11
|
function _interopNamespace(e) {
|
|
11
12
|
if (e && e.__esModule) return e;
|
|
@@ -942,23 +943,16 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
942
943
|
return;
|
|
943
944
|
}
|
|
944
945
|
try {
|
|
945
|
-
// Create
|
|
946
|
+
// Create bounding box helpers for each selected object
|
|
947
|
+
// Smart components get filtered helpers (component body + individual io-device boxes)
|
|
946
948
|
this.selectedObjects.forEach(function (obj) {
|
|
947
|
-
var
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
isBoundingBox: true
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
// Add to scene
|
|
956
|
-
_this5.scene.add(boundingBoxHelper);
|
|
957
|
-
|
|
958
|
-
// Store in array for later cleanup
|
|
959
|
-
_this5.boundingBoxHelpers.push(boundingBoxHelper);
|
|
949
|
+
var helpers = boundingBoxUtils.createSelectionBoxHelpers(obj, _this5.config.boundingBoxColor);
|
|
950
|
+
helpers.forEach(function (helper) {
|
|
951
|
+
_this5.scene.add(helper);
|
|
952
|
+
_this5.boundingBoxHelpers.push(helper);
|
|
953
|
+
});
|
|
960
954
|
});
|
|
961
|
-
console.log("\uD83D\uDCE6 Bounding boxes created for ".concat(this.selectedObjects.length, " object(s)"));
|
|
955
|
+
console.log("\uD83D\uDCE6 Bounding boxes created for ".concat(this.selectedObjects.length, " object(s) (").concat(this.boundingBoxHelpers.length, " helpers)"));
|
|
962
956
|
} catch (error) {
|
|
963
957
|
console.warn('⚠️ Failed to create bounding boxes:', error);
|
|
964
958
|
}
|
|
@@ -1089,21 +1083,19 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
1089
1083
|
// Update bounding boxes for all selected objects
|
|
1090
1084
|
if (this.selectedObjects.length > 0 && this.boundingBoxHelpers.length > 0) {
|
|
1091
1085
|
try {
|
|
1092
|
-
//
|
|
1093
|
-
this.
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
_this6.boundingBoxCache.set(obj, updatedBoundingBox);
|
|
1106
|
-
}
|
|
1086
|
+
// Ensure all selected objects have up-to-date matrices
|
|
1087
|
+
this.selectedObjects.forEach(function (obj) {
|
|
1088
|
+
return obj.updateMatrixWorld(true);
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
// Use the centralized update function which handles filtered, io-device, and standard helpers
|
|
1092
|
+
boundingBoxUtils.updateSelectionBoxHelpers(this.boundingBoxHelpers, this.selectedObjects, this.scene);
|
|
1093
|
+
|
|
1094
|
+
// Also update the cached bounding box if it exists
|
|
1095
|
+
this.selectedObjects.forEach(function (obj) {
|
|
1096
|
+
if (_this6.boundingBoxCache.has(obj)) {
|
|
1097
|
+
var updatedBoundingBox = new THREE__namespace.Box3().setFromObject(obj);
|
|
1098
|
+
_this6.boundingBoxCache.set(obj, updatedBoundingBox);
|
|
1107
1099
|
}
|
|
1108
1100
|
});
|
|
1109
1101
|
} catch (error) {
|
|
@@ -7,6 +7,7 @@ var THREE = require('three');
|
|
|
7
7
|
var pathfinder = require('@2112-lab/pathfinder');
|
|
8
8
|
var baseDisposable = require('../../core/baseDisposable.js');
|
|
9
9
|
var pathfindingData = require('../../core/pathfindingData.js');
|
|
10
|
+
var boundingBoxUtils = require('../../utils/boundingBoxUtils.js');
|
|
10
11
|
var sceneDataManager = require('./sceneDataManager.js');
|
|
11
12
|
var PathRenderingManager = require('./PathRenderingManager.js');
|
|
12
13
|
var ConnectorManager = require('./ConnectorManager.js');
|
|
@@ -177,20 +178,63 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
177
178
|
// Find the actual component object in the scene
|
|
178
179
|
var componentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
179
180
|
if (componentObject) {
|
|
180
|
-
// Compute
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
// Compute FILTERED bounding box — excludes io-device and connector subtrees
|
|
182
|
+
// so the component body bbox is tight-fitting and doesn't envelop attached devices
|
|
183
|
+
var filteredBBox = boundingBoxUtils.computeFilteredBoundingBox(componentObject, ['io-device', 'connector']);
|
|
184
|
+
console.log("\uD83D\uDD04 Updated worldBoundingBox for component ".concat(child.uuid, " (filtered): min=[").concat(filteredBBox.min.x.toFixed(2), ", ").concat(filteredBBox.min.y.toFixed(2), ", ").concat(filteredBBox.min.z.toFixed(2), "], max=[").concat(filteredBBox.max.x.toFixed(2), ", ").concat(filteredBBox.max.y.toFixed(2), ", ").concat(filteredBBox.max.z.toFixed(2), "]"));
|
|
183
185
|
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
|
|
186
|
+
// Build the enriched component entry
|
|
187
|
+
var enrichedChild = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
|
|
187
188
|
userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
|
|
188
189
|
worldBoundingBox: {
|
|
189
|
-
min: [
|
|
190
|
-
max: [
|
|
190
|
+
min: [filteredBBox.min.x, filteredBBox.min.y, filteredBBox.min.z],
|
|
191
|
+
max: [filteredBBox.max.x, filteredBBox.max.y, filteredBBox.max.z]
|
|
191
192
|
}
|
|
192
193
|
})
|
|
193
194
|
});
|
|
195
|
+
|
|
196
|
+
// Compute separate bounding boxes for each attached io-device
|
|
197
|
+
// These are injected as children so the pathfinder treats each as an independent obstacle
|
|
198
|
+
var ioDeviceBBoxes = boundingBoxUtils.computeIODeviceBoundingBoxes(componentObject);
|
|
199
|
+
if (ioDeviceBBoxes.length > 0) {
|
|
200
|
+
// Ensure children array exists (may already contain connectors)
|
|
201
|
+
if (!enrichedChild.children) {
|
|
202
|
+
enrichedChild.children = [];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Inject io-device entries with their own worldBoundingBox
|
|
206
|
+
ioDeviceBBoxes.forEach(function (deviceBBox) {
|
|
207
|
+
// Check if this io-device already exists in scene data children
|
|
208
|
+
var existingIndex = enrichedChild.children.findIndex(function (c) {
|
|
209
|
+
return c.uuid === deviceBBox.uuid;
|
|
210
|
+
});
|
|
211
|
+
if (existingIndex >= 0) {
|
|
212
|
+
// Update existing entry with bounding box
|
|
213
|
+
enrichedChild.children[existingIndex] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, enrichedChild.children[existingIndex]), {}, {
|
|
214
|
+
userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, enrichedChild.children[existingIndex].userData), {}, {
|
|
215
|
+
objectType: 'io-device',
|
|
216
|
+
worldBoundingBox: deviceBBox.worldBoundingBox
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
} else {
|
|
220
|
+
// Create new entry for the io-device
|
|
221
|
+
enrichedChild.children.push({
|
|
222
|
+
uuid: deviceBBox.uuid,
|
|
223
|
+
userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, deviceBBox.userData), {}, {
|
|
224
|
+
worldBoundingBox: deviceBBox.worldBoundingBox
|
|
225
|
+
}),
|
|
226
|
+
children: []
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
console.log("\uD83D\uDCE6 Injected io-device bbox for ".concat(deviceBBox.uuid, ": min=[").concat(deviceBBox.worldBoundingBox.min.map(function (v) {
|
|
230
|
+
return v.toFixed(2);
|
|
231
|
+
}).join(', '), "], max=[").concat(deviceBBox.worldBoundingBox.max.map(function (v) {
|
|
232
|
+
return v.toFixed(2);
|
|
233
|
+
}).join(', '), "]"));
|
|
234
|
+
});
|
|
235
|
+
console.log("\uD83D\uDCE6 Injected ".concat(ioDeviceBBoxes.length, " io-device bounding box(es) for component ").concat(child.uuid));
|
|
236
|
+
}
|
|
237
|
+
return enrichedChild;
|
|
194
238
|
} else {
|
|
195
239
|
console.warn("\u26A0\uFE0F Could not find component object in scene: ".concat(child.uuid));
|
|
196
240
|
}
|
|
@@ -7,6 +7,7 @@ var THREE = require('three');
|
|
|
7
7
|
var textureConfig = require('../environment/textureConfig.js');
|
|
8
8
|
var modelManager = require('./modelManager.js');
|
|
9
9
|
var sceneClearingUtility = require('../../utils/sceneClearingUtility.js');
|
|
10
|
+
var boundingBoxUtils = require('../../utils/boundingBoxUtils.js');
|
|
10
11
|
|
|
11
12
|
function _interopNamespace(e) {
|
|
12
13
|
if (e && e.__esModule) return e;
|
|
@@ -642,6 +643,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
642
643
|
|
|
643
644
|
/**
|
|
644
645
|
* Helper function to compute world bounding boxes
|
|
646
|
+
* For components: uses filtered bbox (excludes io-device and connector subtrees)
|
|
647
|
+
* For io-devices: computes separate bounding boxes and injects them as children
|
|
645
648
|
*/
|
|
646
649
|
}, {
|
|
647
650
|
key: "computeWorldBoundingBoxes",
|
|
@@ -680,12 +683,46 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
680
683
|
};
|
|
681
684
|
jsonObject = _findJsonObject(data.scene.children);
|
|
682
685
|
if (jsonObject) {
|
|
683
|
-
// Compute world bounding box
|
|
684
|
-
var boundingBox = new THREE__namespace.Box3().setFromObject(object);
|
|
685
|
-
|
|
686
686
|
// Store in JSON userData for pathfinder (skip for gateways - they're just routing points)
|
|
687
687
|
if (!jsonObject.userData) jsonObject.userData = {};
|
|
688
|
-
if (jsonObject.userData.objectType
|
|
688
|
+
if (jsonObject.userData.objectType === 'component') {
|
|
689
|
+
// For components: compute filtered bounding box (excludes io-device and connector subtrees)
|
|
690
|
+
var filteredBBox = boundingBoxUtils.computeFilteredBoundingBox(object, ['io-device', 'connector']);
|
|
691
|
+
jsonObject.userData.worldBoundingBox = {
|
|
692
|
+
min: filteredBBox.min.toArray(),
|
|
693
|
+
max: filteredBBox.max.toArray()
|
|
694
|
+
};
|
|
695
|
+
console.log("Added filtered world bounding box for component:", jsonObject.userData.worldBoundingBox);
|
|
696
|
+
|
|
697
|
+
// Compute and inject separate io-device bounding boxes as children
|
|
698
|
+
var ioDeviceBBoxes = boundingBoxUtils.computeIODeviceBoundingBoxes(object);
|
|
699
|
+
if (ioDeviceBBoxes.length > 0) {
|
|
700
|
+
if (!jsonObject.children) jsonObject.children = [];
|
|
701
|
+
ioDeviceBBoxes.forEach(function (deviceBBox) {
|
|
702
|
+
var existingIndex = jsonObject.children.findIndex(function (c) {
|
|
703
|
+
return c.uuid === deviceBBox.uuid;
|
|
704
|
+
});
|
|
705
|
+
if (existingIndex >= 0) {
|
|
706
|
+
// Update existing entry
|
|
707
|
+
if (!jsonObject.children[existingIndex].userData) jsonObject.children[existingIndex].userData = {};
|
|
708
|
+
jsonObject.children[existingIndex].userData.objectType = 'io-device';
|
|
709
|
+
jsonObject.children[existingIndex].userData.worldBoundingBox = deviceBBox.worldBoundingBox;
|
|
710
|
+
} else {
|
|
711
|
+
// Create new entry
|
|
712
|
+
jsonObject.children.push({
|
|
713
|
+
uuid: deviceBBox.uuid,
|
|
714
|
+
userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, deviceBBox.userData), {}, {
|
|
715
|
+
worldBoundingBox: deviceBBox.worldBoundingBox
|
|
716
|
+
}),
|
|
717
|
+
children: []
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
console.log("\uD83D\uDCE6 Injected ".concat(ioDeviceBBoxes.length, " io-device bbox(es) for component ").concat(jsonObject.uuid));
|
|
722
|
+
}
|
|
723
|
+
} else if (jsonObject.userData.objectType !== 'gateway') {
|
|
724
|
+
// For non-component, non-gateway objects: standard bounding box
|
|
725
|
+
var boundingBox = new THREE__namespace.Box3().setFromObject(object);
|
|
689
726
|
jsonObject.userData.worldBoundingBox = {
|
|
690
727
|
min: boundingBox.min.toArray(),
|
|
691
728
|
max: boundingBox.max.toArray()
|