@2112-lab/central-plant 0.1.50 → 0.1.52

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.
@@ -3619,58 +3619,74 @@ var TransformControlsManager = /*#__PURE__*/function () {
3619
3619
  };
3620
3620
 
3621
3621
  // Transform end event
3622
- this.eventHandlers.transformEnd = function () {
3623
- _this2.transformState.isTransforming = false;
3624
-
3625
- // Re-enable orbit controls
3626
- if (_this2.orbitControls) {
3627
- _this2.orbitControls.enabled = true;
3628
- }
3622
+ this.eventHandlers.transformEnd = /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
3623
+ var hasComponents, _this2$selectedObject, sceneCompleteEvent;
3624
+ return _regenerator().w(function (_context) {
3625
+ while (1) switch (_context.n) {
3626
+ case 0:
3627
+ _this2.transformState.isTransforming = false;
3629
3628
 
3630
- // Apply multi-selection transforms (works for single or multiple objects)
3631
- // This is async but we don't await it to avoid blocking the event handler
3632
- if (_this2.selectedObjects.length > 0 && _this2.multiSelectionGroup) {
3633
- _this2.applyMultiSelectionTransform().catch(function (error) {
3634
- console.error('❌ Error in applyMultiSelectionTransform:', error);
3635
- });
3636
- }
3629
+ // Re-enable orbit controls
3630
+ if (_this2.orbitControls) {
3631
+ _this2.orbitControls.enabled = true;
3632
+ }
3637
3633
 
3638
- // Update paths after translation is complete
3639
- // Only if we translated components (not segments/gateways - they handle paths internally)
3640
- if (_this2.currentMode === 'translate' && _this2.sceneViewer && typeof _this2.sceneViewer.updatePaths === 'function') {
3641
- // Check if any of the selected objects are components (not segments or gateways)
3642
- var hasComponents = _this2.selectedObjects.some(function (obj) {
3643
- return !isSegment(obj) && !isGateway(obj);
3644
- });
3645
- if (hasComponents) {
3646
- console.log('🔄 Updating paths after component translation...');
3647
- try {
3648
- _this2.sceneViewer.updatePaths();
3649
- console.log('✅ Paths updated successfully after translation');
3650
- } catch (error) {
3651
- console.error('❌ Error updating paths after translation:', error);
3652
- }
3653
- } else {
3654
- console.log('â„šī¸ Skipping updatePaths - segments/gateways handle their own path updates');
3634
+ // Apply multi-selection transforms (works for single or multiple objects)
3635
+ // IMPORTANT: We await this to prevent race conditions with updatePaths()
3636
+ if (!(_this2.selectedObjects.length > 0 && _this2.multiSelectionGroup)) {
3637
+ _context.n = 2;
3638
+ break;
3639
+ }
3640
+ _context.n = 1;
3641
+ return _this2.applyMultiSelectionTransform().catch(function (error) {
3642
+ console.error('❌ Error in applyMultiSelectionTransform:', error);
3643
+ });
3644
+ case 1:
3645
+ // applyMultiSelectionTransform() already calls updatePaths() once at the end
3646
+ // so we skip the additional updatePaths() call below
3647
+ console.log('✅ Multi-selection transform complete (updatePaths already called)');
3648
+ _context.n = 3;
3649
+ break;
3650
+ case 2:
3651
+ if (_this2.currentMode === 'translate' && _this2.sceneViewer && typeof _this2.sceneViewer.updatePaths === 'function') {
3652
+ // Update paths after translation is complete
3653
+ // Only if we translated components (not segments/gateways - they handle paths internally)
3654
+ // This branch only executes when NOT in multi-selection mode
3655
+ hasComponents = _this2.selectedObjects.some(function (obj) {
3656
+ return !isSegment(obj) && !isGateway(obj);
3657
+ });
3658
+ if (hasComponents) {
3659
+ console.log('🔄 Updating paths after component translation...');
3660
+ try {
3661
+ _this2.sceneViewer.updatePaths();
3662
+ console.log('✅ Paths updated successfully after translation');
3663
+ } catch (error) {
3664
+ console.error('❌ Error updating paths after translation:', error);
3665
+ }
3666
+ } else {
3667
+ console.log('â„šī¸ Skipping updatePaths - segments/gateways handle their own path updates');
3668
+ }
3669
+ }
3670
+ case 3:
3671
+ // Dispatch custom scene update event after transform completes
3672
+ if (typeof window !== 'undefined') {
3673
+ console.log('📡 Dispatching sceneUpdateComplete event after transform');
3674
+ sceneCompleteEvent = new CustomEvent('sceneUpdateComplete', {
3675
+ detail: {
3676
+ timestamp: Date.now(),
3677
+ transformType: _this2.currentMode,
3678
+ objectName: ((_this2$selectedObject = _this2.selectedObjects[0]) === null || _this2$selectedObject === void 0 ? void 0 : _this2$selectedObject.name) || 'unknown',
3679
+ objectCount: _this2.selectedObjects.length
3680
+ }
3681
+ });
3682
+ window.dispatchEvent(sceneCompleteEvent);
3683
+ }
3684
+ console.log("\u2705 Transform completed: ".concat(_this2.currentMode, " mode"));
3685
+ case 4:
3686
+ return _context.a(2);
3655
3687
  }
3656
- }
3657
-
3658
- // Dispatch custom scene update event after transform completes
3659
- if (typeof window !== 'undefined') {
3660
- var _this2$selectedObject;
3661
- console.log('📡 Dispatching sceneUpdateComplete event after transform');
3662
- var sceneCompleteEvent = new CustomEvent('sceneUpdateComplete', {
3663
- detail: {
3664
- timestamp: Date.now(),
3665
- transformType: _this2.currentMode,
3666
- objectName: ((_this2$selectedObject = _this2.selectedObjects[0]) === null || _this2$selectedObject === void 0 ? void 0 : _this2$selectedObject.name) || 'unknown',
3667
- objectCount: _this2.selectedObjects.length
3668
- }
3669
- });
3670
- window.dispatchEvent(sceneCompleteEvent);
3671
- }
3672
- console.log("\u2705 Transform completed: ".concat(_this2.currentMode, " mode"));
3673
- };
3688
+ }, _callee);
3689
+ }));
3674
3690
  // Transform changing event
