@2112-lab/central-plant 0.1.93 → 0.1.95

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.
@@ -3957,6 +3957,17 @@ var TransformControlsManager = /*#__PURE__*/function () {
3957
3957
  obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
3958
3958
  obj.userData._multiSelectOriginalScale = obj.scale.clone();
3959
3959
  });
3960
+
3961
+ // Snapshot group position and helper geometry vertices so we can do
3962
+ // cheap per-frame bbox translation without re-traversing the mesh hierarchy.
3963
+ _this2._dragStartGroupPosition = _this2.multiSelectionGroup.position.clone();
3964
+ _this2.boundingBoxHelpers.forEach(function (helper) {
3965
+ var _helper$geometry;
3966
+ var posAttr = (_helper$geometry = helper.geometry) === null || _helper$geometry === void 0 || (_helper$geometry = _helper$geometry.attributes) === null || _helper$geometry === void 0 ? void 0 : _helper$geometry.position;
3967
+ if (posAttr) {
3968
+ helper.userData._dragStartPositions = new Float32Array(posAttr.array);
3969
+ }
3970
+ });
3960
3971
  }
3961
3972
 
3962
3973
  // Disable orbit controls during transformation
@@ -4021,6 +4032,13 @@ var TransformControlsManager = /*#__PURE__*/function () {
4021
4032
  }
4022
4033
  }
4023
4034
  case 3:
4035
+ // Ensure the bounding box reflects the final post-drag object position.
4036
+ // applyMultiSelectionTransform calls _finalizeMultiSelectionTransform →
4037
+ // createMultiBoundingBox for moves above the threshold. Call updateBoundingBox
4038
+ // here as a safety net for sub-threshold moves or rotation mode, where
4039
+ // _finalizeMultiSelectionTransform is not triggered.
4040
+ _this2.updateBoundingBox();
4041
+
4024
4042
  // Dispatch custom scene update event after transform completes
4025
4043
  if (typeof window !== 'undefined') {
4026
4044
  console.log('📡 Dispatching sceneUpdateComplete event after transform');
@@ -4034,6 +4052,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
4034
4052
  });
4035
4053
  window.dispatchEvent(sceneCompleteEvent);
4036
4054
  }
4055
+
4056
+ // Clean up per-drag snapshots
4057
+ _this2._dragStartGroupPosition = null;
4058
+ _this2.boundingBoxHelpers.forEach(function (helper) {
4059
+ delete helper.userData._dragStartPositions;
4060
+ });
4037
4061
  console.log("\u2705 Transform completed: ".concat(_this2.currentMode, " mode"));
4038
4062
  case 4:
4039
4063
  return _context.a(2);
@@ -4042,33 +4066,16 @@ var TransformControlsManager = /*#__PURE__*/function () {
4042
4066
  }));
4043
4067
  // Transform changing event
4044
4068
  this.eventHandlers.transforming = function () {
4045
- // Apply real-time visual transformation to objects during drag
4069
+ // Apply real-time visual transformation to objects during drag.
4046
4070
  if (_this2.selectedObjects.length > 0 && _this2.multiSelectionGroup) {
4047
4071
  _this2.applyRealtimeTransform();
4048
4072
  }
4049
4073
 
4050
- // Clear the bounding box cache for all selected objects during transformation
4051
- _this2.selectedObjects.forEach(function (obj) {
4052
- if (_this2.boundingBoxCache.has(obj)) {
4053
- _this2.boundingBoxCache.delete(obj);
4054
- }
4055
- });
4056
-
4057
- // Update bounding box during transformation
4058
- _this2.updateBoundingBox();
4059
-
4060
- // Dispatch custom scene update event during transform (optional - fires continuously)
4061
- if (typeof window !== 'undefined') {
4062
- var _this2$selectedObject2;
4063
- var sceneCompleteEvent = new CustomEvent('sceneUpdateComplete', {
4064
- detail: {
4065
- timestamp: Date.now(),
4066
- transformType: _this2.currentMode,
4067
- objectName: ((_this2$selectedObject2 = _this2.selectedObjects[0]) === null || _this2$selectedObject2 === void 0 ? void 0 : _this2$selectedObject2.name) || 'unknown',
4068
- isTransforming: true
4069
- }
4070
- });
4071
- window.dispatchEvent(sceneCompleteEvent);
4074
+ // Per-frame bbox tracking: during translate we can cheaply shift the
4075
+ // pre-snapshotted helper geometry vertices by the drag delta instead of
4076
+ // re-traversing the full mesh hierarchy every pointermove.
4077
+ if (_this2.currentMode === 'translate') {
4078
+ _this2._applyDeltaToBoundingBoxHelpers();
4072
4079
  }
4073
4080
  };
4074
4081
  // First remove any existing listeners to prevent duplicates
@@ -4821,6 +4828,43 @@ var TransformControlsManager = /*#__PURE__*/function () {
4821
4828
  }
4822
4829
  }
4823
4830
 
