@2112-lab/central-plant 0.3.48 → 0.3.50

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.
@@ -226,204 +226,344 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
226
226
  }
227
227
 
228
228
  /**
229
- * Enrich scene data with world-space bounding boxes and positions for collision avoidance
230
- * @param {Object|Array} sceneData - Original scene data or array of children
231
- * @returns {Object|Array} Enriched scene data (shallow copy with modifications)
229
+ * Enrich sceneData with worldBoundingBox for segments and components
230
+ * Connectors remain with just position information.
231
+ *
232
+ * Uses _bboxCache to avoid recomputing filtered / io-device bboxes
233
+ * when the underlying object's world matrix has not changed.
234
+ *
235
+ * @param {Object} sceneData - Original scene data
236
+ * @returns {Object} Enriched scene data (shallow copy with modifications)
232
237
  * @private
233
238
  */
234
239
  }, {
235
240
  key: "_enrichSceneDataWithBoundingBoxes",
236
241
  value: function _enrichSceneDataWithBoundingBoxes(sceneData) {
237
242
  var _this4 = this;
238
- if (!sceneData) return sceneData;
239
-
240
- // Recursive helper to enrich a node and its children
241
- var _enrichNode = function enrichNode(node) {
242
- if (!node) return node;
243
- var enrichedNode = _rollupPluginBabelHelpers.objectSpread2({}, node);
243
+ // Create a shallow copy of sceneData structure
244
+ var enriched = _rollupPluginBabelHelpers.objectSpread2({}, sceneData);
245
+ if (!sceneData.children || !Array.isArray(sceneData.children)) {
246
+ console.warn('⚠️ sceneData has no children array');
247
+ return enriched;
248
+ }
244
249
 
250
+ // Process children to add worldBoundingBox to segments and components
251
+ enriched.children = sceneData.children.map(function (child) {
245
252
  // Skip computed objects ( elbows etc )
246
- if (node.userData && (node.userData.isComputed === true || node.userData.objectType === 'elbow')) {
247
- return node;
253
+ if (child.userData && (child.userData.isComputed === true || child.userData.objectType === 'elbow')) {
254
+ return child;
248
255
  }
249
256
 
250
- // ── Enrich Segments ──
251
- if (node.userData && node.userData.objectType === 'segment') {
252
- var segmentObject = _this4.sceneViewer.scene.getObjectByProperty('uuid', node.uuid);
257
+ // Enrich segments (check if objectType is 'segment' in userData)
258
+ if (child.userData && child.userData.objectType === 'segment') {
259
+ // Find the actual segment object in the scene
260
+ var segmentObject = _this4.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
253
261
  if (segmentObject) {
262
+ // ── Cache check ──
254
263
  var hash = _this4._matrixHash(segmentObject);
255
- var cached = _this4._bboxCache.get(node.uuid);
264
+ var cached = _this4._bboxCache.get(child.uuid);
256
265
  if (cached && cached.matrixHash === hash && cached.segmentBBox) {
257
- enrichedNode.userData = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, node.userData), {}, {
258
- worldBoundingBox: cached.segmentBBox
259
- });
260
- } else {
261
- var worldBBox = new THREE__namespace.Box3().setFromObject(segmentObject);
262
- var bboxData = {
263
- min: [worldBBox.min.x, worldBBox.min.y, worldBBox.min.z],
264
- max: [worldBBox.max.x, worldBBox.max.y, worldBBox.max.z]
265
- };
266
- _this4._bboxCache.set(node.uuid, {
267
- matrixHash: hash,
268
- segmentBBox: bboxData
269
- });
270
- enrichedNode.userData = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, node.userData), {}, {
271
- worldBoundingBox: bboxData
266
+ return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
267
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
268
+ worldBoundingBox: cached.segmentBBox
269
+ })
272
270
  });
273
271
  }
272
+
273
+ // Compute world bounding box
274
+ var worldBBox = new THREE__namespace.Box3().setFromObject(segmentObject);
275
+ var bboxData = {
276
+ min: [worldBBox.min.x, worldBBox.min.y, worldBBox.min.z],
277
+ max: [worldBBox.max.x, worldBBox.max.y, worldBBox.max.z]
278
+ };
279
+
280
+ // Store in cache
281
+ _this4._bboxCache.set(child.uuid, {
282
+ matrixHash: hash,
283
+ segmentBBox: bboxData
284
+ });
285
+ return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
286
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
287
+ worldBoundingBox: bboxData
288
+ })
289
+ });
290
+ } else {
291
+ console.warn("\u26A0\uFE0F Could not find segment object in scene: ".concat(child.uuid));
274
292
  }
