@2112-lab/central-plant 0.3.47 → 0.3.49

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.
@@ -37,7 +37,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
37
37
  * Initialize the CentralPlant manager
38
38
  *
39
39
  * @constructor
40
- * @version 0.3.47
40
+ * @version 0.3.49
41
41
  * @updated 2025-10-22
42
42
  *
43
43
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -367,7 +367,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
367
367
  }, {
368
368
  key: "translate",
369
369
  value: function translate(componentId, axis, value) {
370
- return this.internals.translateComponent(componentId, axis, value);
370
+ var skipPathUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
371
+ return this.internals.translateComponent(componentId, axis, value, skipPathUpdate);
371
372
  }
372
373
 
373
374
  /**
@@ -1065,18 +1066,19 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1065
1066
  return [];
1066
1067
  }
1067
1068
 
1068
- // Traverse through all components in the scene data
1069
- sceneData.scene.children.forEach(function (component) {
1070
- // Each component may have connector children
1071
- if (component.children && Array.isArray(component.children)) {
1072
- component.children.forEach(function (child) {
1073
- // Check if this child is a connector
1074
- if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
1075
- allConnectorIds.push(child.uuid);
1076
- }
1077
- });
1078
- }
1079
- });
1069
+ // Recursive search for connector IDs
1070
+ var _findConnectorIds = function findConnectorIds(nodes) {
1071
+ if (!nodes || !Array.isArray(nodes)) return;
1072
+ nodes.forEach(function (node) {
1073
+ if (node.userData && node.userData.objectType === 'connector' && node.uuid) {
1074
+ allConnectorIds.push(node.uuid);
1075
+ }
1076
+ if (node.children && Array.isArray(node.children)) {
1077
+ _findConnectorIds(node.children);
1078
+ }
1079
+ });
1080
+ };
1081
+ _findConnectorIds(sceneData.scene.children);
1080
1082
 
1081
1083
  // Get existing connections
1082
1084
  var existingConnections = this.getConnections();
@@ -1106,28 +1108,28 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1106
1108
  * const infos = centralPlant.getAvailableConnectionsInfo()
1107
1109
  * // [{ id: 'PUMP-1-CONNECTOR-1', flow: 'out' }, ...]
1108
1110
  */
1111
+ /**
1112
+ * Get all connectors in the scene that are currently available (not used in a connection).
1113
+ * Searches the active Three.js scene directly for the most accurate results.
1114
+ * @returns {Array<{id: string, flow: string}>} Array of connector info objects
1115
+ * @since 0.1.72 (Updated to search Three.js scene directly)
1116
+ */
1109
1117
  }, {
1110
1118
  key: "getAvailableConnectionsInfo",
1111
1119
  value: function getAvailableConnectionsInfo() {
1112
- if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
1113
- console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or current scene data not available');
1114
- return [];
1115
- }
1116
- var sceneData = this.sceneViewer.currentSceneData;
1117
- if (!sceneData.scene || !sceneData.scene.children) {
1118
- console.warn('⚠️ getAvailableConnectionsInfo(): Invalid scene data structure');
1120
+ if (!this.sceneViewer || !this.sceneViewer.scene) {
1121
+ console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or scene not available');
1119
1122
  return [];
1120
1123
  }
1121
1124
  var allConnectorInfos = [];
1122
- sceneData.scene.children.forEach(function (component) {
1123
- if (component.children && Array.isArray(component.children)) {
1124
- component.children.forEach(function (child) {
1125
- if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
1126
- allConnectorInfos.push({
1127
- id: child.uuid,
1128
- flow: child.userData.flow || 'bi'
1129
- });
1130
- }
1125
+
1126
+ // Search the Three.js scene directly for connectors
1127
+ // This is more reliable than searching currentSceneData which might be stale
1128
+ this.sceneViewer.scene.traverse(function (node) {
1129
+ if (node.userData && node.userData.objectType === 'connector' && node.uuid) {
1130
+ allConnectorInfos.push({
1131
+ id: node.uuid,
1132
+ flow: node.userData.flow || 'bi'
1131
1133
  });
1132
1134
  }
1133
1135
  });
@@ -1149,30 +1151,29 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1149
1151
  * const result = centralPlant.validateConnections()
1150
1152
  * result.invalid.forEach(({ connection, reason }) => console.warn(reason, connection))
1151
1153
  */
1154
+ /**
1155
+ * Validate all connections in the current scene for flow direction compatibility.
1156
+ * Searches the active Three.js scene for connector flow markers.
1157
+ * @returns {{ valid: Array<Object>, invalid: Array<{connection: Object, reason: string}> }}
1158
+ * @since 0.1.72 (Updated to search Three.js scene directly)
1159
+ */
1152
1160
  }, {
1153
1161
  key: "validateConnections",
1154
1162
  value: function validateConnections() {
1155
- if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
1156
- console.warn('⚠️ validateConnections(): Scene viewer or current scene data not available');
1163
+ if (!this.sceneViewer || !this.sceneViewer.scene) {
1164
+ console.warn('⚠️ validateConnections(): Scene viewer or scene not available');
1157
1165
  return {
1158
1166
  valid: [],
1159
1167
  invalid: []
1160
1168
  };
1161
1169
  }
1162
1170
  var connections = this.getConnections();
1163
- var sceneData = this.sceneViewer.currentSceneData;
1164
1171
 
1165
- // Build lookup map: connectorId → flow
1172
+ // Build lookup map: connectorId → flow from the Three.js scene
1166
1173
  var flowMap = {};
1167
- var scene = sceneData.scene || {};
1168
- var children = scene.children || [];
1169
- children.forEach(function (component) {
1170
- if (component.children && Array.isArray(component.children)) {
1171
- component.children.forEach(function (child) {
1172
- if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
1173
- flowMap[child.uuid] = child.userData.flow || 'bi';
1174
- }
1175
- });
1174
+ this.sceneViewer.scene.traverse(function (node) {
1175
+ if (node.userData && node.userData.objectType === 'connector' && node.uuid) {
1176
+ flowMap[node.uuid] = node.userData.flow || 'bi';
1176
1177
  }
1177
1178
  });
1178
1179
  var valid = [];
@@ -474,17 +474,19 @@ var CentralPlantInternals = /*#__PURE__*/function () {
474
474
  * @param {string} componentId - The UUID of the component to translate
475
475
  * @param {string} axis - The axis to translate on ('x', 'y', or 'z')
476
476
  * @param {number} value - The value to translate by
477
+ * @param {boolean} [skipPathUpdate=false] - Whether to skip triggering pathfinding
477
478
  * @returns {boolean} True if translation was successful, false otherwise
478
479
  */
479
480
  }, {
480
481
  key: "translateComponent",
481
482
  value: function translateComponent(componentId, axis, value) {
482
483
  var _this$centralPlant$ma;
484
+ var skipPathUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
483
485
  if (!((_this$centralPlant$ma = this.centralPlant.managers) !== null && _this$centralPlant$ma !== void 0 && _this$centralPlant$ma.transformOperationsManager)) {
484
486
  console.error('❌ translateComponent(): TransformOperationsManager not available');
485
487
  return false;
486
488
  }
487
- return this.centralPlant.managers.transformOperationsManager.translateComponent(componentId, axis, value);
489
+ return this.centralPlant.managers.transformOperationsManager.translateComponent(componentId, axis, value, skipPathUpdate);
488
490
  }
489
491
 
490
492
  /**
@@ -576,7 +578,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
576
578
  } else if (objectType === 'gateway') {
577
579
  success = this.translateGateway(objectId, axis, value);
578
580
  } else if (objectType === 'component') {
579
- success = this.translateComponent(objectId, axis, value);
581
+ success = this.translateComponent(objectId, axis, value, skipPathUpdate);
580
582
  } else {
581
583
  result.errors.push("Unknown object type: ".concat(objectType, " (").concat(objectId, ")"));
582
584
  console.warn("\u26A0\uFE0F Unknown object type: ".concat(objectType, " for ").concat(objectId));
@@ -102,7 +102,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
102
102
  this.centralPlant.attachToComponent();
103
103
 
104
104
  // Sync our managers tracking object after attachment
105
- managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'pathFlowManager', 'ioBehaviorManager', 'ioOutlineManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
105
+ managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'transformOperationsManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'pathFlowManager', 'ioBehaviorManager', 'ioOutlineManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
106
106
  managerKeys.forEach(function (key) {
107
107
  if (_this2[key]) {
108
108
  _this2.managers[key] = _this2[key];
@@ -24,7 +24,7 @@ var ComponentManager = /*#__PURE__*/function () {
24
24
  key: "addComponentToScene",
25
25
  value: (function () {
26
26
  var _addComponentToScene = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee(componentData) {
27
- var _gltfScene$userData, uuid, componentDictionary, libraryComponent, position, gltfScene, componentMesh, event, _t, _t2;
27
+ var _gltfScene$userData, uuid, componentDictionary, libraryComponent, position, gltfScene, componentMesh, connectorIndex, event, _t, _t2;
28
28
  return _rollupPluginBabelHelpers.regenerator().w(function (_context) {
29
29
  while (1) switch (_context.n) {
30
30
  case 0:
@@ -128,6 +128,7 @@ var ComponentManager = /*#__PURE__*/function () {
128
128
  }
129
129
 
130
130
  // Enable shadows for all meshes in the component
131
+ connectorIndex = 0;
131
132
  componentMesh.traverse(function (child) {
132
133
  if (child.isMesh) {
133
134
  child.castShadow = true;
@@ -137,12 +138,19 @@ var ComponentManager = /*#__PURE__*/function () {
137
138
  }
138
139
 
139
140
  // Set connector properties for connectors within the component
140
- if (child.name && child.name.toLowerCase().includes('connector')) {
141
+ if (child.name && child.name.toLowerCase().includes('connector') || child.userData && child.userData.objectType === 'connector') {
142
+ connectorIndex++;
141
143
  if (!child.userData) {
142
144
  child.userData = {};
143
145
  }
144
146
  child.userData.objectType = 'connector';
145
- console.log("\uD83D\uDD27 Set objectType='connector' for: ".concat(child.name));
147
+
148
+ // Assign a predictable, stable UUID to the connector
149
+ // This ensures connections made in the sandbox survive export/import
150
+ var connectorUuid = "".concat(uuid, "-CONNECTOR-").concat(connectorIndex);
151
+ child.uuid = connectorUuid;
152
+ child.userData.originalUuid = connectorUuid;
153
+ console.log("\uD83D\uDD27 Set predictable connector UUID: ".concat(connectorUuid, " for: ").concat(child.name));
146
154
  }
147
155
  }
148
156
  });
@@ -40,12 +40,14 @@ var TransformOperationsManager = /*#__PURE__*/function () {
40
40
  * @param {string} componentId - The UUID of the component to translate
41
41
  * @param {string} axis - The axis to translate on ('x', 'y', or 'z')
42
42
  * @param {number} value - The value to translate by
43
+ * @param {boolean} [skipPathUpdate=false] - Whether to skip triggering pathfinding after translation
43
44
  * @returns {boolean} True if translation was successful, false otherwise
44
45
  */
45
46
  return _rollupPluginBabelHelpers.createClass(TransformOperationsManager, [{
46
47
  key: "translateComponent",
47
48
  value: function translateComponent(componentId, axis, value) {
48
49
  var _this$sceneViewer$man, _this$sceneViewer;
50
+ var skipPathUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
49
51
  // Store transform parameters using the OperationHistoryManager
50
52
  if ((_this$sceneViewer$man = this.sceneViewer.managers) !== null && _this$sceneViewer$man !== void 0 && _this$sceneViewer$man.operationHistoryManager) {
51
53
  this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateComponent', {
@@ -113,7 +115,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
113
115
  }
114
116
 
115
117
  // Auto-update paths if enabled (matches behavior of translateSegment and translateGateway)
116
- if (this.sceneViewer.shouldUpdatePaths) {
118
+ if (!skipPathUpdate && this.sceneViewer.shouldUpdatePaths) {
117
119
  try {
118
120
  if (this.sceneViewer && typeof this.sceneViewer.updatePaths === 'function') {
119
121
  this.sceneViewer.updatePaths();
@@ -124,6 +126,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
124
126
  } catch (error) {
125
127
  console.error('❌ Error auto-updating paths:', error);
126
128
  }
129
+ } else if (skipPathUpdate) {
130
+ console.log('ℹ️ skipPathUpdate is true: skipping automatic path update');
127
131
  }
128
132
 
129
133
  // Emit transform event if available
@@ -1942,11 +1946,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
1942
1946
  sceneDataComponent.children.forEach(function (child) {
1943
1947
  var _child$userData21;
1944
1948
  if (((_child$userData21 = child.userData) === null || _child$userData21 === void 0 ? void 0 : _child$userData21.objectType) === 'connector') {
1945
- // Find the actual connector object in the scene
1946
- var connectorObj = component.children.find(function (c) {
1947
- var _c$userData;
1948
- return c.uuid === child.uuid || ((_c$userData = c.userData) === null || _c$userData === void 0 ? void 0 : _c$userData.originalUuid) === child.uuid;
1949
- });
1949
+ // Find the actual connector object in the scene (recursive search for nested connectors)
1950
+ var connectorObj = component.getObjectByProperty('uuid', child.uuid) || component.getObjectByProperty('name', child.uuid);
1950
1951
  if (connectorObj) {
1951
1952
  // Get world position of connector
1952
1953
  var worldPos = new THREE__namespace.Vector3();
@@ -2005,11 +2006,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
2005
2006
  sceneDataComponent.children.forEach(function (child) {
2006
2007
  var _child$userData22;
2007
2008
  if (((_child$userData22 = child.userData) === null || _child$userData22 === void 0 ? void 0 : _child$userData22.objectType) === 'connector') {
2008
- // Find the actual connector object in the scene
2009
- var connectorObj = component.children.find(function (c) {
2010
- var _c$userData2;
2011
- return c.uuid === child.uuid || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === child.uuid;
2012
- });
2009
+ // Find the actual connector object in the scene (recursive search for nested connectors)
2010
+ var connectorObj = component.getObjectByProperty('uuid', child.uuid) || component.getObjectByProperty('name', child.uuid);
2013
2011
  if (connectorObj) {
2014
2012
  var _connectorObj$userDat;
2015
2013
  // Get world position of connector
@@ -64,7 +64,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
64
64
  this.forceInvisible = false;
65
65
 
66
66
  // SceneViewer reference for event listening
67
- this.sceneViewer = null;
67
+ this.sceneViewer = centralPlant ? centralPlant.sceneViewer : null;
68
68
  this._objectTransformedListener = null;
69
69
 
70
70
  // Event handlers storage
@@ -266,23 +266,28 @@ var TransformControlsManager = /*#__PURE__*/function () {
266
266
  _this2.transformState.isTransforming = true;
267
267
 
268
268
  // Store initial transforms for all selected objects
269
- if (_this2.selectedObjects.length > 0 && _this2.multiSelectionGroup) {
269
+ if (_this2.selectedObjects.length > 0) {
270
270
  _this2.selectedObjects.forEach(function (obj) {
271
- obj.userData._multiSelectOriginalPosition = obj.position.clone();
272
- obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
273
- obj.userData._multiSelectOriginalScale = obj.scale.clone();
274
- });
275
-
276
- // Snapshot group position and helper geometry vertices so we can do
277
- // cheap per-frame bbox translation without re-traversing the mesh hierarchy.
278
- _this2._dragStartGroupPosition = _this2.multiSelectionGroup.position.clone();
279
- _this2.boundingBoxHelpers.forEach(function (helper) {
280
- var _helper$geometry;
281
- 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;
282
- if (posAttr) {
283
- helper.userData._dragStartPositions = new Float32Array(posAttr.array);
271
+ obj.userData._dragStartRotation = obj.rotation.clone();
272
+ obj.userData._dragStartPosition = obj.position.clone();
273
+ if (_this2.multiSelectionGroup) {
274
+ obj.userData._multiSelectOriginalPosition = obj.position.clone();
275
+ obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
276
+ obj.userData._multiSelectOriginalScale = obj.scale.clone();
284
277
  }
285
278
  });
279
+ if (_this2.multiSelectionGroup) {
280
+ // Snapshot group position and helper geometry vertices so we can do
281
+ // cheap per-frame bbox translation without re-traversing the mesh hierarchy.
282
+ _this2._dragStartGroupPosition = _this2.multiSelectionGroup.position.clone();
283
+ _this2.boundingBoxHelpers.forEach(function (helper) {
284
+ var _helper$geometry;
285
+ 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;
286
+ if (posAttr) {
287
+ helper.userData._dragStartPositions = new Float32Array(posAttr.array);
288
+ }
289
+ });
290
+ }
286
291
  }
287
292
 
288
293
  // Disable orbit controls during transformation
@@ -299,7 +304,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
299
304
 
300
305
  // Transform end event
301
306
  this.eventHandlers.transformEnd = /*#__PURE__*/_rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee() {
302
- var hasComponents, _this2$selectedObject, sceneCompleteEvent;
307
+ var isTranslate, isRotate, hasComponents, _this2$selectedObject, sceneCompleteEvent;
303
308
  return _rollupPluginBabelHelpers.regenerator().w(function (_context) {
304
309
  while (1) switch (_context.n) {
305
310
  case 0:
@@ -321,29 +326,52 @@ var TransformControlsManager = /*#__PURE__*/function () {
321
326
  console.error('❌ Error in applyMultiSelectionTransform:', error);
322
327
  });
323
328
  case 1:
324
- // applyMultiSelectionTransform() already calls updatePaths() once at the end
325
- // so we skip the additional updatePaths() call below
326
- console.log('✅ Multi-selection transform complete (updatePaths already called)');
329
+ console.log('✅ Multi-selection transform complete');
327
330
  _context.n = 3;
328
331
  break;
329
332
  case 2:
330
- if (_this2.currentMode === 'translate' && _this2.sceneViewer && typeof _this2.sceneViewer.updatePaths === 'function') {
331
- // Update paths after translation is complete
332
- // Only if we translated components (not segments/gateways - they handle paths internally)
333
- // This branch only executes when NOT in multi-selection mode
334
- hasComponents = _this2.selectedObjects.some(function (obj) {
335
- return !objectTypes.isSegment(obj) && !objectTypes.isGateway(obj);
336
- });
337
- if (hasComponents) {
338
- console.log('🔄 Updating paths after component translation...');
339
- try {
340
- _this2.sceneViewer.updatePaths();
341
- console.log('✅ Paths updated successfully after translation');
342
- } catch (error) {
343
- console.error('❌ Error updating paths after translation:', error);
333
+ if (_this2.sceneViewer && typeof _this2.sceneViewer.updatePaths === 'function') {
334
+ // Update paths after transformation is complete (translation or rotation)
335
+ isTranslate = _this2.currentMode === 'translate';
336
+ isRotate = _this2.currentMode === 'rotate';
337
+ if (isTranslate || isRotate) {
338
+ hasComponents = _this2.selectedObjects.some(function (obj) {
339
+ return !objectTypes.isSegment(obj) && !objectTypes.isGateway(obj);
340
+ });
341
+ if (hasComponents) {
342
+ console.log("\uD83D\uDD04 Updating paths after component ".concat(_this2.currentMode, "..."));
343
+ try {
344
+ // Ensure scene data is synced before updating paths
345
+ _this2.selectedObjects.forEach(function (obj) {
346
+ var _obj$userData;
347
+ if (((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType) === 'component') {
348
+ var _this2$sceneViewer$ma;
349
+ var transformMgr = (_this2$sceneViewer$ma = _this2.sceneViewer.managers) === null || _this2$sceneViewer$ma === void 0 ? void 0 : _this2$sceneViewer$ma.transformOperationsManager;
350
+ if (transformMgr) {
351
+ if (isTranslate) {
352
+ transformMgr.updateComponentPositionInSceneData(obj);
353
+ }
354
+ if (isRotate) {
355
+ transformMgr.updateComponentRotationInSceneData(obj);
356
+
357
+ // Calculate rotation delta for direction vector patching
358
+ var startRot = obj.userData._dragStartRotation || obj.rotation;
359
+ var deltaRad = obj.rotation.z - startRot.z;
360
+ var deltaDeg = Math.round(THREE__namespace.MathUtils.radToDeg(deltaRad) / 90) * 90;
361
+ if (deltaDeg !== 0) {
362
+ console.log("\uD83E\uDDED Patching connector directions by ".concat(deltaDeg, " degrees after gizmo rotation"));
363
+ transformMgr.updateConnectorDirections(obj, 'z', deltaDeg);
364
+ }
365
+ }
366
+ }
367
+ }
368
+ });
369
+ _this2.sceneViewer.updatePaths();
370
+ console.log("\u2705 Paths updated successfully after ".concat(_this2.currentMode));
371
+ } catch (error) {
372
+ console.error("\u274C Error updating paths after ".concat(_this2.currentMode, ":"), error);
373
+ }
344
374
  }
345
- } else {
346
- console.log('ℹ️ Skipping updatePaths - segments/gateways handle their own path updates');
347
375
  }
348
376
  }
349
377
  case 3:
@@ -474,8 +502,8 @@ var TransformControlsManager = /*#__PURE__*/function () {
474
502
  var hit = _step.value;
475
503
  var _obj = hit.object;
476
504
  while (_obj) {
477
- var _obj$userData2;
478
- if (((_obj$userData2 = _obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.objectType) === 'io-device') {
505
+ var _obj$userData3;
506
+ if (((_obj$userData3 = _obj.userData) === null || _obj$userData3 === void 0 ? void 0 : _obj$userData3.objectType) === 'io-device') {
479
507
  ioDeviceObject = _obj;
480
508
  break;
481
509
  }
@@ -498,8 +526,8 @@ var TransformControlsManager = /*#__PURE__*/function () {
498
526
  var parentUuid = null;
499
527
  var obj = ioDeviceObject.parent;
500
528
  while (obj) {
501
- var _obj$userData;
502
- if (((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType) === 'component') {
529
+ var _obj$userData2;
530
+ if (((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.objectType) === 'component') {
503
531
  parentUuid = obj.userData.originalUuid || obj.uuid;
504
532
  break;
505
533
  }
@@ -576,8 +604,8 @@ var TransformControlsManager = /*#__PURE__*/function () {
576
604
  var hit = _step2.value;
577
605
  var obj = hit.object;
578
606
  while (obj) {
579
- var _obj$userData3;
580
- if (((_obj$userData3 = obj.userData) === null || _obj$userData3 === void 0 ? void 0 : _obj$userData3.objectType) === 'io-device') {
607
+ var _obj$userData4;
608
+ if (((_obj$userData4 = obj.userData) === null || _obj$userData4 === void 0 ? void 0 : _obj$userData4.objectType) === 'io-device') {
581
609
  _this4.callbacks.onIODeviceClick(obj);
582
610
  return;
583
611
  }
@@ -2238,8 +2266,8 @@ var TransformControlsManager = /*#__PURE__*/function () {
2238
2266
  key: "_updateSegmentReference",
2239
2267
  value: function _updateSegmentReference(oldSegment, newSegment, index) {
2240
2268
  var selectedIndex = this.selectedObjects.findIndex(function (obj) {
2241
- var _obj$userData4;
2242
- return obj.uuid === oldSegment.uuid || ((_obj$userData4 = obj.userData) === null || _obj$userData4 === void 0 ? void 0 : _obj$userData4.originalUuid) === oldSegment.uuid;
2269
+ var _obj$userData5;
2270
+ return obj.uuid === oldSegment.uuid || ((_obj$userData5 = obj.userData) === null || _obj$userData5 === void 0 ? void 0 : _obj$userData5.originalUuid) === oldSegment.uuid;
2243
2271
  });
2244
2272
  if (selectedIndex !== -1 && newSegment) {
2245
2273
  // Clear bounding box cache
@@ -2347,7 +2375,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
2347
2375
  componentId = component.uuid || ((_component$userData = component.userData) === null || _component$userData === void 0 ? void 0 : _component$userData.originalUuid);
2348
2376
  _context6.n = 3;
2349
2377
  return this._translateObjectOnAxes(componentId, deltaX, deltaY, deltaZ, threshold, throttleDelay, AXIS_THROTTLE, function (id, axis, delta) {
2350
- return _this0.centralPlant.translate(id, axis, delta);
2378
+ return _this0.centralPlant.translate(id, axis, delta, true);
2351
2379
  });
2352
2380
  case 3:
2353
2381
  console.log("\uD83D\uDD27 Component ".concat(component.name, " translated (").concat(i + 1, "/").concat(components.length, ")"));
@@ -2446,6 +2474,17 @@ var TransformControlsManager = /*#__PURE__*/function () {
2446
2474
  if (this.selectedObjects.length > 0) {
2447
2475
  this.updateMultiSelection();
2448
2476
  }
2477
+
2478
+ // Trigger pathfinding update once after all objects in the batch are translated
2479
+ if (this.sceneViewer && typeof this.sceneViewer.updatePaths === 'function') {
2480
+ var hasComponentsOrSegments = this.selectedObjects.some(function (obj) {
2481
+ return !objectTypes.isGateway(obj);
2482
+ });
2483
+ if (hasComponentsOrSegments) {
2484
+ console.log('🔄 Triggering batched pathfinding update after multi-object translation...');
2485
+ this.sceneViewer.updatePaths();
2486
+ }
2487
+ }
2449
2488
  console.log("\u2705 Multi-selection transform applied");
2450
2489
  }
2451
2490