4831
+ /**
4832
+ * Cheap per-frame bounding box update during translation drag.
4833
+ * Shifts the 8 pre-snapshotted geometry vertices of every helper by the
4834
+ * current drag delta. O(8 additions per helper) — no mesh traversal.
4835
+ * Only valid for translate mode where the box shape is invariant.
4836
+ * @private
4837
+ */
4838
+ }, {
4839
+ key: "_applyDeltaToBoundingBoxHelpers",
4840
+ value: function _applyDeltaToBoundingBoxHelpers() {
4841
+ if (!this._dragStartGroupPosition || this.boundingBoxHelpers.length === 0) return;
4842
+ var delta = this.multiSelectionGroup.position.clone().sub(this._dragStartGroupPosition);
4843
+ var _iterator3 = _createForOfIteratorHelper(this.boundingBoxHelpers),
4844
+ _step3;
4845
+ try {
4846
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
4847
+ var _helper$geometry2;
4848
+ var helper = _step3.value;
4849
+ var startPositions = helper.userData._dragStartPositions;
4850
+ var posAttr = (_helper$geometry2 = helper.geometry) === null || _helper$geometry2 === void 0 || (_helper$geometry2 = _helper$geometry2.attributes) === null || _helper$geometry2 === void 0 ? void 0 : _helper$geometry2.position;
4851
+ if (!startPositions || !posAttr) continue;
4852
+ var arr = posAttr.array;
4853
+ // 8 vertices × 3 floats (x, y, z)
4854
+ for (var i = 0; i < 24; i += 3) {
4855
+ arr[i] = startPositions[i] + delta.x;
4856
+ arr[i + 1] = startPositions[i + 1] + delta.y;
4857
+ arr[i + 2] = startPositions[i + 2] + delta.z;
4858
+ }
4859
+ posAttr.needsUpdate = true;
4860
+ }
4861
+ } catch (err) {
4862
+ _iterator3.e(err);
4863
+ } finally {
4864
+ _iterator3.f();
4865
+ }
4866
+ }
4867
+
4824
4868
  /**
4825
4869
  * Set the transformation mode
4826
4870
  * @param {'translate' | 'rotate' | 'scale'} mode - The transformation mode
@@ -5195,11 +5239,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
5195
5239
  var objectFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
5196
5240
  var objectsWithBounds = this.getSelectableObjectsWithBounds(objectFilter);
5197
5241
  var intersections = [];
5198
- var _iterator3 = _createForOfIteratorHelper(objectsWithBounds),
5199
- _step3;
5242
+ var _iterator4 = _createForOfIteratorHelper(objectsWithBounds),
5243
+ _step4;
5200
5244
  try {
5201
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
5202
- var item = _step3.value;
5245
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
5246
+ var item = _step4.value;
5203
5247
  var object = item.object,
5204
5248
  boundingBox = item.boundingBox;
5205
5249
 
@@ -5219,9 +5263,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
5219
5263
 
5220
5264
  // Sort by distance (closest first)
5221
5265
  } catch (err) {
5222
- _iterator3.e(err);
5266
+ _iterator4.e(err);
5223
5267
  } finally {
5224
- _iterator3.f();
5268
+ _iterator4.f();
5225
5269
  }
5226
5270
  intersections.sort(function (a, b) {
5227
5271
  return a.distance - b.distance;
@@ -11457,11 +11501,35 @@ var SceneExportManager = /*#__PURE__*/function () {
11457
11501
  // For connectors/gateways: no children (they're leaf nodes)
11458
11502
  if (threeObject.children && threeObject.children.length > 0) {
11459
11503
  var exportableChildren = [];
11460
- if (threeObject.userData.objectType === 'component') ; else if (isManualSegment) {
11461
- // For manual segments, export their connector children
11504
+ if (threeObject.userData.objectType === 'component') {
11505
+ // Export connector children (skip mesh geometry - it lives in the component dictionary GLB)
11462
11506
  threeObject.children.forEach(function (child) {
11463
11507
  var _child$userData;
11464
- if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'segment-connector') {
11508
+ if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector') {
11509
+ var connectorJson = {
11510
+ // Use the raw Three.js UUID — connections in currentSceneData reference this exact value
11511
+ uuid: child.uuid,
11512
+ userData: _objectSpread2(_objectSpread2({
11513
+ objectType: 'connector'
11514
+ }, child.userData.direction ? {
11515
+ direction: child.userData.direction
11516
+ } : {}), child.userData.group ? {
11517
+ group: child.userData.group
11518
+ } : {}),
11519
+ position: {
11520
+ x: roundIfClose(child.position.x),
11521
+ y: roundIfClose(child.position.y),
11522
+ z: roundIfClose(child.position.z)
11523
+ }
11524
+ };
11525
+ exportableChildren.push(connectorJson);
11526
+ }
11527
+ });
11528
+ } else if (isManualSegment) {
11529
+ // For manual segments, export their connector children
11530
+ threeObject.children.forEach(function (child) {
11531
+ var _child$userData2;
11532
+ if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment-connector') {
11465
11533
  // Call the class method using bound reference
11466
11534
  var connectorJson = convertSegmentConnectorToJson(child, threeObject);
11467
11535
  if (connectorJson) {
@@ -11487,9 +11555,9 @@ var SceneExportManager = /*#__PURE__*/function () {
11487
11555
  var findManualSegments = function findManualSegments(object) {
11488
11556
  var manualSegments = [];
11489
11557
  object.traverse(function (child) {
11490
- var _child$userData2;
11558
+ var _child$userData3;
11491
11559
  // Check if this is a manual segment
11492
- if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment') {
11560
+ if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'segment') {
11493
11561
  manualSegments.push(child);
11494
11562
  }
11495
11563
  });
@@ -11689,14 +11757,14 @@ var SceneExportManager = /*#__PURE__*/function () {
11689
11757
  BufferGeometryUtils$1 = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
11690
11758
  exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
11691
11759
  shouldExport = function shouldExport(child) {
11692
- var _child$name2, _child$userData3, _child$userData4, _child$userData5, _child$userData6;
11760
+ var _child$name2, _child$userData4, _child$userData5, _child$userData6, _child$userData7;
11693
11761
  if ((_child$name2 = child.name) !== null && _child$name2 !== void 0 && _child$name2.includes('Polyline')) return false; // Will handle separately
11694
11762
  if (child.name === 'fogPlane') return false; // Skip fog plane
11695
- if ((_child$userData3 = child.userData) !== null && _child$userData3 !== void 0 && _child$userData3.isBrickWall) return false; // Skip environment
11696
- if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBaseGround) return false; // Skip environment
11697
- if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGrid) return false; // Skip environment
11763
+ if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBrickWall) return false; // Skip environment
11764
+ if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGround) return false; // Skip environment
11765
+ if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isBaseGrid) return false; // Skip environment
11698
11766
  if (child.isLight) return false; // Skip lights
11699
- if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isTransformControls) return false; // Skip transform controls
11767
+ if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.isTransformControls) return false; // Skip transform controls
11700
11768
  if (child.isTransformControls) return false; // Skip transform controls
11701
11769
  if (child.type && child.type.includes('TransformControls')) return false;
11702
11770
  if (child.type && child.type.includes('Helper')) return false; // Skip helpers
@@ -28829,9 +28897,13 @@ var ModelManager = /*#__PURE__*/function () {
28829
28897
  var _this = this;
28830
28898
  var connectorChildren = [];
28831
28899
  targetMesh.children.forEach(function (child, index) {
28900
+ var _child$userData;
28832
28901
  var isConnectorGeometry = child.geometry && (child.geometry.uuid === 'CONNECTOR-GEO' || child.geometry.type === 'SphereGeometry' && child.geometry.parameters);
28833
28902
  var isConnectorByName = child.name && child.name.toLowerCase().includes('connector');
28834
- if (isConnectorGeometry && isConnectorByName) {
28903
+ // Also recognise connectors declared via userData (e.g. inline connectors from SAMPLE_1.json
28904
+ // whose geometry may be a fallback BufferGeometry rather than a SphereGeometry).
28905
+ var isConnectorByUserData = ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector';
28906
+ if (isConnectorGeometry && isConnectorByName || isConnectorByUserData) {
28835
28907
  // Ensure userData exists and has worldBoundingBox
28836
28908
  if (!child.userData) child.userData = {};
28837
28909
  if (!child.userData.worldBoundingBox) {
@@ -29115,8 +29187,8 @@ var ModelManager = /*#__PURE__*/function () {
29115
29187
  requiredModels = new Set();
29116
29188
  console.log("\uD83D\uDD0D Checking ".concat(data.scene.children.length, " scene objects for required models..."));
29117
29189
  data.scene.children.forEach(function (child) {
29118
- var _child$userData;
29119
- var libraryId = (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.libraryId;
29190
+ var _child$userData2;
29191
+ var libraryId = (_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.libraryId;
29120
29192
  if (libraryId) {
29121
29193
  if (componentDictionary[libraryId]) {
29122
29194
  var modelKey = componentDictionary[libraryId].modelKey;
@@ -30171,6 +30243,24 @@ var SceneOperationsManager = /*#__PURE__*/function () {
30171
30243
  }
30172
30244
  }
30173
30245
  });
30246
+
30247
+ // Ensure CONNECTOR_GATEWAY_SPHERE exists even when all connectors are nested inside
30248
+ // component children (e.g. SAMPLE_1.json inline connector definitions). Without
30249
+ // this geometry the connector meshes fall back to empty BufferGeometry, which then
30250
+ // causes _preserveConnectorChildren to drop them during GLB model replacement.
30251
+ if (!geometries['CONNECTOR_GATEWAY_SPHERE']) {
30252
+ var hasNestedConnectors = data.scene.children.some(function (child) {
30253
+ var _child$userData3;
30254
+ return ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'component' && Array.isArray(child.children) && child.children.some(function (nestedChild) {
30255
+ var _nestedChild$userData;
30256
+ return ((_nestedChild$userData = nestedChild.userData) === null || _nestedChild$userData === void 0 ? void 0 : _nestedChild$userData.objectType) === 'connector';
30257
+ });
30258
+ });
30259
+ if (hasNestedConnectors) {
30260
+ geometries['CONNECTOR_GATEWAY_SPHERE'] = new THREE__namespace.SphereGeometry(0.1, 16, 16);
30261
+ console.log('🔮 Created shared sphere geometry for nested inline connectors (radius: 0.1)');
30262
+ }
30263
+ }
30174
30264
  return geometries;
30175
30265
  }
30176
30266
 
@@ -30556,12 +30646,12 @@ var SceneOperationsManager = /*#__PURE__*/function () {
30556
30646
  _step;
30557
30647
  try {
30558
30648
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
30559
- var _object$userData, _child$userData3;
30649
+ var _object$userData, _child$userData4;
30560
30650
  var child = _step.value;
30561
30651
  // Enhanced matching logic with hardcoded UUID priority
30562
30652
 
30563
30653
  // Strategy 1: Direct hardcoded UUID match (HIGHEST PRIORITY)
30564
- if (child.uuid === object.uuid || child.uuid === ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.originalUuid) || object.uuid === ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid)) {
30654
+ if (child.uuid === object.uuid || child.uuid === ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.originalUuid) || object.uuid === ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid)) {
30565
30655
  return child;
30566
30656
  }
30567
30657
 
@@ -30706,6 +30796,9 @@ var SceneOperationsManager = /*#__PURE__*/function () {
30706
30796
  // Phase 6: Load behaviors (after GLB models are present so output objects can be resolved)
30707
30797
  this._processBehaviors(data);
30708
30798
  console.log('✅ Scene loaded successfully');
30799
+
30800
+ // Notify UI components (e.g. SceneHierarchy) that the scene is fully loaded
30801
+ this.sceneViewer.emit('scene-loaded');
30709
30802
  _context4.n = 7;
30710
30803
  break;
30711
30804
  case 6:
@@ -30817,10 +30910,10 @@ var SceneOperationsManager = /*#__PURE__*/function () {
30817
30910
  var componentsProcessed = 0;
30818
30911
  var connectorsInjected = 0;
30819
30912
  data.scene.children.forEach(function (child) {
30820
- var _child$userData4, _child$userData5, _child$userData6;
30821
- var childType = ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.objectType) || ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType);
30913
+ var _child$userData5, _child$userData6, _child$userData7;
30914
+ var childType = ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType) || ((_child$userData6 = child.userData) === null || _child$userData6 === void 0 ? void 0 : _child$userData6.objectType);
30822
30915
  // Only process components with libraryId
30823
- if (childType === 'component' && (_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.libraryId) {
30916
+ if (childType === 'component' && (_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.libraryId) {
30824
30917
  var libraryId = child.userData.libraryId;
30825
30918
  var dictEntry = componentDictionary[libraryId];
30826
30919
 
@@ -30977,17 +31070,17 @@ var SceneOperationsManager = /*#__PURE__*/function () {
30977
31070
  geometries = this.createSceneGeometries(data, componentDictionary); // Create basic objects and track GLB replacements
30978
31071
  libraryObjectsToReplace = [];
30979
31072
  data.scene.children.forEach(function (child, index) {
30980
- var _child$userData7, _child$userData8;
31073
+ var _child$userData8, _child$userData9;
30981
31074
  var createdObject = _this4.createSceneObject(child, geometries, materials, componentDictionary);
30982
31075
  _this4.sceneViewer.scene.add(createdObject);
30983
31076
 
30984
31077
  // Track objects that need GLB model replacement
30985
- if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.libraryId && componentDictionary[(_child$userData8 = child.userData) === null || _child$userData8 === void 0 ? void 0 : _child$userData8.libraryId]) {
30986
- var _child$userData9;
31078
+ if ((_child$userData8 = child.userData) !== null && _child$userData8 !== void 0 && _child$userData8.libraryId && componentDictionary[(_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.libraryId]) {
31079
+ var _child$userData0;
30987
31080
  libraryObjectsToReplace.push({
30988
31081
  basicObject: createdObject,
30989
31082
  jsonData: child,
30990
- componentData: componentDictionary[(_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.libraryId]
31083
+ componentData: componentDictionary[(_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.libraryId]
30991
31084
  });
30992
31085
  }
30993
31086
  });
@@ -31126,8 +31219,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
31126
31219
  var instanceBehaviors = [];
31127
31220
  if (Array.isArray(data === null || data === void 0 || (_data$scene3 = data.scene) === null || _data$scene3 === void 0 ? void 0 : _data$scene3.children)) {
31128
31221
  data.scene.children.forEach(function (child) {
31129
- var _child$userData0, _compData$defaultBeha;
31130
- var libraryId = (_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.libraryId;
31222
+ var _child$userData1, _compData$defaultBeha;
31223
+ var libraryId = (_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.libraryId;
31131
31224
  if (!libraryId) return;
31132
31225
  var instanceUuid = child.uuid;
31133
31226
  // Skip instances whose defaults were already resolved by Step A
@@ -31518,8 +31611,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
31518
31611
  // Process children (connectors, etc.) if they exist
31519
31612
  if (componentModel.children && componentModel.children.length > 0) {
31520
31613
  componentModel.children.forEach(function (child) {
31521
- var _child$userData1, _child$userData10;
31522
- var childType = ((_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.objectType) || ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType);
31614
+ var _child$userData10, _child$userData11;
31615
+ var childType = ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType) || ((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType);
31523
31616
  if (childType === 'connector') {
31524
31617
  var _child$geometry;
31525
31618
  var childBoundingBox = new THREE__namespace.Box3().setFromObject(child);
@@ -31604,8 +31697,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
31604
31697
  if (segment.children && segment.children.length > 0) {
31605
31698
  var childrenToRemove = _toConsumableArray(segment.children);
31606
31699
  childrenToRemove.forEach(function (child) {
31607
- var _child$userData11;
31608
- if ((_child$userData11 = child.userData) !== null && _child$userData11 !== void 0 && _child$userData11.isPipeElbow) {
31700
+ var _child$userData12;
31701
+ if ((_child$userData12 = child.userData) !== null && _child$userData12 !== void 0 && _child$userData12.isPipeElbow) {
31609
31702
  console.log("\uD83D\uDDD1\uFE0F Removing elbow child from segment before manualization: ".concat(child.uuid));
31610
31703
  segment.remove(child);
31611
31704
  if (child.geometry) child.geometry.dispose();
@@ -37110,7 +37203,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
37110
37203
  * Initialize the CentralPlant manager
37111
37204
  *
37112
37205
  * @constructor
37113
- * @version 0.1.93
37206
+ * @version 0.1.95
37114
37207
  * @updated 2025-10-22
37115
37208
  *
37116
37209
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -19,7 +19,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
19
19
  * Initialize the CentralPlant manager
20
20
  *
21
21
  * @constructor
22
- * @version 0.1.93
22
+ * @version 0.1.95
23
23
  * @updated 2025-10-22
24
24
  *
25
25
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -257,6 +257,17 @@ var TransformControlsManager = /*#__PURE__*/function () {
257
257
  obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
258
258
  obj.userData._multiSelectOriginalScale = obj.scale.clone();
259
259
  });
260
+
261
+ // Snapshot group position and helper geometry vertices so we can do
262
+ // cheap per-frame bbox translation without re-traversing the mesh hierarchy.
263
+ _this2._dragStartGroupPosition = _this2.multiSelectionGroup.position.clone();
264
+ _this2.boundingBoxHelpers.forEach(function (helper) {
265
+ var _helper$geometry;
266
+ var posAttr = (_helper$geometry = helper.geometry) === null || _helper$geometry === void 0 || (_helper$geometry = _helper$geometry.attributes) === null || _helper$geometry === void 0 ? void 0 : _helper$geometry.position;
267
+ if (posAttr) {
268
+ helper.userData._dragStartPositions = new Float32Array(posAttr.array);
269
+ }
270
+ });
260
271
  }
261
272
 
262
273
  // Disable orbit controls during transformation
@@ -321,6 +332,13 @@ var TransformControlsManager = /*#__PURE__*/function () {
321
332
  }
322
333
  }
323
334
  case 3:
335
+ // Ensure the bounding box reflects the final post-drag object position.
336
+ // applyMultiSelectionTransform calls _finalizeMultiSelectionTransform →
337
+ // createMultiBoundingBox for moves above the threshold. Call updateBoundingBox
338
+ // here as a safety net for sub-threshold moves or rotation mode, where
339
+ // _finalizeMultiSelectionTransform is not triggered.
340
+ _this2.updateBoundingBox();
341
+
324
342
  // Dispatch custom scene update event after transform completes
325
343
  if (typeof window !== 'undefined') {
326
344
  console.log('📡 Dispatching sceneUpdateComplete event after transform');
@@ -334,6 +352,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
334
352
  });
335
353
  window.dispatchEvent(sceneCompleteEvent);
336
354
  }
355
+
356
+ // Clean up per-drag snapshots
357
+ _this2._dragStartGroupPosition = null;
358
+ _this2.boundingBoxHelpers.forEach(function (helper) {
359
+ delete helper.userData._dragStartPositions;
360
+ });
337
361
  console.log("\u2705 Transform completed: ".concat(_this2.currentMode, " mode"));
338
362
  case 4:
339
363
  return _context.a(2);
@@ -342,33 +366,16 @@ var TransformControlsManager = /*#__PURE__*/function () {
342
366
  }));
343
367
  // Transform changing event
344
368
  this.eventHandlers.transforming = function () {
345
- // Apply real-time visual transformation to objects during drag
369
+ // Apply real-time visual transformation to objects during drag.
346
370
  if (_this2.selectedObjects.length > 0 && _this2.multiSelectionGroup) {
347
371
  _this2.applyRealtimeTransform();
348
372
  }
349
373
 
350
- // Clear the bounding box cache for all selected objects during transformation
351
- _this2.selectedObjects.forEach(function (obj) {
352
- if (_this2.boundingBoxCache.has(obj)) {
353
- _this2.boundingBoxCache.delete(obj);
354
- }
355
- });
356
-
357
- // Update bounding box during transformation
358
- _this2.updateBoundingBox();
359
-
360
- // Dispatch custom scene update event during transform (optional - fires continuously)
361
- if (typeof window !== 'undefined') {
362
- var _this2$selectedObject2;
363
- var sceneCompleteEvent = new CustomEvent('sceneUpdateComplete', {
364
- detail: {
365
- timestamp: Date.now(),
366
- transformType: _this2.currentMode,
367
- objectName: ((_this2$selectedObject2 = _this2.selectedObjects[0]) === null || _this2$selectedObject2 === void 0 ? void 0 : _this2$selectedObject2.name) || 'unknown',
368
- isTransforming: true
369
- }
370
- });
371
- window.dispatchEvent(sceneCompleteEvent);
374
+ // Per-frame bbox tracking: during translate we can cheaply shift the
375
+ // pre-snapshotted helper geometry vertices by the drag delta instead of
376
+ // re-traversing the full mesh hierarchy every pointermove.
377
+ if (_this2.currentMode === 'translate') {
378
+ _this2._applyDeltaToBoundingBoxHelpers();
372
379
  }
373
380
  };
374
381
  // First remove any existing listeners to prevent duplicates
@@ -1121,6 +1128,43 @@ var TransformControlsManager = /*#__PURE__*/function () {
1121
1128
  }
1122
1129
  }
1123
1130
 
1131
+ /**
1132
+ * Cheap per-frame bounding box update during translation drag.
1133
+ * Shifts the 8 pre-snapshotted geometry vertices of every helper by the
1134
+ * current drag delta. O(8 additions per helper) — no mesh traversal.
1135
+ * Only valid for translate mode where the box shape is invariant.
1136
+ * @private
1137
+ */
1138
+ }, {
1139
+ key: "_applyDeltaToBoundingBoxHelpers",
1140
+ value: function _applyDeltaToBoundingBoxHelpers() {
1141
+ if (!this._dragStartGroupPosition || this.boundingBoxHelpers.length === 0) return;
1142
+ var delta = this.multiSelectionGroup.position.clone().sub(this._dragStartGroupPosition);
1143
+ var _iterator3 = _rollupPluginBabelHelpers.createForOfIteratorHelper(this.boundingBoxHelpers),
1144
+ _step3;
1145
+ try {
1146
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1147
+ var _helper$geometry2;
1148
+ var helper = _step3.value;
1149
+ var startPositions = helper.userData._dragStartPositions;
1150
+ var posAttr = (_helper$geometry2 = helper.geometry) === null || _helper$geometry2 === void 0 || (_helper$geometry2 = _helper$geometry2.attributes) === null || _helper$geometry2 === void 0 ? void 0 : _helper$geometry2.position;
1151
+ if (!startPositions || !posAttr) continue;
1152
+ var arr = posAttr.array;
1153
+ // 8 vertices × 3 floats (x, y, z)
1154
+ for (var i = 0; i < 24; i += 3) {
1155
+ arr[i] = startPositions[i] + delta.x;
1156
+ arr[i + 1] = startPositions[i + 1] + delta.y;
1157
+ arr[i + 2] = startPositions[i + 2] + delta.z;
1158
+ }
1159
+ posAttr.needsUpdate = true;
1160
+ }
1161
+ } catch (err) {
1162
+ _iterator3.e(err);
1163
+ } finally {
1164
+ _iterator3.f();
1165
+ }
1166
+ }
1167
+
1124
1168
  /**
1125
1169
  * Set the transformation mode
1126
1170
  * @param {'translate' | 'rotate' | 'scale'} mode - The transformation mode
@@ -1495,11 +1539,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
1495
1539
  var objectFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
1496
1540
  var objectsWithBounds = this.getSelectableObjectsWithBounds(objectFilter);
1497
1541
  var intersections = [];
1498
- var _iterator3 = _rollupPluginBabelHelpers.createForOfIteratorHelper(objectsWithBounds),
1499
- _step3;
1542
+ var _iterator4 = _rollupPluginBabelHelpers.createForOfIteratorHelper(objectsWithBounds),
1543
+ _step4;
1500
1544
  try {
1501
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1502
- var item = _step3.value;
1545
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
1546
+ var item = _step4.value;
1503
1547
  var object = item.object,
1504
1548
  boundingBox = item.boundingBox;
1505
1549
 
@@ -1519,9 +1563,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
1519
1563
 
1520
1564
  // Sort by distance (closest first)
1521
1565
  } catch (err) {
1522
- _iterator3.e(err);
1566
+ _iterator4.e(err);
1523
1567
  } finally {
1524
- _iterator3.f();
1568
+ _iterator4.f();
1525
1569
  }
1526
1570
  intersections.sort(function (a, b) {
1527
1571
  return a.distance - b.distance;
@@ -146,9 +146,13 @@ var ModelManager = /*#__PURE__*/function () {
146
146
  var _this = this;
147
147
  var connectorChildren = [];
148
148
  targetMesh.children.forEach(function (child, index) {
149
+ var _child$userData;
149
150
  var isConnectorGeometry = child.geometry && (child.geometry.uuid === 'CONNECTOR-GEO' || child.geometry.type === 'SphereGeometry' && child.geometry.parameters);
150
151
  var isConnectorByName = child.name && child.name.toLowerCase().includes('connector');
151
- if (isConnectorGeometry && isConnectorByName) {
152
+ // Also recognise connectors declared via userData (e.g. inline connectors from SAMPLE_1.json
153
+ // whose geometry may be a fallback BufferGeometry rather than a SphereGeometry).
154
+ var isConnectorByUserData = ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector';
155
+ if (isConnectorGeometry && isConnectorByName || isConnectorByUserData) {
152
156
  // Ensure userData exists and has worldBoundingBox
153
157
  if (!child.userData) child.userData = {};
154
158
  if (!child.userData.worldBoundingBox) {
@@ -432,8 +436,8 @@ var ModelManager = /*#__PURE__*/function () {
432
436
  requiredModels = new Set();
433
437
  console.log("\uD83D\uDD0D Checking ".concat(data.scene.children.length, " scene objects for required models..."));
434
438
  data.scene.children.forEach(function (child) {
435
- var _child$userData;
436
- var libraryId = (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.libraryId;
439
+ var _child$userData2;
440
+ var libraryId = (_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.libraryId;
437
441
  if (libraryId) {
438
442
  if (componentDictionary[libraryId]) {
439
443
  var modelKey = componentDictionary[libraryId].modelKey;
@@ -242,11 +242,35 @@ var SceneExportManager = /*#__PURE__*/function () {
242
242
  // For connectors/gateways: no children (they're leaf nodes)
243
243
  if (threeObject.children && threeObject.children.length > 0) {
244
244
  var exportableChildren = [];
245
- if (threeObject.userData.objectType === 'component') ; else if (isManualSegment) {
246
- // For manual segments, export their connector children
245
+ if (threeObject.userData.objectType === 'component') {
246
+ // Export connector children (skip mesh geometry - it lives in the component dictionary GLB)
247
247
  threeObject.children.forEach(function (child) {
248
248
  var _child$userData;
249
- if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'segment-connector') {
249
+ if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector') {
250
+ var connectorJson = {
251
+ // Use the raw Three.js UUID — connections in currentSceneData reference this exact value
252
+ uuid: child.uuid,
253
+ userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({
254
+ objectType: 'connector'
255
+ }, child.userData.direction ? {
256
+ direction: child.userData.direction
257
+ } : {}), child.userData.group ? {
258
+ group: child.userData.group
259
+ } : {}),
260
+ position: {
261
+ x: roundIfClose(child.position.x),
262
+ y: roundIfClose(child.position.y),
263
+ z: roundIfClose(child.position.z)
264
+ }
265
+ };
266
+ exportableChildren.push(connectorJson);
267
+ }
268
+ });
269
+ } else if (isManualSegment) {
270
+ // For manual segments, export their connector children
271
+ threeObject.children.forEach(function (child) {
272
+ var _child$userData2;
273
+ if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment-connector') {
250
274
  // Call the class method using bound reference
251
275
  var connectorJson = convertSegmentConnectorToJson(child, threeObject);
252
276
  if (connectorJson) {
@@ -272,9 +296,9 @@ var SceneExportManager = /*#__PURE__*/function () {
272
296
  var findManualSegments = function findManualSegments(object) {
273
297
  var manualSegments = [];
274
298
  object.traverse(function (child) {
275
- var _child$userData2;
299
+ var _child$userData3;
276
300
  // Check if this is a manual segment
277
- if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment') {
301
+ if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'segment') {
278
302
  manualSegments.push(child);
279
303
  }
280
304
  });
@@ -474,14 +498,14 @@ var SceneExportManager = /*#__PURE__*/function () {
474
498
  BufferGeometryUtils = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
475
499
  exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
476
500
  shouldExport = function shouldExport(child) {
477
- var _child$name2, _child$userData3, _child$userData4, _child$userData5, _child$userData6;
501
+ var _child$name2, _child$userData4, _child$userData5, _child$userData6, _child$userData7;
478
502
  if ((_child$name2 = child.name) !== null && _child$name2 !== void 0 && _child$name2.includes('Polyline')) return false; // Will handle separately
479
503
  if (child.name === 'fogPlane') return false; // Skip fog plane
480
- if ((_child$userData3 = child.userData) !== null && _child$userData3 !== void 0 && _child$userData3.isBrickWall) return false; // Skip environment
481
- if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBaseGround) return false; // Skip environment
482
- if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGrid) return false; // Skip environment
504
+ if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBrickWall) return false; // Skip environment
505
+ if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGround) return false; // Skip environment
506
+ if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isBaseGrid) return false; // Skip environment
483
507
  if (child.isLight) return false; // Skip lights
484
- if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isTransformControls) return false; // Skip transform controls
508
+ if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.isTransformControls) return false; // Skip transform controls
485
509
  if (child.isTransformControls) return false; // Skip transform controls
486
510
  if (child.type && child.type.includes('TransformControls')) return false;
487
511
  if (child.type && child.type.includes('Helper')) return false; // Skip helpers
@@ -261,6 +261,24 @@ var SceneOperationsManager = /*#__PURE__*/function () {
261
261
  }
262
262
  }
263
263
  });
264
+
265
+ // Ensure CONNECTOR_GATEWAY_SPHERE exists even when all connectors are nested inside
266
+ // component children (e.g. SAMPLE_1.json inline connector definitions). Without
267
+ // this geometry the connector meshes fall back to empty BufferGeometry, which then
268
+ // causes _preserveConnectorChildren to drop them during GLB model replacement.
269
+ if (!geometries['CONNECTOR_GATEWAY_SPHERE']) {
270
+ var hasNestedConnectors = data.scene.children.some(function (child) {
271
+ var _child$userData3;
272
+ return ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'component' && Array.isArray(child.children) && child.children.some(function (nestedChild) {
273
+ var _nestedChild$userData;
274
+ return ((_nestedChild$userData = nestedChild.userData) === null || _nestedChild$userData === void 0 ? void 0 : _nestedChild$userData.objectType) === 'connector';
275
+ });
276
+ });
277
+ if (hasNestedConnectors) {
278
+ geometries['CONNECTOR_GATEWAY_SPHERE'] = new THREE__namespace.SphereGeometry(0.1, 16, 16);
279
+ console.log('🔮 Created shared sphere geometry for nested inline connectors (radius: 0.1)');
280
+ }
281
+ }
264
282
  return geometries;
265
283
  }
266
284
 
@@ -646,12 +664,12 @@ var SceneOperationsManager = /*#__PURE__*/function () {
646
664
  _step;
647
665
  try {
648
666
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
649
- var _object$userData, _child$userData3;
667
+ var _object$userData, _child$userData4;
650
668
  var child = _step.value;
651
669
  // Enhanced matching logic with hardcoded UUID priority
652
670
 
653
671
  // Strategy 1: Direct hardcoded UUID match (HIGHEST PRIORITY)
654
- if (child.uuid === object.uuid || child.uuid === ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.originalUuid) || object.uuid === ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid)) {
672
+ if (child.uuid === object.uuid || child.uuid === ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.originalUuid) || object.uuid === ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid)) {
655
673
  return child;
656
674
  }
657
675
 
@@ -796,6 +814,9 @@ var SceneOperationsManager = /*#__PURE__*/function () {
796
814
  // Phase 6: Load behaviors (after GLB models are present so output objects can be resolved)
797
815
  this._processBehaviors(data);
798
816
  console.log('✅ Scene loaded successfully');
817
+
818
+ // Notify UI components (e.g. SceneHierarchy) that the scene is fully loaded
819
+ this.sceneViewer.emit('scene-loaded');
799
820
  _context4.n = 7;
800
821
  break;
801
822
  case 6:
@@ -907,10 +928,10 @@ var SceneOperationsManager = /*#__PURE__*/function () {
907
928
  var componentsProcessed = 0;
908
929
  var connectorsInjected = 0;
909
930
  data.scene.children.forEach(function (child) {
910
- var _child$userData4, _child$userData5, _child$userData6;
911
- var childType = ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.objectType) || ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType);
931
+ var _child$userData5, _child$userData6, _child$userData7;
932
+ var childType = ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType) || ((_child$userData6 = child.userData) === null || _child$userData6 === void 0 ? void 0 : _child$userData6.objectType);
912
933
  // Only process components with libraryId
913
- if (childType === 'component' && (_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.libraryId) {
934
+ if (childType === 'component' && (_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.libraryId) {
914
935
  var libraryId = child.userData.libraryId;
915
936
  var dictEntry = componentDictionary[libraryId];
916
937
 
@@ -1067,17 +1088,17 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1067
1088
  geometries = this.createSceneGeometries(data, componentDictionary); // Create basic objects and track GLB replacements
1068
1089
  libraryObjectsToReplace = [];
1069
1090
  data.scene.children.forEach(function (child, index) {
1070
- var _child$userData7, _child$userData8;
1091
+ var _child$userData8, _child$userData9;
1071
1092
  var createdObject = _this4.createSceneObject(child, geometries, materials, componentDictionary);
1072
1093
  _this4.sceneViewer.scene.add(createdObject);
1073
1094
 
1074
1095
  // Track objects that need GLB model replacement
1075
- if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.libraryId && componentDictionary[(_child$userData8 = child.userData) === null || _child$userData8 === void 0 ? void 0 : _child$userData8.libraryId]) {
1076
- var _child$userData9;
1096
+ if ((_child$userData8 = child.userData) !== null && _child$userData8 !== void 0 && _child$userData8.libraryId && componentDictionary[(_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.libraryId]) {
1097
+ var _child$userData0;
1077
1098
  libraryObjectsToReplace.push({
1078
1099
  basicObject: createdObject,
1079
1100
  jsonData: child,
1080
- componentData: componentDictionary[(_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.libraryId]
1101
+ componentData: componentDictionary[(_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.libraryId]
1081
1102
  });
1082
1103
  }
1083
1104
  });
@@ -1216,8 +1237,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1216
1237
  var instanceBehaviors = [];
1217
1238
  if (Array.isArray(data === null || data === void 0 || (_data$scene3 = data.scene) === null || _data$scene3 === void 0 ? void 0 : _data$scene3.children)) {
1218
1239
  data.scene.children.forEach(function (child) {
1219
- var _child$userData0, _compData$defaultBeha;
1220
- var libraryId = (_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.libraryId;
1240
+ var _child$userData1, _compData$defaultBeha;
1241
+ var libraryId = (_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.libraryId;
1221
1242
  if (!libraryId) return;
1222
1243
  var instanceUuid = child.uuid;
1223
1244
  // Skip instances whose defaults were already resolved by Step A
@@ -1608,8 +1629,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1608
1629
  // Process children (connectors, etc.) if they exist
1609
1630
  if (componentModel.children && componentModel.children.length > 0) {
1610
1631
  componentModel.children.forEach(function (child) {
1611
- var _child$userData1, _child$userData10;
1612
- var childType = ((_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.objectType) || ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType);
1632
+ var _child$userData10, _child$userData11;
1633
+ var childType = ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType) || ((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType);
1613
1634
  if (childType === 'connector') {
1614
1635
  var _child$geometry;
1615
1636
  var childBoundingBox = new THREE__namespace.Box3().setFromObject(child);
@@ -1694,8 +1715,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1694
1715
  if (segment.children && segment.children.length > 0) {
1695
1716
  var childrenToRemove = _rollupPluginBabelHelpers.toConsumableArray(segment.children);
1696
1717
  childrenToRemove.forEach(function (child) {
1697
- var _child$userData11;
1698
- if ((_child$userData11 = child.userData) !== null && _child$userData11 !== void 0 && _child$userData11.isPipeElbow) {
1718
+ var _child$userData12;
1719
+ if ((_child$userData12 = child.userData) !== null && _child$userData12 !== void 0 && _child$userData12.isPipeElbow) {
1699
1720
  console.log("\uD83D\uDDD1\uFE0F Removing elbow child from segment before manualization: ".concat(child.uuid));
1700
1721
  segment.remove(child);
1701
1722
  if (child.geometry) child.geometry.dispose();
@@ -15,7 +15,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
15
15
  * Initialize the CentralPlant manager
16
16
  *
17
17
  * @constructor
18
- * @version 0.1.93
18
+ * @version 0.1.95
19
19
  * @updated 2025-10-22
20
20
  *
21
21
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -233,6 +233,17 @@ var TransformControlsManager = /*#__PURE__*/function () {
233
233
  obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
234
234
  obj.userData._multiSelectOriginalScale = obj.scale.clone();
235
235
  });
236
+
237
+ // Snapshot group position and helper geometry vertices so we can do
238
+ // cheap per-frame bbox translation without re-traversing the mesh hierarchy.
239
+ _this2._dragStartGroupPosition = _this2.multiSelectionGroup.position.clone();
240
+ _this2.boundingBoxHelpers.forEach(function (helper) {
241
+ var _helper$geometry;
242
+ var posAttr = (_helper$geometry = helper.geometry) === null || _helper$geometry === void 0 || (_helper$geometry = _helper$geometry.attributes) === null || _helper$geometry === void 0 ? void 0 : _helper$geometry.position;
243
+ if (posAttr) {
244
+ helper.userData._dragStartPositions = new Float32Array(posAttr.array);
245
+ }
246
+ });
236
247
  }
237
248
 
238
249
  // Disable orbit controls during transformation
@@ -297,6 +308,13 @@ var TransformControlsManager = /*#__PURE__*/function () {
297
308
  }
298
309
  }
299
310
  case 3:
311
+ // Ensure the bounding box reflects the final post-drag object position.
312
+ // applyMultiSelectionTransform calls _finalizeMultiSelectionTransform →
313
+ // createMultiBoundingBox for moves above the threshold. Call updateBoundingBox
314
+ // here as a safety net for sub-threshold moves or rotation mode, where
315
+ // _finalizeMultiSelectionTransform is not triggered.
316
+ _this2.updateBoundingBox();
317
+
300
318
  // Dispatch custom scene update event after transform completes
301
319
  if (typeof window !== 'undefined') {
302
320
  console.log('📡 Dispatching sceneUpdateComplete event after transform');
@@ -310,6 +328,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
310
328
  });
311
329
  window.dispatchEvent(sceneCompleteEvent);
312
330
  }
331
+
332
+ // Clean up per-drag snapshots
333
+ _this2._dragStartGroupPosition = null;
334
+ _this2.boundingBoxHelpers.forEach(function (helper) {
335
+ delete helper.userData._dragStartPositions;
336
+ });
313
337
  console.log("\u2705 Transform completed: ".concat(_this2.currentMode, " mode"));
314
338
  case 4:
315
339
  return _context.a(2);
@@ -318,33 +342,16 @@ var TransformControlsManager = /*#__PURE__*/function () {
318
342
  }));
319
343
  // Transform changing event
320
344
  this.eventHandlers.transforming = function () {
321
- // Apply real-time visual transformation to objects during drag
345
+ // Apply real-time visual transformation to objects during drag.
322
346
  if (_this2.selectedObjects.length > 0 && _this2.multiSelectionGroup) {
323
347
  _this2.applyRealtimeTransform();
324
348
  }
325
349
 
326
- // Clear the bounding box cache for all selected objects during transformation
327
- _this2.selectedObjects.forEach(function (obj) {
328
- if (_this2.boundingBoxCache.has(obj)) {
329
- _this2.boundingBoxCache.delete(obj);
330
- }
331
- });
332
-
333
- // Update bounding box during transformation
334
- _this2.updateBoundingBox();
335
-
336
- // Dispatch custom scene update event during transform (optional - fires continuously)
337
- if (typeof window !== 'undefined') {
338
- var _this2$selectedObject2;
339
- var sceneCompleteEvent = new CustomEvent('sceneUpdateComplete', {
340
- detail: {
341
- timestamp: Date.now(),
342
- transformType: _this2.currentMode,
343
- objectName: ((_this2$selectedObject2 = _this2.selectedObjects[0]) === null || _this2$selectedObject2 === void 0 ? void 0 : _this2$selectedObject2.name) || 'unknown',
344
- isTransforming: true
345
- }
346
- });
347
- window.dispatchEvent(sceneCompleteEvent);
350
+ // Per-frame bbox tracking: during translate we can cheaply shift the
351
+ // pre-snapshotted helper geometry vertices by the drag delta instead of
352
+ // re-traversing the full mesh hierarchy every pointermove.
353
+ if (_this2.currentMode === 'translate') {
354
+ _this2._applyDeltaToBoundingBoxHelpers();
348
355
  }
349
356
  };
350
357
  // First remove any existing listeners to prevent duplicates
@@ -1097,6 +1104,43 @@ var TransformControlsManager = /*#__PURE__*/function () {
1097
1104
  }
1098
1105
  }
1099
1106
 
1107
+ /**
1108
+ * Cheap per-frame bounding box update during translation drag.
1109
+ * Shifts the 8 pre-snapshotted geometry vertices of every helper by the
1110
+ * current drag delta. O(8 additions per helper) — no mesh traversal.
1111
+ * Only valid for translate mode where the box shape is invariant.
1112
+ * @private
1113
+ */
1114
+ }, {
1115
+ key: "_applyDeltaToBoundingBoxHelpers",
1116
+ value: function _applyDeltaToBoundingBoxHelpers() {
1117
+ if (!this._dragStartGroupPosition || this.boundingBoxHelpers.length === 0) return;
1118
+ var delta = this.multiSelectionGroup.position.clone().sub(this._dragStartGroupPosition);
1119
+ var _iterator3 = _createForOfIteratorHelper(this.boundingBoxHelpers),
1120
+ _step3;
1121
+ try {
1122
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1123
+ var _helper$geometry2;
1124
+ var helper = _step3.value;
1125
+ var startPositions = helper.userData._dragStartPositions;
1126
+ var posAttr = (_helper$geometry2 = helper.geometry) === null || _helper$geometry2 === void 0 || (_helper$geometry2 = _helper$geometry2.attributes) === null || _helper$geometry2 === void 0 ? void 0 : _helper$geometry2.position;
1127
+ if (!startPositions || !posAttr) continue;
1128
+ var arr = posAttr.array;
1129
+ // 8 vertices × 3 floats (x, y, z)
1130
+ for (var i = 0; i < 24; i += 3) {
1131
+ arr[i] = startPositions[i] + delta.x;
1132
+ arr[i + 1] = startPositions[i + 1] + delta.y;
1133
+ arr[i + 2] = startPositions[i + 2] + delta.z;
1134
+ }
1135
+ posAttr.needsUpdate = true;
1136
+ }
1137
+ } catch (err) {
1138
+ _iterator3.e(err);
1139
+ } finally {
1140
+ _iterator3.f();
1141
+ }
1142
+ }
1143
+
1100
1144
  /**
1101
1145
  * Set the transformation mode
1102
1146
  * @param {'translate' | 'rotate' | 'scale'} mode - The transformation mode
@@ -1471,11 +1515,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
1471
1515
  var objectFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
1472
1516
  var objectsWithBounds = this.getSelectableObjectsWithBounds(objectFilter);
1473
1517
  var intersections = [];
1474
- var _iterator3 = _createForOfIteratorHelper(objectsWithBounds),
1475
- _step3;
1518
+ var _iterator4 = _createForOfIteratorHelper(objectsWithBounds),
1519
+ _step4;
1476
1520
  try {
1477
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1478
- var item = _step3.value;
1521
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
1522
+ var item = _step4.value;
1479
1523
  var object = item.object,
1480
1524
  boundingBox = item.boundingBox;
1481
1525
 
@@ -1495,9 +1539,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
1495
1539
 
1496
1540
  // Sort by distance (closest first)
1497
1541
  } catch (err) {
1498
- _iterator3.e(err);
1542
+ _iterator4.e(err);
1499
1543
  } finally {
1500
- _iterator3.f();
1544
+ _iterator4.f();
1501
1545
  }
1502
1546
  intersections.sort(function (a, b) {
1503
1547
  return a.distance - b.distance;
@@ -122,9 +122,13 @@ var ModelManager = /*#__PURE__*/function () {
122
122
  var _this = this;
123
123
  var connectorChildren = [];
124
124
  targetMesh.children.forEach(function (child, index) {
125
+ var _child$userData;
125
126
  var isConnectorGeometry = child.geometry && (child.geometry.uuid === 'CONNECTOR-GEO' || child.geometry.type === 'SphereGeometry' && child.geometry.parameters);
126
127
  var isConnectorByName = child.name && child.name.toLowerCase().includes('connector');
127
- if (isConnectorGeometry && isConnectorByName) {
128
+ // Also recognise connectors declared via userData (e.g. inline connectors from SAMPLE_1.json
129
+ // whose geometry may be a fallback BufferGeometry rather than a SphereGeometry).
130
+ var isConnectorByUserData = ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector';
131
+ if (isConnectorGeometry && isConnectorByName || isConnectorByUserData) {
128
132
  // Ensure userData exists and has worldBoundingBox
129
133
  if (!child.userData) child.userData = {};
130
134
  if (!child.userData.worldBoundingBox) {
@@ -408,8 +412,8 @@ var ModelManager = /*#__PURE__*/function () {
408
412
  requiredModels = new Set();
409
413
  console.log("\uD83D\uDD0D Checking ".concat(data.scene.children.length, " scene objects for required models..."));
410
414
  data.scene.children.forEach(function (child) {
411
- var _child$userData;
412
- var libraryId = (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.libraryId;
415
+ var _child$userData2;
416
+ var libraryId = (_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.libraryId;
413
417
  if (libraryId) {
414
418
  if (componentDictionary[libraryId]) {
415
419
  var modelKey = componentDictionary[libraryId].modelKey;
@@ -220,11 +220,35 @@ var SceneExportManager = /*#__PURE__*/function () {
220
220
  // For connectors/gateways: no children (they're leaf nodes)
221
221
  if (threeObject.children && threeObject.children.length > 0) {
222
222
  var exportableChildren = [];
223
- if (threeObject.userData.objectType === 'component') ; else if (isManualSegment) {
224
- // For manual segments, export their connector children
223
+ if (threeObject.userData.objectType === 'component') {
224
+ // Export connector children (skip mesh geometry - it lives in the component dictionary GLB)
225
225
  threeObject.children.forEach(function (child) {
226
226
  var _child$userData;
227
- if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'segment-connector') {
227
+ if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector') {
228
+ var connectorJson = {
229
+ // Use the raw Three.js UUID — connections in currentSceneData reference this exact value
230
+ uuid: child.uuid,
231
+ userData: _objectSpread2(_objectSpread2({
232
+ objectType: 'connector'
233
+ }, child.userData.direction ? {
234
+ direction: child.userData.direction
235
+ } : {}), child.userData.group ? {
236
+ group: child.userData.group
237
+ } : {}),
238
+ position: {
239
+ x: roundIfClose(child.position.x),
240
+ y: roundIfClose(child.position.y),
241
+ z: roundIfClose(child.position.z)
242
+ }
243
+ };
244
+ exportableChildren.push(connectorJson);
245
+ }
246
+ });
247
+ } else if (isManualSegment) {
248
+ // For manual segments, export their connector children
249
+ threeObject.children.forEach(function (child) {
250
+ var _child$userData2;
251
+ if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment-connector') {
228
252
  // Call the class method using bound reference
229
253
  var connectorJson = convertSegmentConnectorToJson(child, threeObject);
230
254
  if (connectorJson) {
@@ -250,9 +274,9 @@ var SceneExportManager = /*#__PURE__*/function () {
250
274
  var findManualSegments = function findManualSegments(object) {
251
275
  var manualSegments = [];
252
276
  object.traverse(function (child) {
253
- var _child$userData2;
277
+ var _child$userData3;
254
278
  // Check if this is a manual segment
255
- if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment') {
279
+ if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'segment') {
256
280
  manualSegments.push(child);
257
281
  }
258
282
  });
@@ -452,14 +476,14 @@ var SceneExportManager = /*#__PURE__*/function () {
452
476
  BufferGeometryUtils = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
453
477
  exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
454
478
  shouldExport = function shouldExport(child) {
455
- var _child$name2, _child$userData3, _child$userData4, _child$userData5, _child$userData6;
479
+ var _child$name2, _child$userData4, _child$userData5, _child$userData6, _child$userData7;
456
480
  if ((_child$name2 = child.name) !== null && _child$name2 !== void 0 && _child$name2.includes('Polyline')) return false; // Will handle separately
457
481
  if (child.name === 'fogPlane') return false; // Skip fog plane
458
- if ((_child$userData3 = child.userData) !== null && _child$userData3 !== void 0 && _child$userData3.isBrickWall) return false; // Skip environment
459
- if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBaseGround) return false; // Skip environment
460
- if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGrid) return false; // Skip environment
482
+ if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBrickWall) return false; // Skip environment
483
+ if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGround) return false; // Skip environment
484
+ if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isBaseGrid) return false; // Skip environment
461
485
  if (child.isLight) return false; // Skip lights
462
- if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isTransformControls) return false; // Skip transform controls
486
+ if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.isTransformControls) return false; // Skip transform controls
463
487
  if (child.isTransformControls) return false; // Skip transform controls
464
488
  if (child.type && child.type.includes('TransformControls')) return false;
465
489
  if (child.type && child.type.includes('Helper')) return false; // Skip helpers
@@ -237,6 +237,24 @@ var SceneOperationsManager = /*#__PURE__*/function () {
237
237
  }
238
238
  }
239
239
  });
240
+
241
+ // Ensure CONNECTOR_GATEWAY_SPHERE exists even when all connectors are nested inside
242
+ // component children (e.g. SAMPLE_1.json inline connector definitions). Without
243
+ // this geometry the connector meshes fall back to empty BufferGeometry, which then
244
+ // causes _preserveConnectorChildren to drop them during GLB model replacement.
245
+ if (!geometries['CONNECTOR_GATEWAY_SPHERE']) {
246
+ var hasNestedConnectors = data.scene.children.some(function (child) {
247
+ var _child$userData3;
248
+ return ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'component' && Array.isArray(child.children) && child.children.some(function (nestedChild) {
249
+ var _nestedChild$userData;
250
+ return ((_nestedChild$userData = nestedChild.userData) === null || _nestedChild$userData === void 0 ? void 0 : _nestedChild$userData.objectType) === 'connector';
251
+ });
252
+ });
253
+ if (hasNestedConnectors) {
254
+ geometries['CONNECTOR_GATEWAY_SPHERE'] = new THREE.SphereGeometry(0.1, 16, 16);
255
+ console.log('🔮 Created shared sphere geometry for nested inline connectors (radius: 0.1)');
256
+ }
257
+ }
240
258
  return geometries;
241
259
  }
242
260
 
@@ -622,12 +640,12 @@ var SceneOperationsManager = /*#__PURE__*/function () {
622
640
  _step;
623
641
  try {
624
642
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
625
- var _object$userData, _child$userData3;
643
+ var _object$userData, _child$userData4;
626
644
  var child = _step.value;
627
645
  // Enhanced matching logic with hardcoded UUID priority
628
646
 
629
647
  // Strategy 1: Direct hardcoded UUID match (HIGHEST PRIORITY)
630
- if (child.uuid === object.uuid || child.uuid === ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.originalUuid) || object.uuid === ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid)) {
648
+ if (child.uuid === object.uuid || child.uuid === ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.originalUuid) || object.uuid === ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid)) {
631
649
  return child;
632
650
  }
633
651
 
@@ -772,6 +790,9 @@ var SceneOperationsManager = /*#__PURE__*/function () {
772
790
  // Phase 6: Load behaviors (after GLB models are present so output objects can be resolved)
773
791
  this._processBehaviors(data);
774
792
  console.log('✅ Scene loaded successfully');
793
+
794
+ // Notify UI components (e.g. SceneHierarchy) that the scene is fully loaded
795
+ this.sceneViewer.emit('scene-loaded');
775
796
  _context4.n = 7;
776
797
  break;
777
798
  case 6:
@@ -883,10 +904,10 @@ var SceneOperationsManager = /*#__PURE__*/function () {
883
904
  var componentsProcessed = 0;
884
905
  var connectorsInjected = 0;
885
906
  data.scene.children.forEach(function (child) {
886
- var _child$userData4, _child$userData5, _child$userData6;
887
- var childType = ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.objectType) || ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType);
907
+ var _child$userData5, _child$userData6, _child$userData7;
908
+ var childType = ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType) || ((_child$userData6 = child.userData) === null || _child$userData6 === void 0 ? void 0 : _child$userData6.objectType);
888
909
  // Only process components with libraryId
889
- if (childType === 'component' && (_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.libraryId) {
910
+ if (childType === 'component' && (_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.libraryId) {
890
911
  var libraryId = child.userData.libraryId;
891
912
  var dictEntry = componentDictionary[libraryId];
892
913
 
@@ -1043,17 +1064,17 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1043
1064
  geometries = this.createSceneGeometries(data, componentDictionary); // Create basic objects and track GLB replacements
1044
1065
  libraryObjectsToReplace = [];
1045
1066
  data.scene.children.forEach(function (child, index) {
1046
- var _child$userData7, _child$userData8;
1067
+ var _child$userData8, _child$userData9;
1047
1068
  var createdObject = _this4.createSceneObject(child, geometries, materials, componentDictionary);
1048
1069
  _this4.sceneViewer.scene.add(createdObject);
1049
1070
 
1050
1071
  // Track objects that need GLB model replacement
1051
- if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.libraryId && componentDictionary[(_child$userData8 = child.userData) === null || _child$userData8 === void 0 ? void 0 : _child$userData8.libraryId]) {
1052
- var _child$userData9;
1072
+ if ((_child$userData8 = child.userData) !== null && _child$userData8 !== void 0 && _child$userData8.libraryId && componentDictionary[(_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.libraryId]) {
1073
+ var _child$userData0;
1053
1074
  libraryObjectsToReplace.push({
1054
1075
  basicObject: createdObject,
1055
1076
  jsonData: child,
1056
- componentData: componentDictionary[(_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.libraryId]
1077
+ componentData: componentDictionary[(_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.libraryId]
1057
1078
  });
1058
1079
  }
1059
1080
  });
@@ -1192,8 +1213,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1192
1213
  var instanceBehaviors = [];
1193
1214
  if (Array.isArray(data === null || data === void 0 || (_data$scene3 = data.scene) === null || _data$scene3 === void 0 ? void 0 : _data$scene3.children)) {
1194
1215
  data.scene.children.forEach(function (child) {
1195
- var _child$userData0, _compData$defaultBeha;
1196
- var libraryId = (_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.libraryId;
1216
+ var _child$userData1, _compData$defaultBeha;
1217
+ var libraryId = (_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.libraryId;
1197
1218
  if (!libraryId) return;
1198
1219
  var instanceUuid = child.uuid;
1199
1220
  // Skip instances whose defaults were already resolved by Step A
@@ -1584,8 +1605,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1584
1605
  // Process children (connectors, etc.) if they exist
1585
1606
  if (componentModel.children && componentModel.children.length > 0) {
1586
1607
  componentModel.children.forEach(function (child) {
1587
- var _child$userData1, _child$userData10;
1588
- var childType = ((_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.objectType) || ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType);
1608
+ var _child$userData10, _child$userData11;
1609
+ var childType = ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType) || ((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType);
1589
1610
  if (childType === 'connector') {
1590
1611
  var _child$geometry;
1591
1612
  var childBoundingBox = new THREE.Box3().setFromObject(child);
@@ -1670,8 +1691,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1670
1691
  if (segment.children && segment.children.length > 0) {
1671
1692
  var childrenToRemove = _toConsumableArray(segment.children);
1672
1693
  childrenToRemove.forEach(function (child) {
1673
- var _child$userData11;
1674
- if ((_child$userData11 = child.userData) !== null && _child$userData11 !== void 0 && _child$userData11.isPipeElbow) {
1694
+ var _child$userData12;
1695
+ if ((_child$userData12 = child.userData) !== null && _child$userData12 !== void 0 && _child$userData12.isPipeElbow) {
1675
1696
  console.log("\uD83D\uDDD1\uFE0F Removing elbow child from segment before manualization: ".concat(child.uuid));
1676
1697
  segment.remove(child);
1677
1698
  if (child.geometry) child.geometry.dispose();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2112-lab/central-plant",
3
- "version": "0.1.93",
3
+ "version": "0.1.95",
4
4
  "description": "Utility modules for the Central Plant Application",
5
5
  "main": "dist/bundle/index.js",
6
6
  "module": "dist/esm/src/index.js",