275
293
  }
276
294
 
277
- // ── Enrich Components ──
278
- else if (node.userData && node.userData.objectType === 'component') {
279
- var componentObject = _this4.sceneViewer.scene.getObjectByProperty('uuid', node.uuid);
295
+ // Enrich components (check if objectType is 'component' in userData)
296
+ if (child.userData && child.userData.objectType === 'component') {
297
+ // Find the actual component object in the scene
298
+ var componentObject = _this4.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
280
299
  if (componentObject) {
300
+ // Explicitly update matrices for this component subtree before computing bounding boxes
281
301
  componentObject.updateMatrixWorld(true);
302
+
303
+ // ── Cache check ──
282
304
  var _hash = _this4._matrixHash(componentObject);
283
- var _cached = _this4._bboxCache.get(node.uuid);
305
+ var _cached = _this4._bboxCache.get(child.uuid);
284
306
  if (_cached && _cached.matrixHash === _hash && _cached.filteredBBox) {
285
- enrichedNode.position = {
286
- x: componentObject.position.x,
287
- y: componentObject.position.y,
288
- z: componentObject.position.z
289
- };
290
- enrichedNode.rotation = {
291
- x: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.x),
292
- y: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.y),
293
- z: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.z)
294
- };
295
- enrichedNode.userData = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, node.userData), {}, {
296
- worldBoundingBox: _cached.filteredBBox,
297
- position: [componentObject.position.x, componentObject.position.y, componentObject.position.z]
307
+ // Rebuild enriched child from cached data
308
+ var _enrichedChild = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
309
+ // Sync live transform even on cache hit just in case the manifest (child) is stale
310
+ position: {
311
+ x: componentObject.position.x,
312
+ y: componentObject.position.y,
313
+ z: componentObject.position.z
314
+ },
315
+ rotation: {
316
+ x: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.x),
317
+ y: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.y),
318
+ z: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.z)
319
+ },
320
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
321
+ worldBoundingBox: _cached.filteredBBox,
322
+ position: [componentObject.position.x, componentObject.position.y, componentObject.position.z]
323
+ })
298
324
  });
299
-
300
- // Re-merge cached connectors and devices if they exist
301
- if (!enrichedNode.children) enrichedNode.children = [];
302
- if (_cached.connectorBBoxes) {
303
- _cached.connectorBBoxes.forEach(function (conn) {
304
- return _this4._mergeEnrichedChild(enrichedNode.children, conn);
325
+ if (_cached.ioDeviceBBoxes && _cached.ioDeviceBBoxes.length > 0) {
326
+ if (!_enrichedChild.children) _enrichedChild.children = [];
327
+ _cached.ioDeviceBBoxes.forEach(function (deviceBBox) {
328
+ var existingIndex = _enrichedChild.children.findIndex(function (c) {
329
+ return c.uuid === deviceBBox.uuid;
330
+ });
331
+ if (existingIndex >= 0) {
332
+ _enrichedChild.children[existingIndex] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, _enrichedChild.children[existingIndex]), {}, {
333
+ position: {
334
+ x: deviceBBox.userData.position[0],
335
+ y: deviceBBox.userData.position[1],
336
+ z: deviceBBox.userData.position[2]
337
+ },
338
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, _enrichedChild.children[existingIndex].userData), {}, {
339
+ objectType: 'io-device',
340
+ worldBoundingBox: deviceBBox.worldBoundingBox,
341
+ position: deviceBBox.userData.position
342
+ })
343
+ });
344
+ } else {
345
+ _enrichedChild.children.push({
346
+ uuid: deviceBBox.uuid,
347
+ position: {
348
+ x: deviceBBox.userData.position[0],
349
+ y: deviceBBox.userData.position[1],
350
+ z: deviceBBox.userData.position[2]
351
+ },
352
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, deviceBBox.userData), {}, {
353
+ worldBoundingBox: deviceBBox.worldBoundingBox,
354
+ position: deviceBBox.userData.position
355
+ }),
356
+ children: []
357
+ });
358
+ }
305
359
  });