3675
3691
  this.eventHandlers.transforming = function () {
3676
3692
  // Apply real-time visual transformation to objects during drag
@@ -3902,7 +3918,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
3902
3918
  }, {
3903
3919
  key: "_isValidSelectableObject",
3904
3920
  value: function _isValidSelectableObject(object) {
3905
- var _object$userData;
3921
+ var _object$userData, _object$userData2;
3906
3922
  // Safety check: ensure object is still valid and in the scene
3907
3923
  if (!object || !object.parent) {
3908
3924
  console.warn('âš ī¸ Selected object is no longer valid or in scene');
@@ -3920,6 +3936,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
3920
3936
  console.warn('âš ī¸ Object is marked as non-selectable (stub segment)');
3921
3937
  return false;
3922
3938
  }
3939
+
3940
+ // Check if object is marked as immutable (computed segments/elbows from pathfinder)
3941
+ if (((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.immutable) === true) {
3942
+ console.warn('âš ī¸ Object is immutable (computed from pathfinder)');
3943
+ return false;
3944
+ }
3923
3945
  return true;
3924
3946
  }
3925
3947
 
@@ -3959,7 +3981,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
3959
3981
  }, {
3960
3982
  key: "isSelectableObject",
3961
3983
  value: function isSelectableObject(object) {
3962
- var _object$userData2, _object$userData3, _object$userData4, _object$userData5, _object$userData6, _object$userData7, _object$userData8;
3984
+ var _object$userData3, _object$userData4, _object$userData5, _object$userData6, _object$userData7, _object$userData8, _object$userData9, _object$userData0;
3963
3985
  // Basic safety checks
3964
3986
  if (!object || !object.isObject3D) {
3965
3987
  return false;
@@ -3971,25 +3993,30 @@ var TransformControlsManager = /*#__PURE__*/function () {
3971
3993
  }
3972
3994
 
3973
3995
  // Skip helpers and special objects
3974
- var isHelper = object.isHelper || ((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.isHelper) || ((_object$userData3 = object.userData) === null || _object$userData3 === void 0 ? void 0 : _object$userData3.isBoundingBox);
3975
- var isBaseGround = (_object$userData4 = object.userData) === null || _object$userData4 === void 0 ? void 0 : _object$userData4.isBaseGround;
3976
- var isBrickWall = (_object$userData5 = object.userData) === null || _object$userData5 === void 0 ? void 0 : _object$userData5.isBrickWall;
3996
+ var isHelper = object.isHelper || ((_object$userData3 = object.userData) === null || _object$userData3 === void 0 ? void 0 : _object$userData3.isHelper) || ((_object$userData4 = object.userData) === null || _object$userData4 === void 0 ? void 0 : _object$userData4.isBoundingBox);
3997
+ var isBaseGround = (_object$userData5 = object.userData) === null || _object$userData5 === void 0 ? void 0 : _object$userData5.isBaseGround;
3998
+ var isBrickWall = (_object$userData6 = object.userData) === null || _object$userData6 === void 0 ? void 0 : _object$userData6.isBrickWall;
3977
3999
  if (isHelper || isBaseGround || isBrickWall || !object.visible) {
3978
4000
  return false;
3979
4001
  }
3980
4002
 
3981
4003
  // Skip segment connectors - they should not be selectable for transformation
3982
- if (((_object$userData6 = object.userData) === null || _object$userData6 === void 0 ? void 0 : _object$userData6.objectType) === 'segment-connector') {
4004
+ if (((_object$userData7 = object.userData) === null || _object$userData7 === void 0 ? void 0 : _object$userData7.objectType) === 'segment-connector') {
3983
4005
  return false;
3984
4006
  }
3985
4007
 
3986
4008
  // Check if object has explicit selectable flag set to false
3987
- if (((_object$userData7 = object.userData) === null || _object$userData7 === void 0 ? void 0 : _object$userData7.selectable) === false) {
4009
+ if (((_object$userData8 = object.userData) === null || _object$userData8 === void 0 ? void 0 : _object$userData8.selectable) === false) {
4010
+ return false;
4011
+ }
4012
+
4013
+ // Check if object is marked as immutable (computed segments/elbows from pathfinder)
4014
+ if (((_object$userData9 = object.userData) === null || _object$userData9 === void 0 ? void 0 : _object$userData9.immutable) === true) {
3988
4015
  return false;
3989
4016
  }
3990
4017
 
3991
4018
  // Allow components, gateways, and segments to be selected
3992
- var objectType = (_object$userData8 = object.userData) === null || _object$userData8 === void 0 ? void 0 : _object$userData8.objectType;
4019
+ var objectType = (_object$userData0 = object.userData) === null || _object$userData0 === void 0 ? void 0 : _object$userData0.objectType;
3993
4020
  return objectType === 'component' || objectType === 'gateway' || isSegment(object);
3994
4021
  }
3995
4022
  /**
@@ -4664,7 +4691,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
4664
4691
 
4665
4692
  // Traverse scene to find selectable objects
4666
4693
  this.scene.traverse(function (object) {
4667
- var _object$userData9, _object$userData0;
4694
+ var _object$userData1, _object$userData10;
4668
4695
  // Skip invalid objects and helpers early
4669
4696
  if (!object || !object.isObject3D) {
4670
4697
  return;
@@ -4676,7 +4703,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
4676
4703
  }
4677
4704
 
4678
4705
  // Skip other helpers and special objects
4679
- if (object.isHelper || (_object$userData9 = object.userData) !== null && _object$userData9 !== void 0 && _object$userData9.isHelper || (_object$userData0 = object.userData) !== null && _object$userData0 !== void 0 && _object$userData0.isBoundingBox) {
4706
+ if (object.isHelper || (_object$userData1 = object.userData) !== null && _object$userData1 !== void 0 && _object$userData1.isHelper || (_object$userData10 = object.userData) !== null && _object$userData10 !== void 0 && _object$userData10.isBoundingBox) {
4680
4707
  return;
4681
4708
  }
4682
4709
  try {
@@ -4848,17 +4875,17 @@ var TransformControlsManager = /*#__PURE__*/function () {
4848
4875
  }, {
4849
4876
  key: "applyMultiSelectionTransform",
4850
4877
  value: (function () {
4851
- var _applyMultiSelectionTransform = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
4878
+ var _applyMultiSelectionTransform = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
4852
4879
  var _this9 = this;
4853
- var groupPosition, originalCentroid, positionDelta, deltaX, deltaY, deltaZ, threshold, _this$sceneViewer, segments, gateways, components, transformOpsManager, THROTTLE_DELAY, SEGMENT_DELAY, _throttleDelay, _loop, i, _THROTTLE_DELAY, _SEGMENT_DELAY, _throttleDelay2, _loop2, _i, GATEWAY_THROTTLE, GATEWAY_DELAY, COMPONENT_THROTTLE, COMPONENT_DELAY, throttleDelay, _i2, _gateway$userData, gateway, gatewayId, _i3, _component$userData, component, componentId;
4854
- return _regenerator().w(function (_context3) {
4855
- while (1) switch (_context3.n) {
4880
+ var groupPosition, originalCentroid, positionDelta, deltaX, deltaY, deltaZ, threshold, _this$sceneViewer, _this$sceneViewer2, _this$sceneViewer3, _this$sceneViewer4, _this$sceneViewer5, segments, gateways, components, transformOpsManager, THROTTLE_DELAY, SEGMENT_DELAY, _throttleDelay, _loop, i, _THROTTLE_DELAY, _SEGMENT_DELAY, _throttleDelay2, _loop2, _i, GATEWAY_THROTTLE, GATEWAY_DELAY, COMPONENT_THROTTLE, COMPONENT_DELAY, throttleDelay, _i2, _gateway$userData, gateway, gatewayId, _i3, _component$userData, component, componentId;
4881
+ return _regenerator().w(function (_context4) {
4882
+ while (1) switch (_context4.n) {
4856
4883
  case 0:
4857
4884
  if (!(!this.multiSelectionGroup || this.selectedObjects.length === 0)) {
4858
- _context3.n = 1;
4885
+ _context4.n = 1;
4859
4886
  break;
4860
4887
  }
4861
- return _context3.a(2);
4888
+ return _context4.a(2);
4862
4889
  case 1:
4863
4890
  console.log("\uD83D\uDD27 Applying multi-selection transform to ".concat(this.selectedObjects.length, " objects"));
4864
4891
 
@@ -4887,7 +4914,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
4887
4914
  // Only process if there's a meaningful translation
4888
4915
  threshold = 0.001;
4889
4916
  if (!(this.currentMode === 'translate' && positionDelta.length() > threshold)) {
4890
- _context3.n = 21;
4917
+ _context4.n = 21;
4891
4918
  break;
4892
4919
  }
4893
4920
  // FIRST: Reset all objects to their original positions
@@ -4910,14 +4937,23 @@ var TransformControlsManager = /*#__PURE__*/function () {
4910
4937
  });
4911
4938
  components = this.selectedObjects.filter(function (obj) {
4912
4939
  return !isSegment(obj) && !isGateway(obj);
4913
- }); // BATCH SEGMENT TRANSLATIONS: Call translateSegment with skipPathUpdate=true
4940
+ }); // Debug: Check availability of managers
4941
+ console.log('🔍 Debug - sceneViewer available:', !!this.sceneViewer);
4942
+ console.log('🔍 Debug - sceneViewer.managers available:', !!((_this$sceneViewer = this.sceneViewer) !== null && _this$sceneViewer !== void 0 && _this$sceneViewer.managers));
4943
+ console.log('🔍 Debug - Available managers:', (_this$sceneViewer2 = this.sceneViewer) !== null && _this$sceneViewer2 !== void 0 && _this$sceneViewer2.managers ? Object.keys(this.sceneViewer.managers) : 'none');
4944
+ console.log('🔍 Debug - transformOperationsManager (direct):', !!((_this$sceneViewer3 = this.sceneViewer) !== null && _this$sceneViewer3 !== void 0 && _this$sceneViewer3.transformOperationsManager));
4945
+ console.log('🔍 Debug - transformOperations (managers.transformOperations):', !!((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && (_this$sceneViewer4 = _this$sceneViewer4.managers) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.transformOperations));
4946
+ console.log('🔍 Debug - Segments to translate:', segments.length);
4947
+
4948
+ // BATCH SEGMENT TRANSLATIONS: Call translateSegment with skipPathUpdate=true
4914
4949
  // Process segments SEQUENTIALLY with throttling for maximum stability
4915
- if (!(segments.length > 0 && (_this$sceneViewer = this.sceneViewer) !== null && _this$sceneViewer !== void 0 && (_this$sceneViewer = _this$sceneViewer.managers) !== null && _this$sceneViewer !== void 0 && _this$sceneViewer.transformOperations)) {
4916
- _context3.n = 5;
4950
+ // Access transformOperationsManager directly from sceneViewer (it's attached in attachToComponent)
4951
+ if (!(segments.length > 0 && (_this$sceneViewer5 = this.sceneViewer) !== null && _this$sceneViewer5 !== void 0 && _this$sceneViewer5.transformOperationsManager)) {
4952
+ _context4.n = 5;
4917
4953
  break;
4918
4954
  }
4919
4955
  console.log("\uD83D\uDD27 Batch translating ".concat(segments.length, " segments (sequential with throttling)..."));
4920
- transformOpsManager = this.sceneViewer.managers.transformOperations; // Throttle delay in milliseconds (adjust as needed for stability)
4956
+ transformOpsManager = this.sceneViewer.transformOperationsManager; // Throttle delay in milliseconds (adjust as needed for stability)
4921
4957
  THROTTLE_DELAY = 10; // 10ms between axis operations
4922
4958
  SEGMENT_DELAY = 20; // 20ms between segments
4923
4959
  // Helper function for throttled delay
@@ -4928,13 +4964,13 @@ var TransformControlsManager = /*#__PURE__*/function () {
4928
4964
  }; // Process each segment sequentially with throttling for stability
4929
4965
  _loop = /*#__PURE__*/_regenerator().m(function _loop(i) {
4930
4966
  var segment, _segment$userData, _segment$userData2, segmentId, success, newSegmentId, _segment$userData3, _segment$userData4, _segmentId, _success, _newSegmentId, _segment$userData5, _segment$userData6, _segmentId2, _success2, _newSegmentId2, selectedIndex;
4931
- return _regenerator().w(function (_context) {
4932
- while (1) switch (_context.n) {
4967
+ return _regenerator().w(function (_context2) {
4968
+ while (1) switch (_context2.n) {
4933
4969
  case 0:
4934
4970
  segment = segments[i]; // Call translateSegment API with skipPathUpdate=true to defer path updates
4935
4971
  // IMPORTANT: Refresh segment reference after each axis to handle UUID changes from manualization
4936
4972
  if (!(Math.abs(deltaX) > threshold)) {
4937
- _context.n = 1;
4973
+ _context2.n = 1;
4938
4974
  break;
4939
4975
  }
4940
4976
  segmentId = segment.uuid || ((_segment$userData = segment.userData) === null || _segment$userData === void 0 ? void 0 : _segment$userData.originalUuid);
@@ -4944,7 +4980,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
4944
4980
  }
4945
4981
  // Refresh segment reference by searching for the new UUID or by segmentIndex
4946
4982
  // After manualization, UUID changes from SEGMENT-X to Segment-X
4947
- newSegmentId = (_segment$userData2 = segment.userData) !== null && _segment$userData2 !== void 0 && _segment$userData2.segmentIndex ? "Segment-".concat(segment.userData.segmentIndex) : segmentId;
4983
+ newSegmentId = (_segment$userData2 = segment.userData) !== null && _segment$userData2 !== void 0 && _segment$userData2.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : segmentId;
4948
4984
  segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', newSegmentId) || segment;
4949
4985
 
4950
4986
  // Update matrix to ensure geometry is current for next operation
@@ -4952,11 +4988,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
4952
4988
  segment.updateMatrix();
4953
4989
  segment.updateMatrixWorld(true);
4954
4990
  }
4955
- _context.n = 1;
4991
+ _context2.n = 1;
4956
4992
  return _throttleDelay(THROTTLE_DELAY);
4957
4993
  case 1:
4958
4994
  if (!(Math.abs(deltaY) > threshold)) {
4959
- _context.n = 2;
4995
+ _context2.n = 2;
4960
4996
  break;
4961
4997
  }
4962
4998
  _segmentId = segment.uuid || ((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.originalUuid);
@@ -4965,7 +5001,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
4965
5001
  console.warn("\u26A0\uFE0F Failed to translate segment ".concat(_segmentId, " on Y axis"));
4966
5002
  }
4967
5003
  // Refresh segment reference by searching for the new UUID
4968
- _newSegmentId = (_segment$userData4 = segment.userData) !== null && _segment$userData4 !== void 0 && _segment$userData4.segmentIndex ? "Segment-".concat(segment.userData.segmentIndex) : _segmentId;
5004
+ _newSegmentId = (_segment$userData4 = segment.userData) !== null && _segment$userData4 !== void 0 && _segment$userData4.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId;
4969
5005
  segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId) || segment;
4970
5006
 
4971
5007
  // Update matrix to ensure geometry is current for next operation
@@ -4973,11 +5009,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
4973
5009
  segment.updateMatrix();
4974
5010
  segment.updateMatrixWorld(true);
4975
5011
  }
4976
- _context.n = 2;
5012
+ _context2.n = 2;
4977
5013
  return _throttleDelay(THROTTLE_DELAY);
4978
5014
  case 2:
4979
5015
  if (!(Math.abs(deltaZ) > threshold)) {
4980
- _context.n = 3;
5016
+ _context2.n = 3;
4981
5017
  break;
4982
5018
  }
4983
5019
  _segmentId2 = segment.uuid || ((_segment$userData5 = segment.userData) === null || _segment$userData5 === void 0 ? void 0 : _segment$userData5.originalUuid);
@@ -4986,7 +5022,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
4986
5022
  console.warn("\u26A0\uFE0F Failed to translate segment ".concat(_segmentId2, " on Z axis"));
4987
5023
  }
4988
5024
  // Refresh segment reference by searching for the new UUID
4989
- _newSegmentId2 = (_segment$userData6 = segment.userData) !== null && _segment$userData6 !== void 0 && _segment$userData6.segmentIndex ? "Segment-".concat(segment.userData.segmentIndex) : _segmentId2;
5025
+ _newSegmentId2 = (_segment$userData6 = segment.userData) !== null && _segment$userData6 !== void 0 && _segment$userData6.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId2;
4990
5026
  segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId2) || segment;
4991
5027
 
4992
5028
  // Update matrix to ensure geometry is current for next operation
@@ -4994,7 +5030,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
4994
5030
  segment.updateMatrix();
4995
5031
  segment.updateMatrixWorld(true);
4996
5032
  }
4997
- _context.n = 3;
5033
+ _context2.n = 3;
4998
5034
  return _throttleDelay(THROTTLE_DELAY);
4999
5035
  case 3:
5000
5036
  // Update the segment in the selectedObjects array with the refreshed reference
@@ -5026,26 +5062,26 @@ var TransformControlsManager = /*#__PURE__*/function () {
5026
5062
 
5027
5063
  // Delay between segments to ensure all updates propagate
5028
5064
  if (!(i < segments.length - 1)) {
5029
- _context.n = 4;
5065
+ _context2.n = 4;
5030
5066
  break;
5031
5067
  }
5032
- _context.n = 4;
5068
+ _context2.n = 4;
5033
5069
  return _throttleDelay(SEGMENT_DELAY);
5034
5070
  case 4:
5035
- return _context.a(2);
5071
+ return _context2.a(2);
5036
5072
  }
5037
5073
  }, _loop);
5038
5074
  });
5039
5075
  i = 0;
5040
5076
  case 2:
5041
5077
  if (!(i < segments.length)) {
5042
- _context3.n = 4;
5078
+ _context4.n = 4;
5043
5079
  break;
5044
5080
  }
5045
- return _context3.d(_regeneratorValues(_loop(i)), 3);
5081
+ return _context4.d(_regeneratorValues(_loop(i)), 3);
5046
5082
  case 3:
5047
5083
  i++;
5048
- _context3.n = 2;
5084
+ _context4.n = 2;
5049
5085
  break;
5050
5086
  case 4:
5051
5087
  // Only call updatePaths ONCE after all segments are translated
@@ -5054,11 +5090,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
5054
5090
  this.sceneViewer.updatePaths();
5055
5091
  console.log('✅ Paths regenerated successfully for all segments');
5056
5092
  }
5057
- _context3.n = 8;
5093
+ _context4.n = 8;
5058
5094
  break;
5059
5095
  case 5:
5060
5096
  if (!(segments.length > 0)) {
5061
- _context3.n = 8;
5097
+ _context4.n = 8;
5062
5098
  break;
5063
5099
  }
5064
5100
  // Fallback to individual API calls if manager not available
@@ -5075,18 +5111,18 @@ var TransformControlsManager = /*#__PURE__*/function () {
5075
5111
  };
5076
5112
  _loop2 = /*#__PURE__*/_regenerator().m(function _loop2(_i) {
5077
5113
  var segment, _segment$userData7, _segment$userData8, segmentId, newSegmentId, _segment$userData9, _segment$userData0, _segmentId3, _newSegmentId3, _segment$userData1, _segment$userData10, _segmentId4, _newSegmentId4, selectedIndex;
5078
- return _regenerator().w(function (_context2) {
5079
- while (1) switch (_context2.n) {
5114
+ return _regenerator().w(function (_context3) {
5115
+ while (1) switch (_context3.n) {
5080
5116
  case 0:
5081
5117
  segment = segments[_i];
5082
5118
  if (!(Math.abs(deltaX) > threshold)) {
5083
- _context2.n = 1;
5119
+ _context3.n = 1;
5084
5120
  break;
5085
5121
  }
5086
5122
  segmentId = segment.uuid || ((_segment$userData7 = segment.userData) === null || _segment$userData7 === void 0 ? void 0 : _segment$userData7.originalUuid);
5087
5123
  _this9.centralPlant.translateSegment(segmentId, 'x', deltaX);
5088
5124
  // Refresh segment reference by searching for the new UUID after manualization
5089
- newSegmentId = (_segment$userData8 = segment.userData) !== null && _segment$userData8 !== void 0 && _segment$userData8.segmentIndex ? "Segment-".concat(segment.userData.segmentIndex) : segmentId;
5125
+ newSegmentId = (_segment$userData8 = segment.userData) !== null && _segment$userData8 !== void 0 && _segment$userData8.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : segmentId;
5090
5126
  segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', newSegmentId) || segment;
5091
5127
 
5092
5128
  // Update matrix to ensure geometry is current for next operation
@@ -5094,17 +5130,17 @@ var TransformControlsManager = /*#__PURE__*/function () {
5094
5130
  segment.updateMatrix();
5095
5131
  segment.updateMatrixWorld(true);
5096
5132
  }
5097
- _context2.n = 1;
5133
+ _context3.n = 1;
5098
5134
  return _throttleDelay2(_THROTTLE_DELAY);
5099
5135
  case 1:
5100
5136
  if (!(Math.abs(deltaY) > threshold)) {
5101
- _context2.n = 2;
5137
+ _context3.n = 2;
5102
5138
  break;
5103
5139
  }
5104
5140
  _segmentId3 = segment.uuid || ((_segment$userData9 = segment.userData) === null || _segment$userData9 === void 0 ? void 0 : _segment$userData9.originalUuid);
5105
5141
  _this9.centralPlant.translateSegment(_segmentId3, 'y', deltaY);
5106
5142
  // Refresh segment reference by searching for the new UUID after manualization
5107
- _newSegmentId3 = (_segment$userData0 = segment.userData) !== null && _segment$userData0 !== void 0 && _segment$userData0.segmentIndex ? "Segment-".concat(segment.userData.segmentIndex) : _segmentId3;
5143
+ _newSegmentId3 = (_segment$userData0 = segment.userData) !== null && _segment$userData0 !== void 0 && _segment$userData0.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId3;
5108
5144
  segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId3) || segment;
5109
5145
 
5110
5146
  // Update matrix to ensure geometry is current for next operation
@@ -5112,17 +5148,17 @@ var TransformControlsManager = /*#__PURE__*/function () {
5112
5148
  segment.updateMatrix();
5113
5149
  segment.updateMatrixWorld(true);
5114
5150
  }
5115
- _context2.n = 2;
5151
+ _context3.n = 2;
5116
5152
  return _throttleDelay2(_THROTTLE_DELAY);
5117
5153
  case 2:
5118
5154
  if (!(Math.abs(deltaZ) > threshold)) {
5119
- _context2.n = 3;
5155
+ _context3.n = 3;
5120
5156
  break;
5121
5157
  }
5122
5158
  _segmentId4 = segment.uuid || ((_segment$userData1 = segment.userData) === null || _segment$userData1 === void 0 ? void 0 : _segment$userData1.originalUuid);
5123
5159
  _this9.centralPlant.translateSegment(_segmentId4, 'z', deltaZ);
5124
5160
  // Refresh segment reference by searching for the new UUID after manualization
5125
- _newSegmentId4 = (_segment$userData10 = segment.userData) !== null && _segment$userData10 !== void 0 && _segment$userData10.segmentIndex ? "Segment-".concat(segment.userData.segmentIndex) : _segmentId4;
5161
+ _newSegmentId4 = (_segment$userData10 = segment.userData) !== null && _segment$userData10 !== void 0 && _segment$userData10.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId4;
5126
5162
  segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId4) || segment;
5127
5163
 
5128
5164
  // Update matrix to ensure geometry is current for next operation
@@ -5130,7 +5166,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
5130
5166
  segment.updateMatrix();
5131
5167
  segment.updateMatrixWorld(true);
5132
5168
  }
5133
- _context2.n = 3;
5169
+ _context3.n = 3;
5134
5170
  return _throttleDelay2(_THROTTLE_DELAY);
5135
5171
  case 3:
5136
5172
  // Update the segment in the selectedObjects array with the refreshed reference
@@ -5161,26 +5197,26 @@ var TransformControlsManager = /*#__PURE__*/function () {
5161
5197
 
5162
5198
  // Delay between segments
5163
5199
  if (!(_i < segments.length - 1)) {
5164
- _context2.n = 4;
5200
+ _context3.n = 4;
5165
5201
  break;
5166
5202
  }
5167
- _context2.n = 4;
5203
+ _context3.n = 4;
5168
5204
  return _throttleDelay2(_SEGMENT_DELAY);
5169
5205
  case 4:
5170
- return _context2.a(2);
5206
+ return _context3.a(2);
5171
5207
  }
5172
5208
  }, _loop2);
5173
5209
  });
5174
5210
  _i = 0;
5175
5211
  case 6:
5176
5212
  if (!(_i < segments.length)) {
5177
- _context3.n = 8;
5213
+ _context4.n = 8;
5178
5214
  break;
5179
5215
  }
5180
- return _context3.d(_regeneratorValues(_loop2(_i)), 7);
5216
+ return _context4.d(_regeneratorValues(_loop2(_i)), 7);
5181
5217
  case 7:
5182
5218
  _i++;
5183
- _context3.n = 6;
5219
+ _context4.n = 6;
5184
5220
  break;
5185
5221
  case 8:
5186
5222
  // Throttle delays for gateways and components
@@ -5196,33 +5232,33 @@ var TransformControlsManager = /*#__PURE__*/function () {
5196
5232
  _i2 = 0;
5197
5233
  case 9:
5198
5234
  if (!(_i2 < gateways.length)) {
5199
- _context3.n = 14;
5235
+ _context4.n = 14;
5200
5236
  break;
5201
5237
  }
5202
5238
  gateway = gateways[_i2];
5203
5239
  gatewayId = gateway.uuid || ((_gateway$userData = gateway.userData) === null || _gateway$userData === void 0 ? void 0 : _gateway$userData.originalUuid);
5204
5240
  if (!(Math.abs(deltaX) > threshold)) {
5205
- _context3.n = 10;
5241
+ _context4.n = 10;
5206
5242
  break;
5207
5243
  }
5208
5244
  this.centralPlant.translateGateway(gatewayId, 'x', deltaX);
5209
- _context3.n = 10;
5245
+ _context4.n = 10;
5210
5246
  return throttleDelay(GATEWAY_THROTTLE);
5211
5247
  case 10:
5212
5248
  if (!(Math.abs(deltaY) > threshold)) {
5213
- _context3.n = 11;
5249
+ _context4.n = 11;
5214
5250
  break;
5215
5251
  }
5216
5252
  this.centralPlant.translateGateway(gatewayId, 'y', deltaY);
5217
- _context3.n = 11;
5253
+ _context4.n = 11;
5218
5254
  return throttleDelay(GATEWAY_THROTTLE);
5219
5255
  case 11:
5220
5256
  if (!(Math.abs(deltaZ) > threshold)) {
5221
- _context3.n = 12;
5257
+ _context4.n = 12;
5222
5258
  break;
5223
5259
  }
5224
5260
  this.centralPlant.translateGateway(gatewayId, 'z', deltaZ);
5225
- _context3.n = 12;
5261
+ _context4.n = 12;
5226
5262
  return throttleDelay(GATEWAY_THROTTLE);
5227
5263
  case 12:
5228
5264
  console.log("\uD83D\uDEAA Gateway ".concat(gateway.name, " translated (").concat(_i2 + 1, "/").concat(gateways.length, "):"), {
@@ -5233,46 +5269,46 @@ var TransformControlsManager = /*#__PURE__*/function () {
5233
5269
 
5234
5270
  // Delay between gateways
5235
5271
  if (!(_i2 < gateways.length - 1)) {
5236
- _context3.n = 13;
5272
+ _context4.n = 13;
5237
5273
  break;
5238
5274
  }
5239
- _context3.n = 13;
5275
+ _context4.n = 13;
5240
5276
  return throttleDelay(GATEWAY_DELAY);
5241
5277
  case 13:
5242
5278
  _i2++;
5243
- _context3.n = 9;
5279
+ _context4.n = 9;
5244
5280
  break;
5245
5281
  case 14:
5246
5282
  _i3 = 0;
5247
5283
  case 15:
5248
5284
  if (!(_i3 < components.length)) {
5249
- _context3.n = 20;
5285
+ _context4.n = 20;
5250
5286
  break;
5251
5287
  }
5252
5288
  component = components[_i3];
5253
5289
  componentId = component.uuid || ((_component$userData = component.userData) === null || _component$userData === void 0 ? void 0 : _component$userData.originalUuid);
5254
5290
  if (!(Math.abs(deltaX) > threshold)) {
5255
- _context3.n = 16;
5291
+ _context4.n = 16;
5256
5292
  break;
5257
5293
  }
5258
5294
  this.centralPlant.translate(componentId, 'x', deltaX);
5259
- _context3.n = 16;
5295
+ _context4.n = 16;
5260
5296
  return throttleDelay(COMPONENT_THROTTLE);
5261
5297
  case 16:
5262
5298
  if (!(Math.abs(deltaY) > threshold)) {
5263
- _context3.n = 17;
5299
+ _context4.n = 17;
5264
5300
  break;
5265
5301
  }
5266
5302
  this.centralPlant.translate(componentId, 'y', deltaY);
5267
- _context3.n = 17;
5303
+ _context4.n = 17;
5268
5304
  return throttleDelay(COMPONENT_THROTTLE);
5269
5305
  case 17:
5270
5306
  if (!(Math.abs(deltaZ) > threshold)) {
5271
- _context3.n = 18;
5307
+ _context4.n = 18;
5272
5308
  break;
5273
5309
  }
5274
5310
  this.centralPlant.translate(componentId, 'z', deltaZ);
5275
- _context3.n = 18;
5311
+ _context4.n = 18;
5276
5312
  return throttleDelay(COMPONENT_THROTTLE);
5277
5313
  case 18:
5278
5314
  console.log("\uD83D\uDD27 Component ".concat(component.name, " translated (").concat(_i3 + 1, "/").concat(components.length, "):"), {
@@ -5283,14 +5319,14 @@ var TransformControlsManager = /*#__PURE__*/function () {
5283
5319
 
5284
5320
  // Delay between components
5285
5321
  if (!(_i3 < components.length - 1)) {
5286
- _context3.n = 19;
5322
+ _context4.n = 19;
5287
5323
  break;
5288
5324
  }
5289
- _context3.n = 19;
5325
+ _context4.n = 19;
5290
5326
  return throttleDelay(COMPONENT_DELAY);
5291
5327
  case 19:
5292
5328
  _i3++;
5293
- _context3.n = 15;
5329
+ _context4.n = 15;
5294
5330
  break;
5295
5331
  case 20:
5296
5332
  console.log("\u2705 All ".concat(this.selectedObjects.length, " objects translated with delta:"), {
@@ -5319,9 +5355,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
5319
5355
  }
5320
5356
  console.log("\u2705 Multi-selection transform applied");
5321
5357
  case 22:
5322
- return _context3.a(2);
5358
+ return _context4.a(2);
5323
5359
  }
5324
- }, _callee, this);
5360
+ }, _callee2, this);
5325
5361
  }));
5326
5362
  function applyMultiSelectionTransform() {
5327
5363
  return _applyMultiSelectionTransform.apply(this, arguments);
@@ -19020,6 +19056,20 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19020
19056
  this.fixUndergroundComponent(component);
19021
19057
  }
19022
19058
 
19059
+ // Auto-update paths if enabled (matches behavior of translateSegment and translateGateway)
19060
+ if (this.sceneViewer.shouldUpdatePaths) {
19061
+ try {
19062
+ if (this.sceneViewer && typeof this.sceneViewer.updatePaths === 'function') {
19063
+ this.sceneViewer.updatePaths();
19064
+ console.log('🔄 Paths auto-updated after component translation');
19065
+ } else {
19066
+ console.warn('âš ī¸ updatePaths method not available on sceneViewer');
19067
+ }
19068
+ } catch (error) {
19069
+ console.error('❌ Error auto-updating paths:', error);
19070
+ }
19071
+ }
19072
+
19023
19073
  // Emit transform event if available
19024
19074
  if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
19025
19075
  this.sceneViewer.emit('objectTransformed', {
@@ -19040,23 +19090,30 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19040
19090
  * @param {number} value - The value to translate by
19041
19091
  * @returns {boolean} True if translation was successful, false otherwise
19042
19092
  */
19093
+ /**
19094
+ * Validate all preconditions for translateSegment operation
19095
+ * @param {string} segmentId - The UUID of the segment to translate
19096
+ * @param {string} axis - The axis to translate on ('x', 'y', or 'z')
19097
+ * @param {number} value - The value to translate by
19098
+ * @returns {Object|null} Returns { segment } if all checks pass, null otherwise
19099
+ * @private
19100
+ */
19043
19101
  }, {
19044
- key: "translateSegment",
19045
- value: function translateSegment(segmentId, axis, value) {
19046
- var _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$man3, _this$sceneViewer$man4, _this$sceneViewer$man5;
19047
- var skipPathUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
19102
+ key: "validateTranslateSegment",
19103
+ value: function validateTranslateSegment(segmentId, axis, value) {
19104
+ var _segment$userData, _segment$userData2, _segment$userData3;
19048
19105
  // Validate parameters
19049
19106
  if (!segmentId || !axis || value === undefined || value === null) {
19050
19107
  console.error('❌ translateSegment(): Invalid parameters');
19051
- return false;
19108
+ return null;
19052
19109
  }
19053
19110
  if (!['x', 'y', 'z'].includes(axis)) {
19054
19111
  console.error("\u274C translateSegment(): Invalid axis '".concat(axis, "'. Must be 'x', 'y', or 'z'"));
19055
- return false;
19112
+ return null;
19056
19113
  }
19057
19114
  if (!this.sceneViewer || !this.sceneViewer.scene) {
19058
19115
  console.error('❌ translateSegment(): Scene viewer or scene not available');
19059
- return false;
19116
+ return null;
19060
19117
  }
19061
19118
 
19062
19119
  // Find the segment in the scene
@@ -19069,19 +19126,25 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19069
19126
  });
19070
19127
  if (!segment) {
19071
19128
  console.error("\u274C translateSegment(): Segment with ID '".concat(segmentId, "' not found in scene"));
19072
- return false;
19129
+ return null;
19073
19130
  }
19074
19131
 
19075
19132
  // Validate that it's actually a pipe segment
19076
19133
  if (!((_segment$userData = segment.userData) !== null && _segment$userData !== void 0 && _segment$userData.objectType) === 'segment') {
19077
19134
  console.error("\u274C translateSegment(): Object with ID '".concat(segmentId, "' is not a valid pipe segment"));
19078
- return false;
19135
+ return null;
19079
19136
  }
19080
19137
 
19081
19138
  // Check if segment is transformable
19082
19139
  if (((_segment$userData2 = segment.userData) === null || _segment$userData2 === void 0 ? void 0 : _segment$userData2.transformable) === false) {
19083
19140
  console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' is marked as non-transformable (stub segment)"));
19084
- return false;
19141
+ return null;
19142
+ }
19143
+
19144
+ // Check if segment is immutable (computed from pathfinder)
19145
+ if (((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.immutable) === true) {
19146
+ console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' is immutable (computed from pathfinder)"));
19147
+ return null;
19085
19148
  }
19086
19149
 
19087
19150
  // Check segment orientation and cancel invalid translations
@@ -19100,160 +19163,129 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19100
19163
  if (absX > tolerance && axis === 'x') {
19101
19164
  console.warn("\u26A0\uFE0F translateSegment(): Cannot translate segment along ".concat(axis.toUpperCase(), " axis - segment runs along this axis"));
19102
19165
  console.warn(" Segment direction: [".concat(direction.x.toFixed(3), ", ").concat(direction.y.toFixed(3), ", ").concat(direction.z.toFixed(3), "]"));
19103
- return false;
19166
+ return null;
19104
19167
  }
19105
19168
  if (absY > tolerance && axis === 'y') {
19106
19169
  console.warn("\u26A0\uFE0F translateSegment(): Cannot translate segment along ".concat(axis.toUpperCase(), " axis - segment runs along this axis"));
19107
19170
  console.warn(" Segment direction: [".concat(direction.x.toFixed(3), ", ").concat(direction.y.toFixed(3), ", ").concat(direction.z.toFixed(3), "]"));
19108
- return false;
19171
+ return null;
19109
19172
  }
19110
19173
  if (absZ > tolerance && axis === 'z') {
19111
19174
  console.warn("\u26A0\uFE0F translateSegment(): Cannot translate segment along ".concat(axis.toUpperCase(), " axis - segment runs along this axis"));
19112
19175
  console.warn(" Segment direction: [".concat(direction.x.toFixed(3), ", ").concat(direction.y.toFixed(3), ", ").concat(direction.z.toFixed(3), "]"));
19113
- return false;
19176
+ return null;
19114
19177
  }
19115
- console.log('[translateSegment] segment:', segment);
19116
19178
 
19117
- // Calculate segment endpoints to check for nearby connectors
19118
- var segmentEndpoints = this.calculateSegmentEndpoints(segment);
19119
-
19120
- // Check if there are any connectors (component or manual) at segment endpoints
19121
- var connectorsAtEndpoints = this.findConnectorsAtPositions([segmentEndpoints.start, segmentEndpoints.end], 0.15 // tolerance for position matching
19122
- );
19123
- console.log("\uD83D\uDD0D Found ".concat(connectorsAtEndpoints.length, " total connectors at segment endpoints:"), connectorsAtEndpoints.map(function (c) {
19124
- var _c$userData, _c$parent, _c$parent2;
19125
- return {
19126
- uuid: c.uuid,
19127
- type: (_c$userData = c.userData) === null || _c$userData === void 0 ? void 0 : _c$userData.objectType,
19128
- parent: (_c$parent = c.parent) === null || _c$parent === void 0 ? void 0 : _c$parent.uuid,
19129
- parentType: (_c$parent2 = c.parent) === null || _c$parent2 === void 0 || (_c$parent2 = _c$parent2.userData) === null || _c$parent2 === void 0 ? void 0 : _c$parent2.objectType
19130
- };
19131
- }));
19132
-
19133
- // Filter out segment connectors - we only care about component connectors
19134
- var componentConnectorsAtEndpoints = connectorsAtEndpoints.filter(function (connector) {
19135
- var _connector$userData;
19136
- return ((_connector$userData = connector.userData) === null || _connector$userData === void 0 ? void 0 : _connector$userData.objectType) !== 'segment-connector';
19137
- });
19138
- console.log("\uD83D\uDD0D After filtering, ".concat(componentConnectorsAtEndpoints.length, " component connectors at endpoints"));
19139
- if (componentConnectorsAtEndpoints.length > 0) {
19140
- var _this$sceneViewer2, _this$sceneViewer$man2;
19141
- console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' has component connectors at endpoints."));
19142
- console.log(" Found ".concat(componentConnectorsAtEndpoints.length, " component connector(s):"), componentConnectorsAtEndpoints.map(function (c) {
19143
- var _c$parent3;
19144
- return {
19145
- uuid: c.uuid,
19146
- parent: (_c$parent3 = c.parent) === null || _c$parent3 === void 0 ? void 0 : _c$parent3.uuid
19147
- };
19148
- }));
19149
-
19150
- // Check if segment splitting is enabled in settings
19151
- var splitSegmentsEnabled = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.managers) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.settingsManager) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.getSetting('scene', 'splitSegmentsWithComponentConnectors');
19152
- if (splitSegmentsEnabled === false) {
19153
- console.warn('âš ī¸ Segment splitting is disabled. Cannot translate segments with component connectors at endpoints.');
19154
- return false;
19155
- }
19156
-
19157
- // Split the segment and translate the free half
19158
- console.log('âœ‚ī¸ Splitting segment to enable translation of the free half...');
19179
+ // All checks passed - return the segment
19180
+ return {
19181
+ segment: segment
19182
+ };
19183
+ }
19159
19184
 
19160
- // Get sceneOperationsManager
19161
- var _sceneOperationsManager = (_this$sceneViewer$man2 = this.sceneViewer.managers) === null || _this$sceneViewer$man2 === void 0 ? void 0 : _this$sceneViewer$man2.sceneOperationsManager;
19162
- if (!_sceneOperationsManager) {
19163
- console.error('❌ translateSegment(): SceneOperationsManager not available for splitting');
19164
- return false;
19165
- }
19166
- try {
19167
- var splitResult = _sceneOperationsManager.splitSegment(segment, this.sceneViewer.currentSceneData);
19168
- if (splitResult) {
19169
- console.log("\u2705 Segment split and shortened: ".concat(splitResult.uuid, " (new length: ").concat(splitResult.geometry.parameters.height, ")"));
19170
-
19171
- // The splitResult is now a shortened manual segment
19172
- // Translate this shortened segment
19173
- console.log("\uD83C\uDFAF Translating shortened manual segment: ".concat(splitResult.uuid));
19174
-
19175
- // Now translate the shortened manual segment (recursive call with the new segment)
19176
- var translateSuccess = this.translateSegment(splitResult.uuid, axis, value);
19177
- if (!translateSuccess) {
19178
- console.error('❌ translateSegment(): Failed to translate shortened manual segment');
19179
- return false;
19180
- }
19181
- console.log('✅ Split, shorten, and translate operation completed successfully');
19182
- return true;
19183
- } else {
19184
- console.error('❌ translateSegment(): Split operation failed');
19185
- return false;
19186
- }
19187
- } catch (error) {
19188
- console.error('❌ translateSegment(): Error splitting segment:', error);
19189
- return false;
19190
- }
19191
- }
19192
- console.log("\uD83D\uDD04 translateSegment(): Translating segment ".concat(segmentId, " on ").concat(axis, " axis by ").concat(value));
19185
+ /**
19186
+ * Validate collision constraints for translateSegment operation
19187
+ * Temporarily applies the translation to check for collisions, then reverts
19188
+ * @param {THREE.Object3D} segment - The segment to check
19189
+ * @param {string} axis - The axis to translate on ('x', 'y', or 'z')
19190
+ * @param {number} value - The value to translate by
19191
+ * @returns {boolean} True if no collisions detected, false if translation would cause collision
19192
+ * @private
19193
+ */
19194
+ }, {
19195
+ key: "validateTranslateSegmentCollisions",
19196
+ value: function validateTranslateSegmentCollisions(segment, axis, value) {
19197
+ var _this$sceneViewer2;
19198
+ // Store original position for reverting
19199
+ var originalPosition = segment.position[axis];
19193
19200
 
19194
19201
  // Temporarily apply the translation to check for collisions
19195
- var originalPosition = segment.position[axis];
19196
19202
  segment.position[axis] += value;
19197
19203
  segment.updateMatrix();
19198
19204
  segment.updateMatrixWorld(true);
19199
19205
 
19200
19206
  // Check for collision with component connectors along the segment's path
19201
- var collision = this.checkSegmentPathConnectorCollision(segment);
19202
- if (collision) {
19207
+ var connectorCollision = this.checkSegmentPathConnectorCollision(segment);
19208
+ if (connectorCollision) {
19203
19209
  // Revert the translation
19204
19210
  segment.position[axis] = originalPosition;
19205
19211
  segment.updateMatrix();
19206
19212
  segment.updateMatrixWorld(true);
19207
19213
  console.warn("\u26A0\uFE0F translateSegment(): Translation canceled - segment path comes within 0.5 radius of component connector");
19208
- console.warn(" Distance to connector: ".concat(collision.distance.toFixed(3), " (max allowed: 0.5)"));
19209
- console.warn(" Closest point on segment: [".concat(collision.collisionPoint.x.toFixed(3), ", ").concat(collision.collisionPoint.y.toFixed(3), ", ").concat(collision.collisionPoint.z.toFixed(3), "]"));
19210
- console.warn(" Connector position: [".concat(collision.connectorPos.x.toFixed(3), ", ").concat(collision.connectorPos.y.toFixed(3), ", ").concat(collision.connectorPos.z.toFixed(3), "]"));
19211
- console.warn(" Colliding connector: ".concat(collision.connectorId, " on component: ").concat(collision.componentId));
19214
+ console.warn(" Distance to connector: ".concat(connectorCollision.distance.toFixed(3), " (max allowed: 0.5)"));
19215
+ console.warn(" Closest point on segment: [".concat(connectorCollision.collisionPoint.x.toFixed(3), ", ").concat(connectorCollision.collisionPoint.y.toFixed(3), ", ").concat(connectorCollision.collisionPoint.z.toFixed(3), "]"));
19216
+ console.warn(" Connector position: [".concat(connectorCollision.connectorPos.x.toFixed(3), ", ").concat(connectorCollision.connectorPos.y.toFixed(3), ", ").concat(connectorCollision.connectorPos.z.toFixed(3), "]"));
19217
+ console.warn(" Colliding connector: ".concat(connectorCollision.connectorId, " on component: ").concat(connectorCollision.componentId));
19212
19218
  return false;
19213
19219
  }
19214
19220
 
19215
- // Revert the temporary translation before continuing with the normal flow
19216
- segment.position[axis] = originalPosition;
19217
- segment.updateMatrix();
19218
- segment.updateMatrixWorld(true);
19221
+ // Check for collision with component bounding boxes
19222
+ var componentCollision = this.checkSegmentComponentBoundingBoxCollision(segment);
19223
+ if (componentCollision) {
19224
+ // Revert the translation
19225
+ segment.position[axis] = originalPosition;
19226
+ segment.updateMatrix();
19227
+ segment.updateMatrixWorld(true);
19228
+ console.warn("\u26A0\uFE0F translateSegment(): Translation canceled - segment would collide with component bounding box");
19229
+ console.warn(" Component ID: ".concat(componentCollision.componentId));
19230
+ console.warn(" Component Name: ".concat(componentCollision.componentName));
19231
+ console.warn(" Component Type: ".concat(componentCollision.componentType));
19232
+ return false;
19233
+ }
19219
19234
 
19220
19235
  // Check if translationalOverrideForAutomaticSegments is enabled
19221
- var translationalOverride = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.managers) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.settingsManager) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.getSetting('scene', 'translationalOverrideForAutomaticSegments');
19236
+ var translationalOverride = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.managers) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.settingsManager) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.getSetting('scene', 'translationalOverrideForAutomaticSegments');
19222
19237
 
19223
19238
  // If override is disabled (false), check for intersections with computed segments
19224
19239
  if (translationalOverride === false) {
19225
19240
  console.log('🔍 Checking for intersections with computed segments (translationalOverrideForAutomaticSegments is disabled)');
19226
19241
 
19227
- // Temporarily apply the translation to check for intersections
19228
- var _originalPosition = segment.position[axis];
19229
- segment.position[axis] += value;
19230
- segment.updateMatrix();
19231
- segment.updateMatrixWorld(true);
19232
-
19233
19242
  // Check if the translated segment intersects with any computed segments
19234
19243
  var hasIntersection = this.checkSegmentIntersection(segment);
19235
19244
  console.log("\uD83D\uDD04 translateSegment() hasIntersection:", hasIntersection);
19236
19245
  if (hasIntersection) {
19237
19246
  // Revert the translation
19238
- segment.position[axis] = _originalPosition;
19247
+ segment.position[axis] = originalPosition;
19239
19248
  segment.updateMatrix();
19240
19249
  segment.updateMatrixWorld(true);
19241
19250
  console.warn("\u26A0\uFE0F translateSegment(): Translation canceled - segment would intersect with computed segment(s)");
19242
19251
  return false;
19243
19252
  }
19244
19253
  console.log('✅ No intersections detected, proceeding with translation');
19245
- } else {
19246
- // Apply the translation to the Three.js object
19247
- segment.position[axis] += value;
19254
+ }
19248
19255
 
19249
- // Update matrices
19250
- segment.updateMatrix();
19251
- segment.updateMatrixWorld(true);
19256
+ // Revert the temporary translation
19257
+ segment.position[axis] = originalPosition;
19258
+ segment.updateMatrix();
19259
+ segment.updateMatrixWorld(true);
19260
+ return true;
19261
+ }
19262
+ }, {
19263
+ key: "translateSegment",
19264
+ value: function translateSegment(segmentId, axis, value) {
19265
+ var _this$sceneViewer$man2, _this$sceneViewer$man3, _this$sceneViewer$man4;
19266
+ var skipPathUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
19267
+ // Run all basic validation checks
19268
+ var validationResult = this.validateTranslateSegment(segmentId, axis, value);
19269
+ if (!validationResult) {
19270
+ return false;
19271
+ }
19272
+ var segment = validationResult.segment;
19273
+ console.log("\uD83D\uDD04 translateSegment(): Translating segment ".concat(segmentId, " on ").concat(axis, " axis by ").concat(value));
19274
+
19275
+ // Run collision validation checks
19276
+ var collisionValidation = this.validateTranslateSegmentCollisions(segment, axis, value);
19277
+ if (!collisionValidation) {
19278
+ return false;
19252
19279
  }
19253
19280
 
19281
+ // All validations passed - apply the translation
19282
+ segment.position[axis] += value;
19283
+ segment.updateMatrix();
19284
+ segment.updateMatrixWorld(true);
19285
+
19254
19286
  // Validate PathfindingManager and SceneOperationsManager availability
19255
- var pathfindingManager = (_this$sceneViewer$man3 = this.sceneViewer.managers) === null || _this$sceneViewer$man3 === void 0 ? void 0 : _this$sceneViewer$man3.pathfindingManager;
19256
- var sceneOperationsManager = (_this$sceneViewer$man4 = this.sceneViewer.managers) === null || _this$sceneViewer$man4 === void 0 ? void 0 : _this$sceneViewer$man4.sceneOperationsManager;
19287
+ var pathfindingManager = (_this$sceneViewer$man2 = this.sceneViewer.managers) === null || _this$sceneViewer$man2 === void 0 ? void 0 : _this$sceneViewer$man2.pathfindingManager;
19288
+ var sceneOperationsManager = (_this$sceneViewer$man3 = this.sceneViewer.managers) === null || _this$sceneViewer$man3 === void 0 ? void 0 : _this$sceneViewer$man3.sceneOperationsManager;
19257
19289
  if (!pathfindingManager || !sceneOperationsManager) {
19258
19290
  console.error('❌ translateSegment(): PathfindingManager or SceneOperationsManager not available');
19259
19291
  return false;
@@ -19278,7 +19310,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19278
19310
 
19279
19311
  // Store transform parameters using the OperationHistoryManager BEFORE updatePaths
19280
19312
  // This is critical so that intersection detection can undo the operation
19281
- if ((_this$sceneViewer$man5 = this.sceneViewer.managers) !== null && _this$sceneViewer$man5 !== void 0 && _this$sceneViewer$man5.operationHistory) {
19313
+ if ((_this$sceneViewer$man4 = this.sceneViewer.managers) !== null && _this$sceneViewer$man4 !== void 0 && _this$sceneViewer$man4.operationHistory) {
19282
19314
  this.sceneViewer.managers.operationHistory.addToOperationHistory('translateSegment', {
19283
19315
  segmentId: segmentId,
19284
19316
  axis: axis,
@@ -19328,11 +19360,11 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19328
19360
  }, {
19329
19361
  key: "translateGateway",
19330
19362
  value: function translateGateway(gatewayId, axis, value) {
19331
- var _this$sceneViewer$man6, _this$sceneViewer$man7;
19363
+ var _this$sceneViewer$man5, _this$sceneViewer$man6;
19332
19364
  console.log("[Pathfinder] translateGateway started");
19333
19365
 
19334
19366
  // Store transform parameters using the OperationHistoryManager
19335
- if ((_this$sceneViewer$man6 = this.sceneViewer.managers) !== null && _this$sceneViewer$man6 !== void 0 && _this$sceneViewer$man6.operationHistoryManager) {
19367
+ if ((_this$sceneViewer$man5 = this.sceneViewer.managers) !== null && _this$sceneViewer$man5 !== void 0 && _this$sceneViewer$man5.operationHistoryManager) {
19336
19368
  this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateGateway', {
19337
19369
  gatewayId: gatewayId,
19338
19370
  axis: axis,
@@ -19383,7 +19415,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19383
19415
 
19384
19416
  // Handle manual gateway transformation (convert to declared and process connections)
19385
19417
  console.log('🔧 Handling manual gateway transformation via SceneOperationsManager');
19386
- var sceneOperationsManager = (_this$sceneViewer$man7 = this.sceneViewer.managers) === null || _this$sceneViewer$man7 === void 0 ? void 0 : _this$sceneViewer$man7.sceneOperationsManager;
19418
+ var sceneOperationsManager = (_this$sceneViewer$man6 = this.sceneViewer.managers) === null || _this$sceneViewer$man6 === void 0 ? void 0 : _this$sceneViewer$man6.sceneOperationsManager;
19387
19419
  if (!sceneOperationsManager) {
19388
19420
  console.error('❌ translateGateway(): SceneOperationsManager not available');
19389
19421
  return false;
@@ -19485,6 +19517,20 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19485
19517
  component.updateMatrix();
19486
19518
  component.updateMatrixWorld(true);
19487
19519
 
19520
+ // Auto-update paths if enabled (matches behavior of translateComponent)
19521
+ if (this.sceneViewer.shouldUpdatePaths) {
19522
+ try {
19523
+ if (this.sceneViewer && typeof this.sceneViewer.updatePaths === 'function') {
19524
+ this.sceneViewer.updatePaths();
19525
+ console.log('🔄 Paths auto-updated after component rotation');
19526
+ } else {
19527
+ console.warn('âš ī¸ updatePaths method not available on sceneViewer');
19528
+ }
19529
+ } catch (error) {
19530
+ console.error('❌ Error auto-updating paths:', error);
19531
+ }
19532
+ }
19533
+
19488
19534
  // Emit transform event if available
19489
19535
  if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
19490
19536
  this.sceneViewer.emit('objectTransformed', {
@@ -19667,9 +19713,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19667
19713
  }, {
19668
19714
  key: "findConnectorsAtPositions",
19669
19715
  value: function findConnectorsAtPositions(positions) {
19670
- var _this$sceneViewer4;
19716
+ var _this$sceneViewer3;
19671
19717
  var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.15;
19672
- if (!((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.scene)) {
19718
+ if (!((_this$sceneViewer3 = this.sceneViewer) !== null && _this$sceneViewer3 !== void 0 && _this$sceneViewer3.scene)) {
19673
19719
  return [];
19674
19720
  }
19675
19721
  var foundConnectors = [];
@@ -19713,9 +19759,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19713
19759
  }, {
19714
19760
  key: "updateSegmentConnectorPositions",
19715
19761
  value: function updateSegmentConnectorPositions(segment) {
19716
- var _this$sceneViewer5;
19762
+ var _this$sceneViewer4;
19717
19763
  console.log("updateSegmentConnectorPositions started:", segment);
19718
- if (!segment || !((_this$sceneViewer5 = this.sceneViewer) !== null && _this$sceneViewer5 !== void 0 && (_this$sceneViewer5 = _this$sceneViewer5.currentSceneData) !== null && _this$sceneViewer5 !== void 0 && _this$sceneViewer5.scene)) {
19764
+ if (!segment || !((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && (_this$sceneViewer4 = _this$sceneViewer4.currentSceneData) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.scene)) {
19719
19765
  console.warn('âš ī¸ updateSegmentConnectorPositions(): Missing segment or scene data');
19720
19766
  return;
19721
19767
  }
@@ -19741,8 +19787,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19741
19787
 
19742
19788
  // First, find the segment in scene data
19743
19789
  var sceneDataSegment = this.sceneViewer.currentSceneData.scene.children.find(function (child) {
19744
- var _segment$userData3;
19745
- return child.uuid === segment.uuid || child.uuid === ((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.originalUuid);
19790
+ var _segment$userData4;
19791
+ return child.uuid === segment.uuid || child.uuid === ((_segment$userData4 = segment.userData) === null || _segment$userData4 === void 0 ? void 0 : _segment$userData4.originalUuid);
19746
19792
  });
19747
19793
  if (!sceneDataSegment) {
19748
19794
  console.warn("\u26A0\uFE0F Segment ".concat(segment.uuid, " not found in scene data"));
@@ -19762,8 +19808,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19762
19808
 
19763
19809
  // Find the connector in the segment's children array (not root scene.children)
19764
19810
  var sceneDataConnector = sceneDataSegment.children.find(function (child) {
19765
- var _connector$userData2;
19766
- return child.uuid === connector.uuid || child.uuid === ((_connector$userData2 = connector.userData) === null || _connector$userData2 === void 0 ? void 0 : _connector$userData2.originalUuid);
19811
+ var _connector$userData;
19812
+ return child.uuid === connector.uuid || child.uuid === ((_connector$userData = connector.userData) === null || _connector$userData === void 0 ? void 0 : _connector$userData.originalUuid);
19767
19813
  });
19768
19814
  if (sceneDataConnector && sceneDataConnector.userData) {
19769
19815
  // Update position as array [x, y, z] for pathfinder compatibility
@@ -19785,9 +19831,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19785
19831
  }, {
19786
19832
  key: "checkSegmentIntersection",
19787
19833
  value: function checkSegmentIntersection(segment) {
19788
- var _this$sceneViewer6,
19834
+ var _this$sceneViewer5,
19789
19835
  _this = this;
19790
- if (!((_this$sceneViewer6 = this.sceneViewer) !== null && _this$sceneViewer6 !== void 0 && _this$sceneViewer6.scene)) {
19836
+ if (!((_this$sceneViewer5 = this.sceneViewer) !== null && _this$sceneViewer5 !== void 0 && _this$sceneViewer5.scene)) {
19791
19837
  return false;
19792
19838
  }
19793
19839
 
@@ -19857,8 +19903,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19857
19903
  }, {
19858
19904
  key: "checkSegmentPathConnectorCollision",
19859
19905
  value: function checkSegmentPathConnectorCollision(segment) {
19860
- var _this$sceneViewer7;
19861
- if (!((_this$sceneViewer7 = this.sceneViewer) !== null && _this$sceneViewer7 !== void 0 && _this$sceneViewer7.scene) || !segment) {
19906
+ var _this$sceneViewer6;
19907
+ if (!((_this$sceneViewer6 = this.sceneViewer) !== null && _this$sceneViewer6 !== void 0 && _this$sceneViewer6.scene) || !segment) {
19862
19908
  return null;
19863
19909
  }
19864
19910
  var collisionRadius = 0.5; // Radius around connector that triggers collision
@@ -19972,8 +20018,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19972
20018
  }, {
19973
20019
  key: "checkComponentConnectorCollision",
19974
20020
  value: function checkComponentConnectorCollision(newPosition) {
19975
- var _this$sceneViewer8;
19976
- if (!((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene)) {
20021
+ var _this$sceneViewer7;
20022
+ if (!((_this$sceneViewer7 = this.sceneViewer) !== null && _this$sceneViewer7 !== void 0 && _this$sceneViewer7.scene)) {
19977
20023
  return null;
19978
20024
  }
19979
20025
  var tolerance = 0.01; // Small tolerance for floating-point comparison
@@ -20020,6 +20066,48 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20020
20066
  return collision;
20021
20067
  }
20022
20068
 
20069
+ /**
20070
+ * Check if a segment would collide with any component's bounding box
20071
+ * @param {THREE.Object3D} segment - The segment to check for collisions
20072
+ * @returns {Object|null} Collision info {componentId, componentName, componentType} if collision detected, null otherwise
20073
+ * @private
20074
+ */
20075
+ }, {
20076
+ key: "checkSegmentComponentBoundingBoxCollision",
20077
+ value: function checkSegmentComponentBoundingBoxCollision(segment) {
20078
+ var _this$sceneViewer8;
20079
+ if (!((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene) || !segment) {
20080
+ return null;
20081
+ }
20082
+
20083
+ // Create a bounding box for the segment
20084
+ var segmentBBox = new THREE__namespace.Box3().setFromObject(segment);
20085
+ var collision = null;
20086
+
20087
+ // Traverse scene to find all components
20088
+ this.sceneViewer.scene.traverse(function (child) {
20089
+ var _child$userData11, _child$userData12;
20090
+ if (collision) return; // Stop if collision already found
20091
+
20092
+ // Check if this is a component (equipment)
20093
+ if (((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType) === 'component' && (_child$userData12 = child.userData) !== null && _child$userData12 !== void 0 && _child$userData12.libraryId) {
20094
+ // Create bounding box for the component
20095
+ var componentBBox = new THREE__namespace.Box3().setFromObject(child);
20096
+
20097
+ // Check if bounding boxes intersect
20098
+ if (segmentBBox.intersectsBox(componentBBox)) {
20099
+ console.log('âš ī¸ TransformOperationsManager: Segment bounding box collision with component:', child.userData.libraryId || child.name || child.uuid);
20100
+ collision = {
20101
+ componentId: child.uuid,
20102
+ componentName: child.name || 'Unknown',
20103
+ componentType: child.userData.libraryId || 'Unknown'
20104
+ };
20105
+ }
20106
+ }
20107
+ });
20108
+ return collision;
20109
+ }
20110
+
20023
20111
  /**
20024
20112
  * Calculate the minimum distance between two line segments in 3D space
20025
20113
  * @param {THREE.Vector3} p1 - Start point of first segment
@@ -20140,8 +20228,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20140
20228
  // Get the moved segment's connectors
20141
20229
  var movedConnectors = [];
20142
20230
  movedSegment.traverse(function (child) {
20143
- var _child$userData11;
20144
- if (((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType) === 'segment-connector') {
20231
+ var _child$userData13;
20232
+ if (((_child$userData13 = child.userData) === null || _child$userData13 === void 0 ? void 0 : _child$userData13.objectType) === 'segment-connector') {
20145
20233
  movedConnectors.push(child);
20146
20234
  }
20147
20235
  });
@@ -20211,8 +20299,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20211
20299
  // Get all connectors of the adjacent segment
20212
20300
  var adjacentConnectors = [];
20213
20301
  adjacentSegment.traverse(function (child) {
20214
- var _child$userData12;
20215
- if (((_child$userData12 = child.userData) === null || _child$userData12 === void 0 ? void 0 : _child$userData12.objectType) === 'segment-connector') {
20302
+ var _child$userData14;
20303
+ if (((_child$userData14 = child.userData) === null || _child$userData14 === void 0 ? void 0 : _child$userData14.objectType) === 'segment-connector') {
20216
20304
  adjacentConnectors.push(child);
20217
20305
  }
20218
20306
  });
@@ -20540,8 +20628,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20540
20628
  // Remove segment from scene data
20541
20629
  if (currentSceneData.scene && currentSceneData.scene.children) {
20542
20630
  var segmentIndex = currentSceneData.scene.children.findIndex(function (child) {
20543
- var _segment$userData4;
20544
- return child.uuid === segment.uuid || child.uuid === ((_segment$userData4 = segment.userData) === null || _segment$userData4 === void 0 ? void 0 : _segment$userData4.originalUuid);
20631
+ var _segment$userData5;
20632
+ return child.uuid === segment.uuid || child.uuid === ((_segment$userData5 = segment.userData) === null || _segment$userData5 === void 0 ? void 0 : _segment$userData5.originalUuid);
20545
20633
  });
20546
20634
  if (segmentIndex !== -1) {
20547
20635
  currentSceneData.scene.children.splice(segmentIndex, 1);
@@ -20574,8 +20662,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20574
20662
  // Get the active segment's connectors
20575
20663
  var activeConnectors = [];
20576
20664
  activeSegment.traverse(function (child) {
20577
- var _child$userData13;
20578
- if (((_child$userData13 = child.userData) === null || _child$userData13 === void 0 ? void 0 : _child$userData13.objectType) === 'segment-connector') {
20665
+ var _child$userData15;
20666
+ if (((_child$userData15 = child.userData) === null || _child$userData15 === void 0 ? void 0 : _child$userData15.objectType) === 'segment-connector') {
20579
20667
  activeConnectors.push(child);
20580
20668
  }
20581
20669
  });
@@ -24092,21 +24180,12 @@ var KeyboardControlsManager = /*#__PURE__*/function () {
24092
24180
  return _createClass(KeyboardControlsManager, [{
24093
24181
  key: "setupKeyboardControls",
24094
24182
  value: function setupKeyboardControls() {
24095
- var _this = this;
24096
24183
  this.handleKeyDown = function (event) {
24097
24184
  // Sample Ctrl+Z example
24098
24185
  if (event.ctrlKey && (event.key.toLowerCase() === 'z' || event.code === 'KeyZ')) {
24099
24186
  // method call here
24100
24187
  return;
24101
24188
  }
24102
-
24103
- // Shift+D to split selected segment
24104
- if (event.shiftKey && (event.key.toLowerCase() === 'd' || event.code === 'KeyD')) {
24105
- _this.handleSegmentSplit();
24106
- event.preventDefault();
24107
- event.stopPropagation();
24108
- return;
24109
- }
24110
24189
  switch (event.key.toLowerCase()) {
24111
24190
  }
24112
24191
  };
@@ -24120,53 +24199,6 @@ var KeyboardControlsManager = /*#__PURE__*/function () {
24120
24199
  console.log('Keyboard controls initialized with Ctrl+Z undo override and Shift+D segment split');
24121
24200
  }
24122
24201
 
24123
- /**
24124
- * Handle segment split operation (Shift+D)
24125
- * Splits the currently selected segment in half if it's a pipe segment
24126
- */
24127
- }, {
24128
- key: "handleSegmentSplit",
24129
- value: function handleSegmentSplit() {
24130
- var sceneViewer = this.sceneViewer;
24131
-
24132
- // Check if transform controls are active with a selected object
24133
- if (!sceneViewer.transformManager || !sceneViewer.transformManager.selectedObjects || sceneViewer.transformManager.selectedObjects.length === 0) {
24134
- console.log('â„šī¸ No object selected for segment split');
24135
- return;
24136
- }
24137
- var selectedObject = sceneViewer.transformManager.selectedObjects[0];
24138
-
24139
- // Verify it's a segment
24140
- if (!selectedObject.userData || selectedObject.userData.objectType !== 'segment') {
24141
- console.log('â„šī¸ Selected object is not a segment, cannot split');
24142
- return;
24143
- }
24144
- console.log('âœ‚ī¸ Shift+D pressed - splitting segment:', selectedObject.uuid);
24145
-
24146
- // Access CentralPlant through sceneViewer
24147
- var centralPlant = sceneViewer.centralPlant;
24148
- if (!centralPlant || typeof centralPlant.splitSegment !== 'function') {
24149
- console.error('❌ CentralPlant or splitSegment method not available');
24150
- return;
24151
- }
24152
-
24153
- // Call the public API to split the segment
24154
- var result = centralPlant.splitSegment(selectedObject.uuid);
24155
- if (result) {
24156
- console.log('✅ Segment split successful:', result);
24157
-
24158
- // Deselect the original segment (now removed) and optionally select one of the new segments
24159
- sceneViewer.transformManager.deselectObject();
24160
-
24161
- // Optionally select the first new segment
24162
- if (result.segment1) {
24163
- sceneViewer.transformManager.selectObject(result.segment1);
24164
- }
24165
- } else {
24166
- console.error('❌ Segment split failed');
24167
- }
24168
- }
24169
-
24170
24202
  /**
24171
24203
  * Toggle auto-rotation of the camera
24172
24204
  */
@@ -24933,10 +24965,23 @@ var SceneDataManager = /*#__PURE__*/function () {
24933
24965
  worldBoundingBox: worldBoundingBox
24934
24966
  })
24935
24967
  };
24968
+
24969
+ // For connectors and gateways, add world position
24936
24970
  if (obj.userData.objectType.includes('connector') || obj.userData.objectType === 'gateway') {
24937
24971
  var worldPosition = new THREE__namespace.Vector3();
24938
24972
  obj.getWorldPosition(worldPosition);
24939
24973
  results.userData.position = [worldPosition.x, worldPosition.y, worldPosition.z];
24974
+
24975
+ // Differentiate component connectors from segment connectors for pathfinder
24976
+ // Component connectors are children of components
24977
+ if (obj.userData.objectType === 'connector') {
24978
+ var _parent$userData;
24979
+ // Check if parent is a component (not a segment)
24980
+ var parent = obj.parent;
24981
+ if (parent && ((_parent$userData = parent.userData) === null || _parent$userData === void 0 ? void 0 : _parent$userData.objectType) === 'component') {
24982
+ results.userData.objectType = 'component-connector';
24983
+ }
24984
+ }
24940
24985
  }
24941
24986
  return results;
24942
24987
  });
@@ -25263,6 +25308,15 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
25263
25308
  }
25264
25309
  });
25265
25310
 
25311
+ // Check if endpoints are component connectors (from pathfinder result)
25312
+ var fromIsComponentConnector = pathData.fromObjectType === 'component-connector';
25313
+ var toIsComponentConnector = pathData.toObjectType === 'component-connector';
25314
+
25315
+ // Check if endpoints have direction constraints (more accurate for immutability)
25316
+ // Segments adjacent to connectors with direction should be immutable
25317
+ var fromHasDirection = pathData.fromHasDirection !== undefined ? pathData.fromHasDirection : fromIsComponentConnector;
25318
+ var toHasDirection = pathData.toHasDirection !== undefined ? pathData.toHasDirection : toIsComponentConnector;
25319
+
25266
25320
  // Create one cylinder per segment (after colinear optimization, this should be minimal segments)
25267
25321
  for (var j = 0; j < pathPoints.length - 1; j++) {
25268
25322
  var start = pathPoints[j];
@@ -25291,13 +25345,21 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
25291
25345
  // Make pipe segments selectable and add identifying data
25292
25346
  var segmentId = cylinder.uuid;
25293
25347
 
25348
+ // Determine if this segment should be immutable (first or last segment connected to connector with direction)
25349
+ // Segments adjacent to connectors with direction constraints are immutable (cannot be edited)
25350
+ // Segments adjacent to gateways (no direction) can be edited
25351
+ var isFirstSegment = j === 0;
25352
+ var isLastSegment = j === pathPoints.length - 2;
25353
+ var isImmutable = fromHasDirection && isFirstSegment || toHasDirection && isLastSegment;
25354
+
25294
25355
  // Add userData to make pipe segments selectable and for tooltip display
25295
25356
  cylinder.userData = {
25296
25357
  objectType: 'segment',
25297
25358
  segmentId: segmentId,
25298
25359
  segmentIndex: globalSegmentIndex,
25299
25360
  pathFrom: pathData.from,
25300
- pathTo: pathData.to
25361
+ pathTo: pathData.to,
25362
+ immutable: isImmutable // Mark segments connected to component connectors as immutable
25301
25363
  };
25302
25364
 
25303
25365
  // Increment global segment counter
@@ -25310,7 +25372,6 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
25310
25372
  _this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, sceneViewer.scene // Pass scene instead of polyline
25311
25373
  );
25312
25374
  }
25313
- console.log("\u2705 Created pipe path ".concat(pathData.from, "-").concat(pathData.to, " with ").concat(pathPoints.length - 1, " segments"));
25314
25375
  }
25315
25376
  });
25316
25377
  }
@@ -25362,6 +25423,8 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
25362
25423
  pathFrom: pathData.from,
25363
25424
  pathTo: pathData.to,
25364
25425
  angle: (angle * 180 / Math.PI).toFixed(1),
25426
+ immutable: true,
25427
+ // Mark computed elbows as immutable
25365
25428
  // Add component data for tooltips
25366
25429
  component: {
25367
25430
  type: 'PipeElbow',
@@ -25658,7 +25721,8 @@ var ConnectorManager = /*#__PURE__*/function (_BaseDisposable) {
25658
25721
 
25659
25722
  /**
25660
25723
  * Restructure connections to use the new connectors
25661
- * @param {string} authoritativeConnectorUUID - The authoritative connector UUID
25724
+ * Measures distance from point-a to both connectors and connects to the nearest one
25725
+ * @param {string} authoritativeConnectorUUID - The authoritative connector UUID (point-a)
25662
25726
  * @param {Array} connectors - Array of connector objects (0: start, 1: end)
25663
25727
  * @param {Object} currentSceneData - Current scene data
25664
25728
  * @param {Array<string>} convertedGatewayUUIDs - Array of gateway UUIDs that were converted to manual (optional)
@@ -25673,6 +25737,66 @@ var ConnectorManager = /*#__PURE__*/function (_BaseDisposable) {
25673
25737
 
25674
25738
  console.log("\uD83D\uDD27 [restructureConnections] connectors:", JSON.parse(JSON.stringify(connectors)));
25675
25739
  console.log("\uD83D\uDD27 [restructureConnections] convertedGatewayUUIDs:", convertedGatewayUUIDs);
25740
+ console.log("\uD83D\uDD27 [restructureConnections] authoritativeConnectorUUID:", authoritativeConnectorUUID);
25741
+
25742
+ // Find the authoritative connector object (point-a) in the scene to measure distances
25743
+ var authoritativeObject = null;
25744
+ this.sceneViewer.scene.traverse(function (obj) {
25745
+ if (obj.uuid === authoritativeConnectorUUID) {
25746
+ authoritativeObject = obj;
25747
+ }
25748
+ });
25749
+ if (!authoritativeObject) {
25750
+ console.error("\u274C [restructureConnections] Could not find authoritative connector: ".concat(authoritativeConnectorUUID));
25751
+ console.error("\u274C [restructureConnections] This may indicate:");
25752
+ console.error(" 1. The connector UUID changed during gateway manualization");
25753
+ console.error(" 2. The original connection was removed/modified before restructuring");
25754
+ console.error(" 3. The findOriginalConnection method returned a stale connection");
25755
+ console.error("\u274C [restructureConnections] Current connections:", JSON.stringify(currentSceneData.connections, null, 2));
25756
+
25757
+ // FALLBACK: Try to find any connector that might be the authoritative one
25758
+ // Look for objects with similar UUID patterns or check the original connection endpoints
25759
+ console.warn("\u26A0\uFE0F [restructureConnections] Attempting fallback connector search...");
25760
+
25761
+ // Search for possible matches (component connectors, gateway connectors, etc.)
25762
+ var possibleMatches = [];
25763
+ this.sceneViewer.scene.traverse(function (obj) {
25764
+ var _obj$userData, _obj$userData2, _obj$userData3;
25765
+ if (((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType) === 'connector' || ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.objectType) === 'segment-connector' || ((_obj$userData3 = obj.userData) === null || _obj$userData3 === void 0 ? void 0 : _obj$userData3.objectType) === 'gateway-connector') {
25766
+ possibleMatches.push({
25767
+ uuid: obj.uuid,
25768
+ objectType: obj.userData.objectType,
25769
+ isDeclared: obj.userData.isDeclared
25770
+ });
25771
+ }
25772
+ });
25773
+ console.warn("\u26A0\uFE0F [restructureConnections] Found ".concat(possibleMatches.length, " possible connectors:"), possibleMatches);
25774
+ console.error("\u274C [restructureConnections] Cannot proceed without authoritative connector");
25775
+ return;
25776
+ }
25777
+
25778
+ // Get world positions for distance calculation
25779
+ var pointA = new THREE__namespace.Vector3();
25780
+ authoritativeObject.getWorldPosition(pointA);
25781
+ var connector1Position = new THREE__namespace.Vector3();
25782
+ var connector2Position = new THREE__namespace.Vector3();
25783
+ connectors[0].getWorldPosition(connector1Position);
25784
+ connectors[1].getWorldPosition(connector2Position);
25785
+
25786
+ // Calculate distances from point-a to both segment connectors
25787
+ var distanceToConnector1 = pointA.distanceTo(connector1Position);
25788
+ var distanceToConnector2 = pointA.distanceTo(connector2Position);
25789
+ console.log("\uD83D\uDCCF [restructureConnections] Distance from ".concat(authoritativeConnectorUUID, " to:"));
25790
+ console.log(" - ".concat(startConnectorUUID, ": ").concat(distanceToConnector1.toFixed(4)));
25791
+ console.log(" - ".concat(endConnectorUUID, ": ").concat(distanceToConnector2.toFixed(4)));
25792
+
25793
+ // Determine which connector is nearest to point-a
25794
+ var nearestConnector = distanceToConnector1 <= distanceToConnector2 ? connectors[0] : connectors[1];
25795
+ var farthestConnector = distanceToConnector1 > distanceToConnector2 ? connectors[0] : connectors[1];
25796
+ var nearestConnectorUUID = nearestConnector.uuid;
25797
+ var farthestConnectorUUID = farthestConnector.uuid;
25798
+ console.log("\u2705 [restructureConnections] Nearest connector: ".concat(nearestConnectorUUID, " (distance: ").concat(Math.min(distanceToConnector1, distanceToConnector2).toFixed(4), ")"));
25799
+ console.log("\uD83D\uDCCD [restructureConnections] Farthest connector: ".concat(farthestConnectorUUID, " (distance: ").concat(Math.max(distanceToConnector1, distanceToConnector2).toFixed(4), ")"));
25676
25800
 
25677
25801
  // Deep copy connections array to prevent unintended mutations during iteration
25678
25802
  // Then map to update references, creating new connection objects
@@ -25681,30 +25805,32 @@ var ConnectorManager = /*#__PURE__*/function (_BaseDisposable) {
25681
25805
 
25682
25806
  // Create a shallow copy of the connection object
25683
25807
  var updatedConnection = _objectSpread2({}, connection);
25808
+
25809
+ // Update connections to point to the FARTHEST connector (opposite end from point-a)
25684
25810
  if (connection.from === authoritativeConnectorUUID) {
25685
- updatedConnection.from = endConnectorUUID;
25686
- console.log("\u2705 [restructureConnections] Updated connection.from to ".concat(endConnectorUUID));
25811
+ updatedConnection.from = farthestConnectorUUID;
25812
+ console.log("\u2705 [restructureConnections] Updated connection.from to ".concat(farthestConnectorUUID, " (farthest)"));
25687
25813
  }
25688
25814
  if (connection.to === authoritativeConnectorUUID) {
25689
- updatedConnection.to = endConnectorUUID;
25690
- console.log("\u2705 [restructureConnections] Updated connection.to to ".concat(endConnectorUUID));
25815
+ updatedConnection.to = farthestConnectorUUID;
25816
+ console.log("\u2705 [restructureConnections] Updated connection.to to ".concat(farthestConnectorUUID, " (farthest)"));
25691
25817
  }
25692
25818
  return updatedConnection;
25693
25819
  });
25694
25820
 
25695
25821
  // Check if the new connection already exists to prevent duplicates
25696
25822
  var newConnectionExists = currentSceneData.connections.some(function (conn) {
25697
- return conn.from === authoritativeConnectorUUID && conn.to === startConnectorUUID || conn.from === startConnectorUUID && conn.to === authoritativeConnectorUUID;
25823
+ return conn.from === authoritativeConnectorUUID && conn.to === nearestConnectorUUID || conn.from === nearestConnectorUUID && conn.to === authoritativeConnectorUUID;
25698
25824
  });
25699
25825
  if (!newConnectionExists) {
25700
- // Add new connection from authoritative connector to the segment start
25826
+ // Add new connection from authoritative connector (point-a) to the NEAREST segment connector
25701
25827
  currentSceneData.connections.push({
25702
25828
  from: authoritativeConnectorUUID,
25703
- to: startConnectorUUID
25829
+ to: nearestConnectorUUID
25704
25830
  });
25705
- console.log("\u2705 [restructureConnections] Added new connection: ".concat(authoritativeConnectorUUID, " \u2192 ").concat(startConnectorUUID));
25831
+ console.log("\u2705 [restructureConnections] Added new connection: ".concat(authoritativeConnectorUUID, " \u2192 ").concat(nearestConnectorUUID, " (nearest)"));
25706
25832
  } else {
25707
- console.log("\u26A0\uFE0F [restructureConnections] Connection already exists, skipping: ".concat(authoritativeConnectorUUID, " \u2192 ").concat(startConnectorUUID));
25833
+ console.log("\u26A0\uFE0F [restructureConnections] Connection already exists, skipping: ".concat(authoritativeConnectorUUID, " \u2192 ").concat(nearestConnectorUUID));
25708
25834
  }
25709
25835
 
25710
25836
  // Log converted gateways for tracking
@@ -25751,11 +25877,11 @@ var ConnectorManager = /*#__PURE__*/function (_BaseDisposable) {
25751
25877
  var fromObject = null;
25752
25878
  var toObject = null;
25753
25879
  sceneViewer.scene.traverse(function (obj) {
25754
- var _obj$userData, _obj$userData2;
25755
- if (obj.uuid === pathFrom || ((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.originalUuid) === pathFrom) {
25880
+ var _obj$userData4, _obj$userData5;
25881
+ if (obj.uuid === pathFrom || ((_obj$userData4 = obj.userData) === null || _obj$userData4 === void 0 ? void 0 : _obj$userData4.originalUuid) === pathFrom) {
25756
25882
  fromObject = obj;
25757
25883
  }
25758
- if (obj.uuid === pathTo || ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.originalUuid) === pathTo) {
25884
+ if (obj.uuid === pathTo || ((_obj$userData5 = obj.userData) === null || _obj$userData5 === void 0 ? void 0 : _obj$userData5.originalUuid) === pathTo) {
25759
25885
  toObject = obj;
25760
25886
  }
25761
25887
  });
@@ -29379,7 +29505,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
29379
29505
  }, {
29380
29506
  key: "manualizeSegment",
29381
29507
  value: function manualizeSegment(segment, currentSceneData) {
29382
- var _segment$userData, _this$sceneViewer$man;
29508
+ var _segment$userData, _segment$material$use, _this$sceneViewer$man;
29383
29509
  if (!segment || !((_segment$userData = segment.userData) !== null && _segment$userData !== void 0 && _segment$userData.objectType) === 'segment') {
29384
29510
  console.log('❌ Object is not a pipe segment:', {
29385
29511
  isObject: !!segment,
@@ -29396,6 +29522,16 @@ var SceneOperationsManager = /*#__PURE__*/function () {
29396
29522
  return;
29397
29523
  }
29398
29524
 
29525
+ // CRITICAL: Clone the material BEFORE changing its color
29526
+ // This prevents the color change from affecting other segments that share the same material instance
29527
+ if (segment.material && !((_segment$material$use = segment.material.userData) !== null && _segment$material$use !== void 0 && _segment$material$use.isCloned)) {
29528
+ var originalMaterial = segment.material;
29529
+ segment.material = originalMaterial.clone();
29530
+ segment.material.userData = segment.material.userData || {};
29531
+ segment.material.userData.isCloned = true;
29532
+ console.log('📋 Cloned segment material to prevent shared material mutation');
29533
+ }
29534
+
29399
29535
  // Override material color to blue in dev mode
29400
29536
  var isDev = false;
29401
29537
  if (typeof window !== 'undefined') {
@@ -29420,7 +29556,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
29420
29556
  // Change from "SEGMENT-X" to "Segment-X" (capital S to lowercase s)
29421
29557
  var segmentIndex = segment.userData.segmentIndex;
29422
29558
  var oldUuid = segment.uuid;
29423
- segment.uuid = "Segment-".concat(segmentIndex);
29559
+ segment.uuid = "SEGMENT-".concat(segmentIndex);
29424
29560
  console.log("\uD83D\uDD27 Renamed segment UUID from ".concat(oldUuid, " to: ").concat(segment.uuid));
29425
29561
 
29426
29562
  // Calculate segment endpoints in world coordinates
@@ -29455,20 +29591,29 @@ var SceneOperationsManager = /*#__PURE__*/function () {
29455
29591
  // Now add connectors to the segment's children array in scene data
29456
29592
  connectorManager.addConnectorsToScene(connectors);
29457
29593
 
29458
- // Find the original connection that this segment belongs to (after gateways are converted)
29594
+ // Check and convert connected gateways to manual (declared) FIRST
29595
+ // CRITICAL: This must happen BEFORE finding the authoritative connector
29596
+ // because gateway conversion may modify the connections array
29597
+ // NOTE: This may trigger path regeneration via translateGateway, so segment must already be renamed
29598
+ var convertedGatewayUUIDs = this._convertConnectedGatewaysToManual(connectors, currentSceneData);
29599
+ console.log('🔍 Gateway conversion completed, now finding authoritative connector with updated connections');
29600
+
29601
+ // Find the original connection that this segment belongs to (AFTER gateways are converted)
29602
+ // IMPORTANT: This must run after gateway conversion because connections may have changed
29459
29603
  var originalConnection = connectorManager.findOriginalConnection(segment, currentSceneData.connections);
29460
29604
  if (!originalConnection) {
29461
29605
  console.warn('âš ī¸ Could not find original connection for segment:', segment.uuid);
29606
+ console.warn('âš ī¸ This may indicate the connection was modified during gateway conversion');
29607
+ console.warn('âš ī¸ Available connections:', JSON.stringify(currentSceneData.connections, null, 2));
29462
29608
  return;
29463
29609
  }
29464
- console.log('🔍 Found original connection:', originalConnection);
29610
+ console.log('🔍 Found original connection (after gateway conversion):', originalConnection);
29611
+
29612
+ // Determine the authoritative connector (the non-gateway endpoint)
29613
+ // After gateway conversion, gateways should have connectors, so check for "Gateway" pattern
29465
29614
  var authoritativeConnectorUUID = originalConnection.from.includes("Gateway") === false ? originalConnection.from : originalConnection.to;
29466
29615
  console.log('[SceneOperations] authoritativeConnectorUUID:', authoritativeConnectorUUID);
29467
29616
 
29468
- // Check and convert connected gateways to manual (declared)
29469
- // NOTE: This may trigger path regeneration via translateGateway, so segment must already be renamed
29470
- var convertedGatewayUUIDs = this._convertConnectedGatewaysToManual(connectors, currentSceneData);
29471
-
29472
29617
  // Restructure connections, passing any converted gateway UUIDs
29473
29618
  connectorManager.restructureConnections(authoritativeConnectorUUID, connectors, currentSceneData, convertedGatewayUUIDs);
29474
29619
 
@@ -29677,147 +29822,6 @@ var SceneOperationsManager = /*#__PURE__*/function () {
29677
29822
  }
29678
29823
  console.log("\u2705 Gateway ".concat(gateway.uuid, " successfully converted to manual (declared)"));
29679
29824
  }
29680
-
29681
- /**
29682
- * Split a segment by manualizing it and shortening it by 0.5 units
29683
- * The segment gets converted to a declared (manual) segment with connectors,
29684
- * and is shortened from the end that has a component connector (or the end if no connectors)
29685
- * @param {string|THREE.Object3D} segmentIdOrObject - The UUID or Three.js object of the segment to split
29686
- * @param {Object} currentSceneData - Current scene data with connections
29687
- * @returns {THREE.Object3D|null} The shortened manual segment or null on failure
29688
- */
29689
- }, {
29690
- key: "splitSegment",
29691
- value: function splitSegment(segmentIdOrObject, currentSceneData) {
29692
- var _segment$userData3,
29693
- _this6 = this;
29694
- console.log('âœ‚ī¸ splitSegment started:', segmentIdOrObject);
29695
-
29696
- // Find the segment object
29697
- var segment = null;
29698
- if (typeof segmentIdOrObject === 'string') {
29699
- this.sceneViewer.scene.traverse(function (child) {
29700
- var _child$userData10;
29701
- if (child.uuid === segmentIdOrObject || ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.originalUuid) === segmentIdOrObject) {
29702
- segment = child;
29703
- }
29704
- });
29705
- } else if (segmentIdOrObject && segmentIdOrObject.isObject3D) {
29706
- segment = segmentIdOrObject;
29707
- }
29708
-
29709
- // Validate segment
29710
- if (!segment || ((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.objectType) !== 'segment') {
29711
- console.error('❌ splitSegment(): Invalid segment or not found');
29712
- return null;
29713
- }
29714
- if (!currentSceneData) {
29715
- console.error('❌ splitSegment(): currentSceneData is required');
29716
- return null;
29717
- }
29718
- console.log('âœ‚ī¸ Splitting/shortening segment:', segment.uuid);
29719
-
29720
- // Get segment geometry to calculate endpoints
29721
- var geometry = segment.geometry;
29722
- if (!geometry || !geometry.parameters) {
29723
- console.error('❌ splitSegment(): Segment has invalid geometry');
29724
- return null;
29725
- }
29726
- var segmentLength = geometry.parameters.height || 1;
29727
- var segmentRadius = geometry.parameters.radiusTop || 0.1;
29728
- var shortenAmount = 0.5;
29729
- var newLength = segmentLength - shortenAmount;
29730
- if (newLength <= 0) {
29731
- console.error('❌ splitSegment(): Segment too short to shorten by 0.5');
29732
- return null;
29733
- }
29734
-
29735
- // Calculate segment direction vector
29736
- var direction = new THREE__namespace.Vector3(0, 1, 0);
29737
- direction.applyQuaternion(segment.quaternion);
29738
- direction.normalize();
29739
-
29740
- // Calculate original segment endpoints
29741
- var startPoint = new THREE__namespace.Vector3();
29742
- startPoint.copy(segment.position).sub(direction.clone().multiplyScalar(segmentLength / 2));
29743
- var endPoint = new THREE__namespace.Vector3();
29744
- endPoint.copy(segment.position).add(direction.clone().multiplyScalar(segmentLength / 2));
29745
-
29746
- // Check for component connectors at endpoints
29747
- var findConnectorsAtPosition = function findConnectorsAtPosition(position) {
29748
- var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.15;
29749
- var connectors = [];
29750
- _this6.sceneViewer.scene.traverse(function (child) {
29751
- var _child$userData11;
29752
- if (((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType) === 'connector') {
29753
- var connectorWorldPos = new THREE__namespace.Vector3();
29754
- child.getWorldPosition(connectorWorldPos);
29755
- var distance = connectorWorldPos.distanceTo(position);
29756
- if (distance <= tolerance) {
29757
- connectors.push(child);
29758
- }
29759
- }
29760
- });
29761
- return connectors.filter(function (c) {
29762
- var _c$userData;
29763
- return ((_c$userData = c.userData) === null || _c$userData === void 0 ? void 0 : _c$userData.objectType) !== 'segment-connector';
29764
- });
29765
- };
29766
- var startConnectors = findConnectorsAtPosition(startPoint);
29767
- var endConnectors = findConnectorsAtPosition(endPoint);
29768
-
29769
- // Determine which end to shorten from
29770
- var newStartPoint, newEndPoint;
29771
- if (endConnectors.length > 0) {
29772
- // Component connector at end - shorten from end
29773
- newStartPoint = startPoint.clone();
29774
- newEndPoint = endPoint.clone().sub(direction.clone().multiplyScalar(shortenAmount));
29775
- console.log("\uD83D\uDCCD Component connector at END - shortening from end by ".concat(shortenAmount));
29776
- } else if (startConnectors.length > 0) {
29777
- // Component connector at start - shorten from start
29778
- newStartPoint = startPoint.clone().add(direction.clone().multiplyScalar(shortenAmount));
29779
- newEndPoint = endPoint.clone();
29780
- console.log("\uD83D\uDCCD Component connector at START - shortening from start by ".concat(shortenAmount));
29781
- } else {
29782
- // No component connectors - shorten from end (default)
29783
- newStartPoint = startPoint.clone();
29784
- newEndPoint = endPoint.clone().sub(direction.clone().multiplyScalar(shortenAmount));
29785
- console.log("\uD83D\uDCCD No component connectors - shortening from end by ".concat(shortenAmount));
29786
- }
29787
- console.log('📍 Segment shortening:', {
29788
- originalStart: startPoint.toArray(),
29789
- originalEnd: endPoint.toArray(),
29790
- newStart: newStartPoint.toArray(),
29791
- newEnd: newEndPoint.toArray(),
29792
- originalLength: segmentLength,
29793
- newLength: newLength,
29794
- shortenAmount: shortenAmount
29795
- });
29796
-
29797
- // Get material from existing segment
29798
- segment.material;
29799
-
29800
- // Dispose old geometry and create new shortened geometry
29801
- if (segment.geometry) {
29802
- segment.geometry.dispose();
29803
- }
29804
- var newGeometry = new THREE__namespace.CylinderGeometry(segmentRadius, segmentRadius, newLength, 16, 1, false);
29805
- segment.geometry = newGeometry;
29806
-
29807
- // Reposition the segment to the new center
29808
- var newPosition = new THREE__namespace.Vector3();
29809
- newPosition.lerpVectors(newStartPoint, newEndPoint, 0.5);
29810
- segment.position.copy(newPosition);
29811
- // Quaternion stays the same
29812
-
29813
- console.log('✅ Segment geometry updated and repositioned');
29814
-
29815
- // Now manualize the shortened segment
29816
- console.log('🔧 Manualizing the shortened segment...');
29817
- this.manualizeSegment(segment, currentSceneData);
29818
- console.log('✅ Segment split completed successfully - segment shortened and manualized');
29819
- return segment;
29820
- }
29821
29825
  }]);
29822
29826
  }();
29823
29827
 
@@ -33761,7 +33765,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
33761
33765
  * Initialize the CentralPlant manager
33762
33766
  *
33763
33767
  * @constructor
33764
- * @version 0.1.50
33768
+ * @version 0.1.52
33765
33769
  * @updated 2025-10-22
33766
33770
  *
33767
33771
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -34066,51 +34070,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
34066
34070
  return this.internals.translateGateway(gatewayId, axis, value);
34067
34071
  }
34068
34072
 
34069
- /**
34070
- * Split a pipe segment by shortening it by 0.5 units and manualizing it
34071
- * @param {string} segmentId - The UUID of the segment to split
34072
- * @returns {THREE.Object3D|null} The shortened manual segment or null on failure
34073
- * @description Shortens a selected pipe segment by 0.5 units and converts it to
34074
- * manual/declared status with connectors. The segment is shortened from the end that
34075
- * has a component connector (or from the end if no connectors are present).
34076
- * The segment becomes transformable after this operation. Paths are regenerated
34077
- * to ensure proper connections.
34078
- * @example
34079
- * // Split/shorten a segment when selected via transform controls
34080
- * const result = centralPlant.splitSegment('SEGMENT-12345');
34081
- * if (result) {
34082
- * console.log('Segment shortened and manualized:', result.uuid);
34083
- * }
34084
- *
34085
- * @since 0.1.37
34086
- */
34087
- }, {
34088
- key: "splitSegment",
34089
- value: function splitSegment(segmentId) {
34090
- var _this$sceneViewer$man;
34091
- if (!this.sceneViewer || !((_this$sceneViewer$man = this.sceneViewer.managers) !== null && _this$sceneViewer$man !== void 0 && _this$sceneViewer$man.sceneOperationsManager)) {
34092
- console.warn('âš ī¸ splitSegment(): Scene viewer or scene operations manager not available');
34093
- return null;
34094
- }
34095
- if (!segmentId) {
34096
- console.error('❌ splitSegment(): No segment ID provided');
34097
- return null;
34098
- }
34099
- try {
34100
- var result = this.sceneViewer.managers.sceneOperationsManager.splitSegment(segmentId, this.sceneViewer.currentSceneData);
34101
- if (result) {
34102
- console.log('✅ splitSegment(): Segment split successfully');
34103
- return result;
34104
- } else {
34105
- console.warn('âš ī¸ splitSegment(): Split operation returned null');
34106
- return null;
34107
- }
34108
- } catch (error) {
34109
- console.error('❌ splitSegment(): Error splitting segment:', error);
34110
- return null;
34111
- }
34112
- }
34113
-
34114
34073
  /**
34115
34074
  * Rotate a component by componentId
34116
34075
  * @param {string} componentId - The UUID of the component to rotate
@@ -35392,8 +35351,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
35392
35351
  }, {
35393
35352
  key: "generatePath",
35394
35353
  value: function generatePath(fromConnectorId, toConnectorId) {
35395
- var _this$sceneViewer$man2;
35396
- if (!this.sceneViewer || !((_this$sceneViewer$man2 = this.sceneViewer.managers) !== null && _this$sceneViewer$man2 !== void 0 && _this$sceneViewer$man2.pathfinding)) {
35354
+ var _this$sceneViewer$man;
35355
+ if (!this.sceneViewer || !((_this$sceneViewer$man = this.sceneViewer.managers) !== null && _this$sceneViewer$man !== void 0 && _this$sceneViewer$man.pathfinding)) {
35397
35356
  return null;
35398
35357
  }
35399
35358
  try {