306
360
  }
307
- if (_cached.ioDeviceBBoxes) {
308
- _cached.ioDeviceBBoxes.forEach(function (dev) {
309
- return _this4._mergeEnrichedChild(enrichedNode.children, dev);
361
+
362
+ // Also reinject connectors from cache
363
+ if (_cached.connectorBBoxes && _cached.connectorBBoxes.length > 0) {
364
+ if (!_enrichedChild.children) _enrichedChild.children = [];
365
+ _cached.connectorBBoxes.forEach(function (connBBox) {
366
+ var existingIndex = _enrichedChild.children.findIndex(function (c) {
367
+ return c.uuid === connBBox.uuid;
368
+ });
369
+ if (existingIndex >= 0) {
370
+ _enrichedChild.children[existingIndex] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, _enrichedChild.children[existingIndex]), {}, {
371
+ position: {
372
+ x: connBBox.userData.position[0],
373
+ y: connBBox.userData.position[1],
374
+ z: connBBox.userData.position[2]
375
+ },
376
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, _enrichedChild.children[existingIndex].userData), {}, {
377
+ worldBoundingBox: connBBox.worldBoundingBox,
378
+ position: connBBox.userData.position
379
+ })
380
+ });
381
+ } else {
382
+ _enrichedChild.children.push({
383
+ uuid: connBBox.uuid,
384
+ position: {
385
+ x: connBBox.userData.position[0],
386
+ y: connBBox.userData.position[1],
387
+ z: connBBox.userData.position[2]
388
+ },
389
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, connBBox.userData), {}, {
390
+ worldBoundingBox: connBBox.worldBoundingBox,
391
+ position: connBBox.userData.position
392
+ }),
393
+ children: []
394
+ });
395
+ }
310
396
  });
311
397
  }
312
- } else {
313
- var filteredBBox = boundingBoxUtils.computeFilteredBoundingBox(componentObject, ['io-device', 'connector']);
314
- var _bboxData = {
315
- min: [filteredBBox.min.x, filteredBBox.min.y, filteredBBox.min.z],
316
- max: [filteredBBox.max.x, filteredBBox.max.y, filteredBBox.max.z]
317
- };
318
- enrichedNode.position = {
398
+ return _enrichedChild;
399
+ }
400
+
401
+ // Compute FILTERED bounding box — excludes io-device and connector subtrees
402
+ // so the component body bbox is tight-fitting and doesn't envelop attached devices
403
+ var filteredBBox = boundingBoxUtils.computeFilteredBoundingBox(componentObject, ['io-device', 'connector']);
404
+ 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), "]"));
405
+ var _bboxData = {
406
+ min: [filteredBBox.min.x, filteredBBox.min.y, filteredBBox.min.z],
407
+ max: [filteredBBox.max.x, filteredBBox.max.y, filteredBBox.max.z]
408
+ };
409
+
410
+ // Build the enriched component entry
411
+ var enrichedChild = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
412
+ // Sync live transform to ensure pathfinder has latest coordinates
413
+ position: {
319
414
  x: componentObject.position.x,
320
415
  y: componentObject.position.y,
321
416
  z: componentObject.position.z
322
- };
323
- enrichedNode.rotation = {
417
+ },
418
+ rotation: {
324
419
  x: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.x),
325
420
  y: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.y),
326
421
  z: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.z)
327
- };
328
- enrichedNode.userData = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, node.userData), {}, {
422
+ },
423
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
329
424
  worldBoundingBox: _bboxData,
330
425
  position: [componentObject.position.x, componentObject.position.y, componentObject.position.z]
426
+ })
427
+ });
428
+
429
+ // Compute separate bounding boxes for each attached io-device
430
+ var ioDeviceBBoxes = boundingBoxUtils.computeIODeviceBoundingBoxes(componentObject);
431
+ if (ioDeviceBBoxes.length > 0) {
432
+ // Ensure children array exists (may already contain connectors)
433
+ if (!enrichedChild.children) {
434
+ enrichedChild.children = [];
435
+ }
436
+
437
+ // Inject io-device entries with their own worldBoundingBox
438
+ ioDeviceBBoxes.forEach(function (deviceBBox) {
439
+ var existingIndex = enrichedChild.children.findIndex(function (c) {
440
+ return c.uuid === deviceBBox.uuid;
441
+ });
442
+ if (existingIndex >= 0) {
443
+ enrichedChild.children[existingIndex] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, enrichedChild.children[existingIndex]), {}, {
444
+ position: {
445
+ x: deviceBBox.userData.position[0],
446
+ y: deviceBBox.userData.position[1],
447
+ z: deviceBBox.userData.position[2]
448
+ },
449
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, enrichedChild.children[existingIndex].userData), {}, {
450
+ objectType: 'io-device',
451
+ worldBoundingBox: deviceBBox.worldBoundingBox,
452
+ position: deviceBBox.userData.position
453
+ })
454
+ });
455
+ } else {
456
+ enrichedChild.children.push({
457
+ uuid: deviceBBox.uuid,
458
+ position: {
459
+ x: deviceBBox.userData.position[0],
460
+ y: deviceBBox.userData.position[1],
461
+ z: deviceBBox.userData.position[2]
462
+ },
463
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, deviceBBox.userData), {}, {
464
+ worldBoundingBox: deviceBBox.worldBoundingBox,
465
+ position: deviceBBox.userData.position
466
+ }),
467
+ children: []
468
+ });
469
+ }
470
+ console.log("\uD83D\uDCE6 Injected io-device bbox for ".concat(deviceBBox.uuid, ": min=[").concat(deviceBBox.worldBoundingBox.min.map(function (v) {
471
+ return v.toFixed(2);
472
+ }).join(', '), "], max=[").concat(deviceBBox.worldBoundingBox.max.map(function (v) {
473
+ return v.toFixed(2);
474
+ }).join(', '), "]"));
331
475
  });
332
- var connectorBBoxes = boundingBoxUtils.computeConnectorBoundingBoxes(componentObject);
333
- var ioDeviceBBoxes = boundingBoxUtils.computeIODeviceBoundingBoxes(componentObject);
334
- if (!enrichedNode.children) enrichedNode.children = [];
335
- connectorBBoxes.forEach(function (conn) {
336
- return _this4._mergeEnrichedChild(enrichedNode.children, conn);
337
- });
338
- ioDeviceBBoxes.forEach(function (dev) {
339
- return _this4._mergeEnrichedChild(enrichedNode.children, dev);
340
- });
341
- _this4._bboxCache.set(node.uuid, {
342
- matrixHash: _hash,
343
- filteredBBox: _bboxData,
344
- ioDeviceBBoxes: ioDeviceBBoxes,
345
- connectorBBoxes: connectorBBoxes
476
+ console.log("\uD83D\uDCE6 Injected ".concat(ioDeviceBBoxes.length, " io-device bounding box(es) for component ").concat(child.uuid));
477
+ }
478
+
479
+ // PHASE 2: Enrich Connectors (CRITICAL for pathfinding API)
480
+ // Also compute world bounding boxes for connectors and inject into children.
481
+ // This ensures endpoints have world coordinates in sceneDataCopy.
482
+ var connectorBBoxes = boundingBoxUtils.computeConnectorBoundingBoxes(componentObject);
483
+ if (connectorBBoxes.length > 0) {
484
+ if (!enrichedChild.children) enrichedChild.children = [];
485
+ connectorBBoxes.forEach(function (connBBox) {
486
+ var existingIndex = enrichedChild.children.findIndex(function (c) {
487
+ return c.uuid === connBBox.uuid;
488
+ });
489
+ if (existingIndex >= 0) {
490
+ enrichedChild.children[existingIndex] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, enrichedChild.children[existingIndex]), {}, {
491
+ position: {
492
+ x: connBBox.userData.position[0],
493
+ y: connBBox.userData.position[1],
494
+ z: connBBox.userData.position[2]
495
+ },
496
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, enrichedChild.children[existingIndex].userData), {}, {
497
+ worldBoundingBox: connBBox.worldBoundingBox,
498
+ position: connBBox.userData.position
499
+ })
500
+ });
501
+ } else {
502
+ enrichedChild.children.push({
503
+ uuid: connBBox.uuid,
504
+ position: {
505
+ x: connBBox.userData.position[0],
506
+ y: connBBox.userData.position[1],
507
+ z: connBBox.userData.position[2]
508
+ },
509
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, connBBox.userData), {}, {
510
+ worldBoundingBox: connBBox.worldBoundingBox,
511
+ position: connBBox.userData.position
512
+ }),
513
+ children: []
514
+ });
515
+ }
346
516
  });
347
517
  }
518
+
519
+ // Store in cache
520
+ _this4._bboxCache.set(child.uuid, {
521
+ matrixHash: _hash,
522
+ filteredBBox: _bboxData,
523
+ ioDeviceBBoxes: ioDeviceBBoxes,
524
+ connectorBBoxes: connectorBBoxes
525
+ });
526
+ return enrichedChild;
527
+ } else {
528
+ console.warn("\u26A0\uFE0F Could not find component object in scene: ".concat(child.uuid));
348
529
  }
349
530
  }
350
531
 
351
- // ── Enrich Standalone Objects (Gateways/Connectors) ──
352
- else if (node.userData && (node.userData.objectType === 'gateway' || node.userData.objectType === 'connector')) {
353
- var _node$userData;
354
- var object = _this4.sceneViewer.scene.getObjectByProperty('uuid', node.uuid) || _this4.sceneViewer.scene.getObjectByProperty('uuid', (_node$userData = node.userData) === null || _node$userData === void 0 ? void 0 : _node$userData.originalUuid);
532
+ // ────────────────────────────────────────────────────────────────────────
533
+ // PHASE 3: Handle top-level Gateways and Connectors
534
+ // ────────────────────────────────────────────────────────────────────────
535
+ if (child.userData && (child.userData.objectType === 'gateway' || child.userData.objectType === 'connector')) {
536
+ var _child$userData;
537
+ var object = _this4.sceneViewer.scene.getObjectByProperty('uuid', child.uuid) || _this4.sceneViewer.scene.getObjectByProperty('uuid', (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid);
355
538
  if (object) {
356
539
  var worldPos = new THREE__namespace.Vector3();
357
540
  object.getWorldPosition(worldPos);
358
- enrichedNode.position = {
359
- x: worldPos.x,
360
- y: worldPos.y,
361
- z: worldPos.z
362
- };
363
- enrichedNode.userData = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, node.userData), {}, {
364
- position: [worldPos.x, worldPos.y, worldPos.z]
541
+ return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
542
+ // Sync live transform to ensure pathfinder has latest coordinates
543
+ position: {
544
+ x: worldPos.x,
545
+ y: worldPos.y,
546
+ z: worldPos.z
547
+ },
548
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
549
+ position: [worldPos.x, worldPos.y, worldPos.z]
550
+ })
365
551
  });
366
-
367
- // If it's a connector, also sync direction
368
- if (node.userData.objectType === 'connector') {
369
- var worldDir = new THREE__namespace.Vector3(0, 0, 1);
370
- if (node.userData.direction) worldDir.set(node.userData.direction[0], node.userData.direction[1], node.userData.direction[2]);
371
- worldDir.applyQuaternion(object.getWorldQuaternion(new THREE__namespace.Quaternion())).normalize();
372
- enrichedNode.userData.direction = [worldDir.x, worldDir.y, worldDir.z];
373
- }
374
552
  }
375
553
  }
376
554
 
377
- // Recurse into children
378
- if (node.children && Array.isArray(node.children)) {
379
- enrichedNode.children = node.children.map(_enrichNode);
380
- }
381
- return enrichedNode;
382
- };
383
-
384
- // Handle root being an array or object
385
- if (Array.isArray(sceneData)) {
386
- return sceneData.map(_enrichNode);
387
- } else if (sceneData.children && Array.isArray(sceneData.children)) {
388
- var enrichedRoot = _rollupPluginBabelHelpers.objectSpread2({}, sceneData);
389
- enrichedRoot.children = sceneData.children.map(_enrichNode);
390
- return enrichedRoot;
391
- } else {
392
- return _enrichNode(sceneData);
393
- }
555
+ // For non-segments and non-components (and if object search failed), return as-is
556
+ return child;
557
+ });
558
+ return enriched;
394
559
  }
395
560
 
396
561
  /**
397
- * Helper to merge an enriched child (connector/device) into a children array
398
- * @private
562
+ * Core pathfinding logic shared across initialization and updates
399
563
  */
400
- }, {
401
- key: "_mergeEnrichedChild",
402
- value: function _mergeEnrichedChild(childrenArray, enrichedData) {
403
- var existingIndex = childrenArray.findIndex(function (c) {
404
- return c.uuid === enrichedData.uuid;
405
- });
406
- var nodeToMerge = {
407
- uuid: enrichedData.uuid,
408
- position: {
409
- x: enrichedData.userData.position[0],
410
- y: enrichedData.userData.position[1],
411
- z: enrichedData.userData.position[2]
412
- },
413
- userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, enrichedData.userData), {}, {
414
- worldBoundingBox: enrichedData.worldBoundingBox
415
- }),
416
- children: []
417
- };
418
- if (existingIndex >= 0) {
419
- childrenArray[existingIndex] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, childrenArray[existingIndex]), nodeToMerge);
420
- } else {
421
- childrenArray.push(nodeToMerge);
422
- }
423
- }
424
564
  }, {
425
565
  key: "_executePathfinding",
426
- value: function () {
566
+ value: (function () {
427
567
  var _executePathfinding2 = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee(sceneData, connections) {
428
568
  var _this5 = this,
429
569
  _sceneDataCopy$childr,
@@ -598,7 +738,7 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
598
738
  return _executePathfinding2.apply(this, arguments);
599
739
  }
600
740
  return _executePathfinding;
601
- }()
741
+ }())
602
742
  }, {
603
743
  key: "getSimplifiedSceneData",
604
744
  value: function getSimplifiedSceneData() {
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
6
- var THREE = require('three');
6
+ require('three');
7
7
  var GLTFExporter = require('../../../node_modules/three/examples/jsm/exporters/GLTFExporter.js');
8
8
  var nameUtils = require('../../utils/nameUtils.js');
9
9
 
@@ -25,8 +25,6 @@ function _interopNamespace(e) {
25
25
  return Object.freeze(n);
26
26
  }
27
27
 
28
- var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
29
-
30
28
  var SceneExportManager = /*#__PURE__*/function () {
31
29
  function SceneExportManager(sceneViewer) {
32
30
  _rollupPluginBabelHelpers.classCallCheck(this, SceneExportManager);
@@ -248,11 +246,10 @@ var SceneExportManager = /*#__PURE__*/function () {
248
246
  };
249
247
  }
250
248
 
251
- // For components: only export child connectors if they were manually added/defined.
252
- // Most connectors are injected from dictionary at import time, but some (like manually placed ones)
253
- // need to be persisted to maintain connections in the exported scene.
249
+ // Only manual segments persist their connector children here.
250
+ // Component connectors are NOT exported they are regenerated from the
251
+ // component dictionary on load (see note below), keeping the scene JSON minimal.
254
252
  if (threeObject.children && threeObject.children.length > 0) {
255
- var _threeObject$userData11;
256
253
  var exportableChildren = [];
257
254
  if (isManualSegment) {
258
255
  // For manual segments, export their connector children
@@ -266,30 +263,15 @@ var SceneExportManager = /*#__PURE__*/function () {
266
263
  }
267
264
  }
268
265
  });
269
- } else if (((_threeObject$userData11 = threeObject.userData) === null || _threeObject$userData11 === void 0 ? void 0 : _threeObject$userData11.objectType) === 'component') {
270
- // For components, export all connectors (including deep children within GLFs)
271
- threeObject.traverse(function (child) {
272
- var _child$userData2;
273
- if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'connector') {
274
- // Calculate position relative to component root
275
- var componentMatrixWorldInverse = threeObject.matrixWorld.clone().invert();
276
- var childWorldPos = new THREE__namespace.Vector3();
277
- child.getWorldPosition(childWorldPos);
278
- var relativePos = childWorldPos.applyMatrix4(componentMatrixWorldInverse);
279
- exportableChildren.push({
280
- uuid: child.uuid,
281
- name: child.name,
282
- type: 'Mesh',
283
- position: {
284
- x: roundIfClose(relativePos.x),
285
- y: roundIfClose(relativePos.y),
286
- z: roundIfClose(relativePos.z)
287
- },
288
- userData: _rollupPluginBabelHelpers.objectSpread2({}, child.userData)
289
- });
290
- }
291
- });
292
266
  }
267
+ // NOTE: Component connectors are intentionally NOT exported.
268
+ // They are defined in the component dictionary and regenerated on load by
269
+ // sceneOperationsManager._injectConnectorChildrenFromDictionary using the
270
+ // matching uuid scheme (`${componentUuid}_${dictConnectorUuid}`), and the
271
+ // pathfinder rebuilds their world positions/bounding boxes on every run
272
+ // (computeConnectorBoundingBoxes). Connections still resolve because the
273
+ // regenerated connector uuids match the connection endpoints.
274
+
293
275
  if (exportableChildren.length > 0) {
294
276
  jsonObject.children = exportableChildren;
295
277
  }
@@ -303,9 +285,9 @@ var SceneExportManager = /*#__PURE__*/function () {
303
285
  // Extract main scene objects (components and standalone connectors)
304
286
  var sceneChildren = [];
305
287
  this.sceneViewer.scene.children.forEach(function (child) {
306
- var _child$userData3;
288
+ var _child$userData2;
307
289
  // Only export components and connectors; skip segments, gateways, polylines, etc.
308
- var objectType = (_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType;
290
+ var objectType = (_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType;
309
291
  if (objectType !== 'component' && objectType !== 'connector') {
310
292
  return;
311
293
  }
@@ -469,14 +451,14 @@ var SceneExportManager = /*#__PURE__*/function () {
469
451
  BufferGeometryUtils = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
470
452
  exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
471
453
  shouldExport = function shouldExport(child) {
472
- var _child$name, _child$userData4, _child$userData5, _child$userData6, _child$userData7;
454
+ var _child$name, _child$userData3, _child$userData4, _child$userData5, _child$userData6;
473
455
  if ((_child$name = child.name) !== null && _child$name !== void 0 && _child$name.includes('Polyline')) return false; // Will handle separately
474
456
  if (child.name === 'fogPlane') return false; // Skip fog plane
475
- if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBrickWall) return false; // Skip environment
476
- if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGround) return false; // Skip environment
477
- if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isBaseGrid) return false; // Skip environment
457
+ if ((_child$userData3 = child.userData) !== null && _child$userData3 !== void 0 && _child$userData3.isBrickWall) return false; // Skip environment
458
+ if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBaseGround) return false; // Skip environment
459
+ if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGrid) return false; // Skip environment
478
460
  if (child.isLight) return false; // Skip lights
479
- if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.isTransformControls) return false; // Skip transform controls
461
+ if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isTransformControls) return false; // Skip transform controls
480
462
  if (child.isTransformControls) return false; // Skip transform controls
481
463
  if (child.type && child.type.includes('TransformControls')) return false;
482
464
  if (child.type && child.type.includes('Helper')) return false; // Skip helpers
@@ -6,6 +6,7 @@ var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHel
6
6
  var THREE = require('three');
7
7
  var OrbitControls = require('../../../node_modules/three/examples/jsm/controls/OrbitControls.js');
8
8
  var GLTFLoader = require('../../../node_modules/three/examples/jsm/loaders/GLTFLoader.js');
9
+ var cameraControlsManager = require('../controls/cameraControlsManager.js');
9
10
 
10
11
  function _interopNamespace(e) {
11
12
  if (e && e.__esModule) return e;
@@ -54,7 +55,7 @@ var SceneInitializationManager = /*#__PURE__*/function () {
54
55
  containerWidth = containerRect.width;
55
56
  containerHeight = containerRect.height; // Create camera (Z-up coordinate system with flipped Y)
56
57
  component.camera = new THREE__namespace.PerspectiveCamera(50, containerWidth / containerHeight, 0.01, 1000);
57
- component.camera.position.set(-8, -9, 2); // Flipped Y direction
58
+ component.camera.position.set(cameraControlsManager.DEFAULT_HOME_VIEW_DIRECTION.x, cameraControlsManager.DEFAULT_HOME_VIEW_DIRECTION.y, cameraControlsManager.HOME_EMPTY_CAMERA_HEIGHT_ABOVE_GROUND);
58
59
  component.camera.up.set(0, 0, 1); // Set Z as up vector
59
60
 
60
61
  // Create renderer