@2112-lab/central-plant 0.1.74 → 0.1.76

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.
@@ -3491,7 +3491,8 @@ var TransformControlsManager = /*#__PURE__*/function () {
3491
3491
  onTransform: null,
3492
3492
  onTransformEnd: null,
3493
3493
  onModeChange: null,
3494
- onObjectRemoved: null
3494
+ onObjectRemoved: null,
3495
+ onSelectionChanged: null
3495
3496
  };
3496
3497
  this.init();
3497
3498
  }
@@ -3566,6 +3567,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
3566
3567
  if (callbacks.onObjectRemoved) {
3567
3568
  this.callbacks.onObjectRemoved = callbacks.onObjectRemoved;
3568
3569
  }
3570
+ if (callbacks.onSelectionChanged) {
3571
+ this.callbacks.onSelectionChanged = callbacks.onSelectionChanged;
3572
+ }
3569
3573
  console.log('🔗 Transform controls callbacks registered');
3570
3574
  }
3571
3575
  /**
@@ -4135,6 +4139,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
4135
4139
  if (this.callbacks.onObjectSelect) {
4136
4140
  this.callbacks.onObjectSelect(object);
4137
4141
  }
4142
+
4143
+ // Trigger explicit selection change callback
4144
+ if (this.callbacks.onSelectionChanged) {
4145
+ this.callbacks.onSelectionChanged(object);
4146
+ }
4138
4147
  console.log("\uD83C\uDFAF Object selected: ".concat(object.name || object.uuid));
4139
4148
  return true;
4140
4149
  }
@@ -4158,9 +4167,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
4158
4167
  // Update the multi-selection display (works for single object too)
4159
4168
  this.updateMultiSelection();
4160
4169
 
4161
- // NOTE: We deliberately do NOT call any callback here
4162
- // This allows transform controls and bounding box to show without triggering tooltips
4163
-
4170
+ // NOTE: We deliberately do NOT call onObjectSelect here to avoid tooltips
4171
+ // But we DO call onSelectionChanged to sync UI
4172
+ if (this.callbacks.onSelectionChanged) {
4173
+ this.callbacks.onSelectionChanged(object);
4174
+ }
4164
4175
  console.log("\uD83C\uDFAF Object selected for transform only: ".concat(object.name || object.uuid));
4165
4176
  return true;
4166
4177
  }
@@ -4364,6 +4375,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
4364
4375
  if (this.callbacks.onObjectSelect) {
4365
4376
  this.callbacks.onObjectSelect(null);
4366
4377
  }
4378
+
4379
+ // Trigger explicit selection change callback
4380
+ if (this.callbacks.onSelectionChanged) {
4381
+ this.callbacks.onSelectionChanged(null);
4382
+ }
4367
4383
  }
4368
4384
 
4369
4385
  /**
@@ -18480,6 +18496,14 @@ var ComponentManager = /*#__PURE__*/function () {
18480
18496
  try {
18481
18497
  // Use the new utility function to find objects by hardcoded UUID
18482
18498
  var object = findObjectByHardcodedUuid(this.sceneViewer.scene, componentUuid);
18499
+
18500
+ // Fallback: If not found by utility, try direct UUID or name lookup
18501
+ if (!object) {
18502
+ object = this.sceneViewer.scene.getObjectByProperty('uuid', componentUuid);
18503
+ }
18504
+ if (!object) {
18505
+ object = this.sceneViewer.scene.getObjectByProperty('name', componentUuid);
18506
+ }
18483
18507
  if (!object) {
18484
18508
  console.warn('⚠️ Component not found:', componentUuid);
18485
18509
  return false;
@@ -19512,7 +19536,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19512
19536
  var component = null;
19513
19537
  this.sceneViewer.scene.traverse(function (child) {
19514
19538
  var _child$userData;
19515
- if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId) {
19539
+ if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId || child.name === componentId) {
19516
19540
  component = child;
19517
19541
  }
19518
19542
  });
@@ -19978,7 +20002,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19978
20002
  var gateway = null;
19979
20003
  this.sceneViewer.scene.traverse(function (child) {
19980
20004
  var _child$userData3;
19981
- if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId) {
20005
+ if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId || child.name === gatewayId) {
19982
20006
  gateway = child;
19983
20007
  }
19984
20008
  });
@@ -20075,7 +20099,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20075
20099
  var component = null;
20076
20100
  this.sceneViewer.scene.traverse(function (child) {
20077
20101
  var _child$userData4;
20078
- if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId) {
20102
+ if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId || child.name === componentId) {
20079
20103
  component = child;
20080
20104
  }
20081
20105
  });
@@ -20111,6 +20135,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20111
20135
  component.updateMatrix();
20112
20136
  component.updateMatrixWorld(true);
20113
20137
 
20138
+ // Update component rotation and connector positions in scene data
20139
+ this.updateComponentRotationInSceneData(component);
20140
+
20114
20141
  // Auto-update paths if enabled (matches behavior of translateComponent)
20115
20142
  if (this.sceneViewer.shouldUpdatePaths) {
20116
20143
  try {
@@ -21410,6 +21437,69 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21410
21437
  }
21411
21438
  }
21412
21439
 
21440
+ /**
21441
+ * Update component rotation and child connectors in currentSceneData after rotation
21442
+ * @param {THREE.Object3D} component - The component that was rotated
21443
+ * @private
21444
+ */
21445
+ }, {
21446
+ key: "updateComponentRotationInSceneData",
21447
+ value: function updateComponentRotationInSceneData(component) {
21448
+ var _this$sceneViewer12;
21449
+ if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
21450
+ console.warn('⚠️ Cannot update component rotation: currentSceneData not available');
21451
+ return;
21452
+ }
21453
+ var cleanValue = function cleanValue(value) {
21454
+ return Math.abs(value) < 1e-10 ? 0 : value;
21455
+ };
21456
+
21457
+ // Find the component in scene data
21458
+ // Use the same logic as other methods to match by UUID or originalUuid
21459
+ var sceneDataComponent = this.sceneViewer.currentSceneData.scene.children.find(function (child) {
21460
+ var _component$userData6;
21461
+ return child.uuid === component.uuid || child.uuid === ((_component$userData6 = component.userData) === null || _component$userData6 === void 0 ? void 0 : _component$userData6.originalUuid);
21462
+ });
21463
+ if (sceneDataComponent) {
21464
+ // Update rotation
21465
+ if (!sceneDataComponent.rotation) {
21466
+ sceneDataComponent.rotation = {};
21467
+ }
21468
+ sceneDataComponent.rotation.x = cleanValue(component.rotation.x);
21469
+ sceneDataComponent.rotation.y = cleanValue(component.rotation.y);
21470
+ sceneDataComponent.rotation.z = cleanValue(component.rotation.z);
21471
+ console.log("\u2705 Updated component ".concat(component.uuid, " rotation in scene data"));
21472
+
21473
+ // Also update child connectors' positions if they exist (rotation moves them in world space)
21474
+ if (sceneDataComponent.children) {
21475
+ sceneDataComponent.children.forEach(function (child) {
21476
+ var _child$userData24;
21477
+ if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'connector') {
21478
+ // Find the actual connector object in the scene
21479
+ var connectorObj = component.children.find(function (c) {
21480
+ var _c$userData2;
21481
+ return c.uuid === child.uuid || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === child.uuid;
21482
+ });
21483
+ if (connectorObj) {
21484
+ // Get world position of connector
21485
+ var worldPos = new THREE__namespace.Vector3();
21486
+ connectorObj.getWorldPosition(worldPos);
21487
+
21488
+ // Update connector's position in userData as array
21489
+ if (!child.userData) {
21490
+ child.userData = {};
21491
+ }
21492
+ child.userData.position = [cleanValue(worldPos.x), cleanValue(worldPos.y), cleanValue(worldPos.z)];
21493
+ console.log(" \u21B3 Updated child connector ".concat(child.uuid, " position to [").concat(child.userData.position.join(', '), "]"));
21494
+ }
21495
+ }
21496
+ });
21497
+ }
21498
+ } else {
21499
+ console.warn("\u26A0\uFE0F Component ".concat(component.uuid, " not found in scene data"));
21500
+ }
21501
+ }
21502
+
21413
21503
  /**
21414
21504
  * Update a connector's position in scene data
21415
21505
  * @param {THREE.Object3D} connector - The connector to update
@@ -21420,9 +21510,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21420
21510
  }, {
21421
21511
  key: "updateConnectorPositionInSceneData",
21422
21512
  value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
21423
- var _this$sceneViewer12;
21513
+ var _this$sceneViewer13;
21424
21514
  // Update scene data if available
21425
- if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
21515
+ if (!((_this$sceneViewer13 = this.sceneViewer) !== null && _this$sceneViewer13 !== void 0 && (_this$sceneViewer13 = _this$sceneViewer13.currentSceneData) !== null && _this$sceneViewer13 !== void 0 && _this$sceneViewer13.scene)) {
21426
21516
  return;
21427
21517
  }
21428
21518
  var cleanPosition = function cleanPosition(value) {
@@ -21713,8 +21803,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21713
21803
  // Check if either external connector belongs to the active segment
21714
21804
  var activeSegmentConnectors = [];
21715
21805
  activeSegment.traverse(function (child) {
21716
- var _child$userData24;
21717
- if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'segment-connector') {
21806
+ var _child$userData25;
21807
+ if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
21718
21808
  activeSegmentConnectors.push(child.uuid);
21719
21809
  }
21720
21810
  });
@@ -21762,8 +21852,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21762
21852
  // Get all connectors of the active segment
21763
21853
  var activeConnectors = [];
21764
21854
  activeSegment.traverse(function (child) {
21765
- var _child$userData25;
21766
- if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
21855
+ var _child$userData26;
21856
+ if (((_child$userData26 = child.userData) === null || _child$userData26 === void 0 ? void 0 : _child$userData26.objectType) === 'segment-connector') {
21767
21857
  activeConnectors.push(child);
21768
21858
  }
21769
21859
  });
@@ -34670,6 +34760,79 @@ var CentralPlantInternals = /*#__PURE__*/function () {
34670
34760
  }
34671
34761
  }
34672
34762
 
34763
+ /**
34764
+ * Delete a component from the scene by componentId (internal implementation)
34765
+ * @param {string} componentId - The UUID of the component to delete
34766
+ * @returns {boolean} True if deletion was successful, false otherwise
34767
+ */
34768
+ }, {
34769
+ key: "deleteComponent",
34770
+ value: function deleteComponent(componentId) {
34771
+ var _this$centralPlant$sc7;
34772
+ // Check if component manager is available
34773
+ var componentManager = (_this$centralPlant$sc7 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc7 === void 0 ? void 0 : _this$centralPlant$sc7.componentManager;
34774
+ if (!componentManager) {
34775
+ console.error('❌ deleteComponent(): Component manager not available');
34776
+ return false;
34777
+ }
34778
+ try {
34779
+ console.log("\uD83D\uDDD1\uFE0F deleteComponent(): Deleting component ".concat(componentId));
34780
+
34781
+ // Use componentManager to remove the component
34782
+ var success = componentManager.removeComponentFromScene(componentId);
34783
+ if (success) {
34784
+ // Also remove from scene data if available
34785
+ if (this.centralPlant.sceneViewer.sceneOperationsManager && this.centralPlant.sceneViewer.currentSceneData) {
34786
+ // Note: componentManager.removeComponentFromScene might not update sceneData
34787
+ // We should verify if sceneOperationsManager has a method for this or if we need to manually update
34788
+ // For now, assuming componentManager handles the scene object removal,
34789
+ // we might need to update the data structure manually if componentManager doesn't.
34790
+
34791
+ // Let's implement a safe removal from sceneData here just in case
34792
+ var sceneData = this.centralPlant.sceneViewer.currentSceneData;
34793
+ if (sceneData.scene && sceneData.scene.children) {
34794
+ var index = sceneData.scene.children.findIndex(function (c) {
34795
+ var _c$userData2;
34796
+ return c.uuid === componentId || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === componentId;
34797
+ });
34798
+ if (index !== -1) {
34799
+ sceneData.scene.children.splice(index, 1);
34800
+ console.log('✅ Removed component from sceneData');
34801
+ }
34802
+ }
34803
+ }
34804
+
34805
+ // Deselect if the deleted component was selected
34806
+ // We check if the selected object matches the deleted ID, OR if the selected object is now detached from the scene (parent is null)
34807
+ var transformManager = this.centralPlant.sceneViewer.transformManager;
34808
+ if (transformManager && transformManager.selectedObjectForTransform) {
34809
+ var _selectedObj$userData;
34810
+ var selectedObj = transformManager.selectedObjectForTransform;
34811
+ if (selectedObj.uuid === componentId || selectedObj.name === componentId || ((_selectedObj$userData = selectedObj.userData) === null || _selectedObj$userData === void 0 ? void 0 : _selectedObj$userData.originalUuid) === componentId || selectedObj.parent === null) {
34812
+ console.log('🎯 deleteComponent(): Deselecting deleted object');
34813
+ transformManager.deselectObject();
34814
+ }
34815
+ }
34816
+
34817
+ // Emit component-removed event for UI updates
34818
+ if (this.centralPlant.sceneViewer.emit) {
34819
+ this.centralPlant.sceneViewer.emit('component-removed', {
34820
+ id: componentId
34821
+ });
34822
+ console.log("\uD83D\uDCE1 Emitted 'component-removed' event for ".concat(componentId));
34823
+ }
34824
+ console.log("\u2705 deleteComponent(): Component ".concat(componentId, " deleted successfully"));
34825
+ return true;
34826
+ } else {
34827
+ console.warn("\u26A0\uFE0F deleteComponent(): Failed to delete component ".concat(componentId));
34828
+ return false;
34829
+ }
34830
+ } catch (error) {
34831
+ console.error("\u274C deleteComponent(): Error deleting component ".concat(componentId, ":"), error);
34832
+ return false;
34833
+ }
34834
+ }
34835
+
34673
34836
  /**
34674
34837
  * Get all component IDs from the scene
34675
34838
  * @returns {Array<string>} Array of component UUIDs
@@ -34702,7 +34865,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
34702
34865
  * Initialize the CentralPlant manager
34703
34866
  *
34704
34867
  * @constructor
34705
- * @version 0.1.74
34868
+ * @version 0.1.76
34706
34869
  * @updated 2025-10-22
34707
34870
  *
34708
34871
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -34955,6 +35118,23 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
34955
35118
  return this.internals.addComponent(libraryId, options);
34956
35119
  }
34957
35120
 
35121
+ /**
35122
+ * Delete a component from the scene by componentId
35123
+ * @param {string} componentId - The UUID of the component to delete
35124
+ * @returns {boolean} True if deletion was successful, false otherwise
35125
+ * @description Removes a 3D component from the scene and cleans up associated resources.
35126
+ * @example
35127
+ * const success = centralPlant.deleteComponent('component-uuid-123');
35128
+ * if (success) {
35129
+ * console.log('Component deleted successfully');
35130
+ * }
35131
+ */
35132
+ }, {
35133
+ key: "deleteComponent",
35134
+ value: function deleteComponent(componentId) {
35135
+ return this.internals.deleteComponent(componentId);
35136
+ }
35137
+
34958
35138
  /**
34959
35139
  * Translate a component by componentId
34960
35140
  * @param {string} componentId - The UUID of the component to translate
@@ -37229,7 +37409,28 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37229
37409
 
37230
37410
  // Setup callbacks
37231
37411
  this.transformManager.on({
37232
- onModeChange: this.onModeChange.bind(this)
37412
+ onModeChange: this.onModeChange.bind(this),
37413
+ onSelectionChanged: function onSelectionChanged(object) {
37414
+ if (object) {
37415
+ var _object$userData;
37416
+ // Object selected
37417
+ var componentId = object.name || object.uuid;
37418
+ var objectType = ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) || 'component';
37419
+ _this4.selectedObjectForTransform = object;
37420
+ console.log("\uD83D\uDCE1 Emitting component-selected for: ".concat(componentId));
37421
+ _this4.emit('component-selected', {
37422
+ id: componentId,
37423
+ uuid: object.uuid,
37424
+ type: objectType,
37425
+ object: object
37426
+ });
37427
+ } else {
37428
+ // Object deselected
37429
+ _this4.selectedObjectForTransform = null;
37430
+ console.log("\uD83D\uDCE1 Emitting component-deselected");
37431
+ _this4.emit('component-deselected');
37432
+ }
37433
+ }
37233
37434
  });
37234
37435
 
37235
37436
  // Setup SceneViewer event listeners for bounding box synchronization
@@ -37448,13 +37649,13 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37448
37649
  }, {
37449
37650
  key: "isSelectableObject",
37450
37651
  value: function isSelectableObject(object) {
37451
- var _object$userData;
37652
+ var _object$userData2;
37452
37653
  if (object.type == "TransformControlsPlane") {
37453
37654
  object = object.object;
37454
37655
  }
37455
37656
 
37456
37657
  // Allow pipe segments to be selected
37457
- if (((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === "segment") {
37658
+ if (((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) === "segment") {
37458
37659
  return true;
37459
37660
  }
37460
37661
 
@@ -37511,7 +37712,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37511
37712
  }, {
37512
37713
  key: "selectObject",
37513
37714
  value: function selectObject(object) {
37514
- var _object$userData2;
37715
+ var _object$userData3;
37515
37716
  if (!object || !object.uuid) {
37516
37717
  console.warn('⚠️ Cannot select invalid object');
37517
37718
  return false;
@@ -37522,7 +37723,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37522
37723
 
37523
37724
  // Emit selection event with component details
37524
37725
  var componentId = object.name || object.uuid;
37525
- var objectType = ((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) || 'component';
37726
+ var objectType = ((_object$userData3 = object.userData) === null || _object$userData3 === void 0 ? void 0 : _object$userData3.objectType) || 'component';
37526
37727
  this.emit('component-selected', {
37527
37728
  id: componentId,
37528
37729
  uuid: object.uuid,
@@ -19,7 +19,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
19
19
  * Initialize the CentralPlant manager
20
20
  *
21
21
  * @constructor
22
- * @version 0.1.74
22
+ * @version 0.1.76
23
23
  * @updated 2025-10-22
24
24
  *
25
25
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -272,6 +272,23 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
272
272
  return this.internals.addComponent(libraryId, options);
273
273
  }
274
274
 
275
+ /**
276
+ * Delete a component from the scene by componentId
277
+ * @param {string} componentId - The UUID of the component to delete
278
+ * @returns {boolean} True if deletion was successful, false otherwise
279
+ * @description Removes a 3D component from the scene and cleans up associated resources.
280
+ * @example
281
+ * const success = centralPlant.deleteComponent('component-uuid-123');
282
+ * if (success) {
283
+ * console.log('Component deleted successfully');
284
+ * }
285
+ */
286
+ }, {
287
+ key: "deleteComponent",
288
+ value: function deleteComponent(componentId) {
289
+ return this.internals.deleteComponent(componentId);
290
+ }
291
+
275
292
  /**
276
293
  * Translate a component by componentId
277
294
  * @param {string} componentId - The UUID of the component to translate
@@ -1105,6 +1105,79 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1105
1105
  }
1106
1106
  }
1107
1107
 
1108
+ /**
1109
+ * Delete a component from the scene by componentId (internal implementation)
1110
+ * @param {string} componentId - The UUID of the component to delete
1111
+ * @returns {boolean} True if deletion was successful, false otherwise
1112
+ */
1113
+ }, {
1114
+ key: "deleteComponent",
1115
+ value: function deleteComponent(componentId) {
1116
+ var _this$centralPlant$sc7;
1117
+ // Check if component manager is available
1118
+ var componentManager = (_this$centralPlant$sc7 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc7 === void 0 ? void 0 : _this$centralPlant$sc7.componentManager;
1119
+ if (!componentManager) {
1120
+ console.error('❌ deleteComponent(): Component manager not available');
1121
+ return false;
1122
+ }
1123
+ try {
1124
+ console.log("\uD83D\uDDD1\uFE0F deleteComponent(): Deleting component ".concat(componentId));
1125
+
1126
+ // Use componentManager to remove the component
1127
+ var success = componentManager.removeComponentFromScene(componentId);
1128
+ if (success) {
1129
+ // Also remove from scene data if available
1130
+ if (this.centralPlant.sceneViewer.sceneOperationsManager && this.centralPlant.sceneViewer.currentSceneData) {
1131
+ // Note: componentManager.removeComponentFromScene might not update sceneData
1132
+ // We should verify if sceneOperationsManager has a method for this or if we need to manually update
1133
+ // For now, assuming componentManager handles the scene object removal,
1134
+ // we might need to update the data structure manually if componentManager doesn't.
1135
+
1136
+ // Let's implement a safe removal from sceneData here just in case
1137
+ var sceneData = this.centralPlant.sceneViewer.currentSceneData;
1138
+ if (sceneData.scene && sceneData.scene.children) {
1139
+ var index = sceneData.scene.children.findIndex(function (c) {
1140
+ var _c$userData2;
1141
+ return c.uuid === componentId || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === componentId;
1142
+ });
1143
+ if (index !== -1) {
1144
+ sceneData.scene.children.splice(index, 1);
1145
+ console.log('✅ Removed component from sceneData');
1146
+ }
1147
+ }
1148
+ }
1149
+
1150
+ // Deselect if the deleted component was selected
1151
+ // We check if the selected object matches the deleted ID, OR if the selected object is now detached from the scene (parent is null)
1152
+ var transformManager = this.centralPlant.sceneViewer.transformManager;
1153
+ if (transformManager && transformManager.selectedObjectForTransform) {
1154
+ var _selectedObj$userData;
1155
+ var selectedObj = transformManager.selectedObjectForTransform;
1156
+ if (selectedObj.uuid === componentId || selectedObj.name === componentId || ((_selectedObj$userData = selectedObj.userData) === null || _selectedObj$userData === void 0 ? void 0 : _selectedObj$userData.originalUuid) === componentId || selectedObj.parent === null) {
1157
+ console.log('🎯 deleteComponent(): Deselecting deleted object');
1158
+ transformManager.deselectObject();
1159
+ }
1160
+ }
1161
+
1162
+ // Emit component-removed event for UI updates
1163
+ if (this.centralPlant.sceneViewer.emit) {
1164
+ this.centralPlant.sceneViewer.emit('component-removed', {
1165
+ id: componentId
1166
+ });
1167
+ console.log("\uD83D\uDCE1 Emitted 'component-removed' event for ".concat(componentId));
1168
+ }
1169
+ console.log("\u2705 deleteComponent(): Component ".concat(componentId, " deleted successfully"));
1170
+ return true;
1171
+ } else {
1172
+ console.warn("\u26A0\uFE0F deleteComponent(): Failed to delete component ".concat(componentId));
1173
+ return false;
1174
+ }
1175
+ } catch (error) {
1176
+ console.error("\u274C deleteComponent(): Error deleting component ".concat(componentId, ":"), error);
1177
+ return false;
1178
+ }
1179
+ }
1180
+
1108
1181
  /**
1109
1182
  * Get all component IDs from the scene
1110
1183
  * @returns {Array<string>} Array of component UUIDs
@@ -378,7 +378,28 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
378
378
 
379
379
  // Setup callbacks
380
380
  this.transformManager.on({
381
- onModeChange: this.onModeChange.bind(this)
381
+ onModeChange: this.onModeChange.bind(this),
382
+ onSelectionChanged: function onSelectionChanged(object) {
383
+ if (object) {
384
+ var _object$userData;
385
+ // Object selected
386
+ var componentId = object.name || object.uuid;
387
+ var objectType = ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) || 'component';
388
+ _this4.selectedObjectForTransform = object;
389
+ console.log("\uD83D\uDCE1 Emitting component-selected for: ".concat(componentId));
390
+ _this4.emit('component-selected', {
391
+ id: componentId,
392
+ uuid: object.uuid,
393
+ type: objectType,
394
+ object: object
395
+ });
396
+ } else {
397
+ // Object deselected
398
+ _this4.selectedObjectForTransform = null;
399
+ console.log("\uD83D\uDCE1 Emitting component-deselected");
400
+ _this4.emit('component-deselected');
401
+ }
402
+ }
382
403
  });
383
404
 
384
405
  // Setup SceneViewer event listeners for bounding box synchronization
@@ -597,13 +618,13 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
597
618
  }, {
598
619
  key: "isSelectableObject",
599
620
  value: function isSelectableObject(object) {
600
- var _object$userData;
621
+ var _object$userData2;
601
622
  if (object.type == "TransformControlsPlane") {
602
623
  object = object.object;
603
624
  }
604
625
 
605
626
  // Allow pipe segments to be selected
606
- if (((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === "segment") {
627
+ if (((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) === "segment") {
607
628
  return true;
608
629
  }
609
630
 
@@ -660,7 +681,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
660
681
  }, {
661
682
  key: "selectObject",
662
683
  value: function selectObject(object) {
663
- var _object$userData2;
684
+ var _object$userData3;
664
685
  if (!object || !object.uuid) {
665
686
  console.warn('⚠️ Cannot select invalid object');
666
687
  return false;
@@ -671,7 +692,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
671
692
 
672
693
  // Emit selection event with component details
673
694
  var componentId = object.name || object.uuid;
674
- var objectType = ((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) || 'component';
695
+ var objectType = ((_object$userData3 = object.userData) === null || _object$userData3 === void 0 ? void 0 : _object$userData3.objectType) || 'component';
675
696
  this.emit('component-selected', {
676
697
  id: componentId,
677
698
  uuid: object.uuid,
@@ -194,6 +194,14 @@ var ComponentManager = /*#__PURE__*/function () {
194
194
  try {
195
195
  // Use the new utility function to find objects by hardcoded UUID
196
196
  var object = nameUtils.findObjectByHardcodedUuid(this.sceneViewer.scene, componentUuid);
197
+
198
+ // Fallback: If not found by utility, try direct UUID or name lookup
199
+ if (!object) {
200
+ object = this.sceneViewer.scene.getObjectByProperty('uuid', componentUuid);
201
+ }
202
+ if (!object) {
203
+ object = this.sceneViewer.scene.getObjectByProperty('name', componentUuid);
204
+ }
197
205
  if (!object) {
198
206
  console.warn('⚠️ Component not found:', componentUuid);
199
207
  return false;
@@ -72,7 +72,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
72
72
  var component = null;
73
73
  this.sceneViewer.scene.traverse(function (child) {
74
74
  var _child$userData;
75
- if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId) {
75
+ if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId || child.name === componentId) {
76
76
  component = child;
77
77
  }
78
78
  });
@@ -538,7 +538,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
538
538
  var gateway = null;
539
539
  this.sceneViewer.scene.traverse(function (child) {
540
540
  var _child$userData3;
541
- if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId) {
541
+ if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId || child.name === gatewayId) {
542
542
  gateway = child;
543
543
  }
544
544
  });
@@ -635,7 +635,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
635
635
  var component = null;
636
636
  this.sceneViewer.scene.traverse(function (child) {
637
637
  var _child$userData4;
638
- if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId) {
638
+ if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId || child.name === componentId) {
639
639
  component = child;
640
640
  }
641
641
  });
@@ -671,6 +671,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
671
671
  component.updateMatrix();
672
672
  component.updateMatrixWorld(true);
673
673
 
674
+ // Update component rotation and connector positions in scene data
675
+ this.updateComponentRotationInSceneData(component);
676
+
674
677
  // Auto-update paths if enabled (matches behavior of translateComponent)
675
678
  if (this.sceneViewer.shouldUpdatePaths) {
676
679
  try {
@@ -1970,6 +1973,69 @@ var TransformOperationsManager = /*#__PURE__*/function () {
1970
1973
  }
1971
1974
  }
1972
1975
 
1976
+ /**
1977
+ * Update component rotation and child connectors in currentSceneData after rotation
1978
+ * @param {THREE.Object3D} component - The component that was rotated
1979
+ * @private
1980
+ */
1981
+ }, {
1982
+ key: "updateComponentRotationInSceneData",
1983
+ value: function updateComponentRotationInSceneData(component) {
1984
+ var _this$sceneViewer12;
1985
+ if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
1986
+ console.warn('⚠️ Cannot update component rotation: currentSceneData not available');
1987
+ return;
1988
+ }
1989
+ var cleanValue = function cleanValue(value) {
1990
+ return Math.abs(value) < 1e-10 ? 0 : value;
1991
+ };
1992
+
1993
+ // Find the component in scene data
1994
+ // Use the same logic as other methods to match by UUID or originalUuid
1995
+ var sceneDataComponent = this.sceneViewer.currentSceneData.scene.children.find(function (child) {
1996
+ var _component$userData6;
1997
+ return child.uuid === component.uuid || child.uuid === ((_component$userData6 = component.userData) === null || _component$userData6 === void 0 ? void 0 : _component$userData6.originalUuid);
1998
+ });
1999
+ if (sceneDataComponent) {
2000
+ // Update rotation
2001
+ if (!sceneDataComponent.rotation) {
2002
+ sceneDataComponent.rotation = {};
2003
+ }
2004
+ sceneDataComponent.rotation.x = cleanValue(component.rotation.x);
2005
+ sceneDataComponent.rotation.y = cleanValue(component.rotation.y);
2006
+ sceneDataComponent.rotation.z = cleanValue(component.rotation.z);
2007
+ console.log("\u2705 Updated component ".concat(component.uuid, " rotation in scene data"));
2008
+
2009
+ // Also update child connectors' positions if they exist (rotation moves them in world space)
2010
+ if (sceneDataComponent.children) {
2011
+ sceneDataComponent.children.forEach(function (child) {
2012
+ var _child$userData24;
2013
+ if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'connector') {
2014
+ // Find the actual connector object in the scene
2015
+ var connectorObj = component.children.find(function (c) {
2016
+ var _c$userData2;
2017
+ return c.uuid === child.uuid || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === child.uuid;
2018
+ });
2019
+ if (connectorObj) {
2020
+ // Get world position of connector
2021
+ var worldPos = new THREE__namespace.Vector3();
2022
+ connectorObj.getWorldPosition(worldPos);
2023
+
2024
+ // Update connector's position in userData as array
2025
+ if (!child.userData) {
2026
+ child.userData = {};
2027
+ }
2028
+ child.userData.position = [cleanValue(worldPos.x), cleanValue(worldPos.y), cleanValue(worldPos.z)];
2029
+ console.log(" \u21B3 Updated child connector ".concat(child.uuid, " position to [").concat(child.userData.position.join(', '), "]"));
2030
+ }
2031
+ }
2032
+ });
2033
+ }
2034
+ } else {
2035
+ console.warn("\u26A0\uFE0F Component ".concat(component.uuid, " not found in scene data"));
2036
+ }
2037
+ }
2038
+
1973
2039
  /**
1974
2040
  * Update a connector's position in scene data
1975
2041
  * @param {THREE.Object3D} connector - The connector to update
@@ -1980,9 +2046,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
1980
2046
  }, {
1981
2047
  key: "updateConnectorPositionInSceneData",
1982
2048
  value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
1983
- var _this$sceneViewer12;
2049
+ var _this$sceneViewer13;
1984
2050
  // Update scene data if available
1985
- if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
2051
+ if (!((_this$sceneViewer13 = this.sceneViewer) !== null && _this$sceneViewer13 !== void 0 && (_this$sceneViewer13 = _this$sceneViewer13.currentSceneData) !== null && _this$sceneViewer13 !== void 0 && _this$sceneViewer13.scene)) {
1986
2052
  return;
1987
2053
  }
1988
2054
  var cleanPosition = function cleanPosition(value) {
@@ -2273,8 +2339,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
2273
2339
  // Check if either external connector belongs to the active segment
2274
2340
  var activeSegmentConnectors = [];
2275
2341
  activeSegment.traverse(function (child) {
2276
- var _child$userData24;
2277
- if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'segment-connector') {
2342
+ var _child$userData25;
2343
+ if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
2278
2344
  activeSegmentConnectors.push(child.uuid);
2279
2345
  }
2280
2346
  });
@@ -2322,8 +2388,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
2322
2388
  // Get all connectors of the active segment
2323
2389
  var activeConnectors = [];
2324
2390
  activeSegment.traverse(function (child) {
2325
- var _child$userData25;
2326
- if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
2391
+ var _child$userData26;
2392
+ if (((_child$userData26 = child.userData) === null || _child$userData26 === void 0 ? void 0 : _child$userData26.objectType) === 'segment-connector') {
2327
2393
  activeConnectors.push(child);
2328
2394
  }
2329
2395
  });
@@ -115,7 +115,8 @@ var TransformControlsManager = /*#__PURE__*/function () {
115
115
  onTransform: null,
116
116
  onTransformEnd: null,
117
117
  onModeChange: null,
118
- onObjectRemoved: null
118
+ onObjectRemoved: null,
119
+ onSelectionChanged: null
119
120
  };
120
121
  this.init();
121
122
  }
@@ -190,6 +191,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
190
191
  if (callbacks.onObjectRemoved) {
191
192
  this.callbacks.onObjectRemoved = callbacks.onObjectRemoved;
192
193
  }
194
+ if (callbacks.onSelectionChanged) {
195
+ this.callbacks.onSelectionChanged = callbacks.onSelectionChanged;
196
+ }
193
197
  console.log('🔗 Transform controls callbacks registered');
194
198
  }
195
199
  /**
@@ -759,6 +763,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
759
763
  if (this.callbacks.onObjectSelect) {
760
764
  this.callbacks.onObjectSelect(object);
761
765
  }
766
+
767
+ // Trigger explicit selection change callback
768
+ if (this.callbacks.onSelectionChanged) {
769
+ this.callbacks.onSelectionChanged(object);
770
+ }
762
771
  console.log("\uD83C\uDFAF Object selected: ".concat(object.name || object.uuid));
763
772
  return true;
764
773
  }
@@ -782,9 +791,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
782
791
  // Update the multi-selection display (works for single object too)
783
792
  this.updateMultiSelection();
784
793
 
785
- // NOTE: We deliberately do NOT call any callback here
786
- // This allows transform controls and bounding box to show without triggering tooltips
787
-
794
+ // NOTE: We deliberately do NOT call onObjectSelect here to avoid tooltips
795
+ // But we DO call onSelectionChanged to sync UI
796
+ if (this.callbacks.onSelectionChanged) {
797
+ this.callbacks.onSelectionChanged(object);
798
+ }
788
799
  console.log("\uD83C\uDFAF Object selected for transform only: ".concat(object.name || object.uuid));
789
800
  return true;
790
801
  }
@@ -988,6 +999,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
988
999
  if (this.callbacks.onObjectSelect) {
989
1000
  this.callbacks.onObjectSelect(null);
990
1001
  }
1002
+
1003
+ // Trigger explicit selection change callback
1004
+ if (this.callbacks.onSelectionChanged) {
1005
+ this.callbacks.onSelectionChanged(null);
1006
+ }
991
1007
  }
992
1008
 
993
1009
  /**
@@ -15,7 +15,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
15
15
  * Initialize the CentralPlant manager
16
16
  *
17
17
  * @constructor
18
- * @version 0.1.74
18
+ * @version 0.1.76
19
19
  * @updated 2025-10-22
20
20
  *
21
21
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -268,6 +268,23 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
268
268
  return this.internals.addComponent(libraryId, options);
269
269
  }
270
270
 
271
+ /**
272
+ * Delete a component from the scene by componentId
273
+ * @param {string} componentId - The UUID of the component to delete
274
+ * @returns {boolean} True if deletion was successful, false otherwise
275
+ * @description Removes a 3D component from the scene and cleans up associated resources.
276
+ * @example
277
+ * const success = centralPlant.deleteComponent('component-uuid-123');
278
+ * if (success) {
279
+ * console.log('Component deleted successfully');
280
+ * }
281
+ */
282
+ }, {
283
+ key: "deleteComponent",
284
+ value: function deleteComponent(componentId) {
285
+ return this.internals.deleteComponent(componentId);
286
+ }
287
+
271
288
  /**
272
289
  * Translate a component by componentId
273
290
  * @param {string} componentId - The UUID of the component to translate
@@ -1081,6 +1081,79 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1081
1081
  }
1082
1082
  }
1083
1083
 
1084
+ /**
1085
+ * Delete a component from the scene by componentId (internal implementation)
1086
+ * @param {string} componentId - The UUID of the component to delete
1087
+ * @returns {boolean} True if deletion was successful, false otherwise
1088
+ */
1089
+ }, {
1090
+ key: "deleteComponent",
1091
+ value: function deleteComponent(componentId) {
1092
+ var _this$centralPlant$sc7;
1093
+ // Check if component manager is available
1094
+ var componentManager = (_this$centralPlant$sc7 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc7 === void 0 ? void 0 : _this$centralPlant$sc7.componentManager;
1095
+ if (!componentManager) {
1096
+ console.error('❌ deleteComponent(): Component manager not available');
1097
+ return false;
1098
+ }
1099
+ try {
1100
+ console.log("\uD83D\uDDD1\uFE0F deleteComponent(): Deleting component ".concat(componentId));
1101
+
1102
+ // Use componentManager to remove the component
1103
+ var success = componentManager.removeComponentFromScene(componentId);
1104
+ if (success) {
1105
+ // Also remove from scene data if available
1106
+ if (this.centralPlant.sceneViewer.sceneOperationsManager && this.centralPlant.sceneViewer.currentSceneData) {
1107
+ // Note: componentManager.removeComponentFromScene might not update sceneData
1108
+ // We should verify if sceneOperationsManager has a method for this or if we need to manually update
1109
+ // For now, assuming componentManager handles the scene object removal,
1110
+ // we might need to update the data structure manually if componentManager doesn't.
1111
+
1112
+ // Let's implement a safe removal from sceneData here just in case
1113
+ var sceneData = this.centralPlant.sceneViewer.currentSceneData;
1114
+ if (sceneData.scene && sceneData.scene.children) {
1115
+ var index = sceneData.scene.children.findIndex(function (c) {
1116
+ var _c$userData2;
1117
+ return c.uuid === componentId || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === componentId;
1118
+ });
1119
+ if (index !== -1) {
1120
+ sceneData.scene.children.splice(index, 1);
1121
+ console.log('✅ Removed component from sceneData');
1122
+ }
1123
+ }
1124
+ }
1125
+
1126
+ // Deselect if the deleted component was selected
1127
+ // We check if the selected object matches the deleted ID, OR if the selected object is now detached from the scene (parent is null)
1128
+ var transformManager = this.centralPlant.sceneViewer.transformManager;
1129
+ if (transformManager && transformManager.selectedObjectForTransform) {
1130
+ var _selectedObj$userData;
1131
+ var selectedObj = transformManager.selectedObjectForTransform;
1132
+ if (selectedObj.uuid === componentId || selectedObj.name === componentId || ((_selectedObj$userData = selectedObj.userData) === null || _selectedObj$userData === void 0 ? void 0 : _selectedObj$userData.originalUuid) === componentId || selectedObj.parent === null) {
1133
+ console.log('🎯 deleteComponent(): Deselecting deleted object');
1134
+ transformManager.deselectObject();
1135
+ }
1136
+ }
1137
+
1138
+ // Emit component-removed event for UI updates
1139
+ if (this.centralPlant.sceneViewer.emit) {
1140
+ this.centralPlant.sceneViewer.emit('component-removed', {
1141
+ id: componentId
1142
+ });
1143
+ console.log("\uD83D\uDCE1 Emitted 'component-removed' event for ".concat(componentId));
1144
+ }
1145
+ console.log("\u2705 deleteComponent(): Component ".concat(componentId, " deleted successfully"));
1146
+ return true;
1147
+ } else {
1148
+ console.warn("\u26A0\uFE0F deleteComponent(): Failed to delete component ".concat(componentId));
1149
+ return false;
1150
+ }
1151
+ } catch (error) {
1152
+ console.error("\u274C deleteComponent(): Error deleting component ".concat(componentId, ":"), error);
1153
+ return false;
1154
+ }
1155
+ }
1156
+
1084
1157
  /**
1085
1158
  * Get all component IDs from the scene
1086
1159
  * @returns {Array<string>} Array of component UUIDs
@@ -374,7 +374,28 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
374
374
 
375
375
  // Setup callbacks
376
376
  this.transformManager.on({
377
- onModeChange: this.onModeChange.bind(this)
377
+ onModeChange: this.onModeChange.bind(this),
378
+ onSelectionChanged: function onSelectionChanged(object) {
379
+ if (object) {
380
+ var _object$userData;
381
+ // Object selected
382
+ var componentId = object.name || object.uuid;
383
+ var objectType = ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) || 'component';
384
+ _this4.selectedObjectForTransform = object;
385
+ console.log("\uD83D\uDCE1 Emitting component-selected for: ".concat(componentId));
386
+ _this4.emit('component-selected', {
387
+ id: componentId,
388
+ uuid: object.uuid,
389
+ type: objectType,
390
+ object: object
391
+ });
392
+ } else {
393
+ // Object deselected
394
+ _this4.selectedObjectForTransform = null;
395
+ console.log("\uD83D\uDCE1 Emitting component-deselected");
396
+ _this4.emit('component-deselected');
397
+ }
398
+ }
378
399
  });
379
400
 
380
401
  // Setup SceneViewer event listeners for bounding box synchronization
@@ -593,13 +614,13 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
593
614
  }, {
594
615
  key: "isSelectableObject",
595
616
  value: function isSelectableObject(object) {
596
- var _object$userData;
617
+ var _object$userData2;
597
618
  if (object.type == "TransformControlsPlane") {
598
619
  object = object.object;
599
620
  }
600
621
 
601
622
  // Allow pipe segments to be selected
602
- if (((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === "segment") {
623
+ if (((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) === "segment") {
603
624
  return true;
604
625
  }
605
626
 
@@ -656,7 +677,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
656
677
  }, {
657
678
  key: "selectObject",
658
679
  value: function selectObject(object) {
659
- var _object$userData2;
680
+ var _object$userData3;
660
681
  if (!object || !object.uuid) {
661
682
  console.warn('⚠️ Cannot select invalid object');
662
683
  return false;
@@ -667,7 +688,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
667
688
 
668
689
  // Emit selection event with component details
669
690
  var componentId = object.name || object.uuid;
670
- var objectType = ((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) || 'component';
691
+ var objectType = ((_object$userData3 = object.userData) === null || _object$userData3 === void 0 ? void 0 : _object$userData3.objectType) || 'component';
671
692
  this.emit('component-selected', {
672
693
  id: componentId,
673
694
  uuid: object.uuid,
@@ -190,6 +190,14 @@ var ComponentManager = /*#__PURE__*/function () {
190
190
  try {
191
191
  // Use the new utility function to find objects by hardcoded UUID
192
192
  var object = findObjectByHardcodedUuid(this.sceneViewer.scene, componentUuid);
193
+
194
+ // Fallback: If not found by utility, try direct UUID or name lookup
195
+ if (!object) {
196
+ object = this.sceneViewer.scene.getObjectByProperty('uuid', componentUuid);
197
+ }
198
+ if (!object) {
199
+ object = this.sceneViewer.scene.getObjectByProperty('name', componentUuid);
200
+ }
193
201
  if (!object) {
194
202
  console.warn('⚠️ Component not found:', componentUuid);
195
203
  return false;
@@ -48,7 +48,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
48
48
  var component = null;
49
49
  this.sceneViewer.scene.traverse(function (child) {
50
50
  var _child$userData;
51
- if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId) {
51
+ if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId || child.name === componentId) {
52
52
  component = child;
53
53
  }
54
54
  });
@@ -514,7 +514,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
514
514
  var gateway = null;
515
515
  this.sceneViewer.scene.traverse(function (child) {
516
516
  var _child$userData3;
517
- if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId) {
517
+ if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId || child.name === gatewayId) {
518
518
  gateway = child;
519
519
  }
520
520
  });
@@ -611,7 +611,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
611
611
  var component = null;
612
612
  this.sceneViewer.scene.traverse(function (child) {
613
613
  var _child$userData4;
614
- if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId) {
614
+ if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId || child.name === componentId) {
615
615
  component = child;
616
616
  }
617
617
  });
@@ -647,6 +647,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
647
647
  component.updateMatrix();
648
648
  component.updateMatrixWorld(true);
649
649
 
650
+ // Update component rotation and connector positions in scene data
651
+ this.updateComponentRotationInSceneData(component);
652
+
650
653
  // Auto-update paths if enabled (matches behavior of translateComponent)
651
654
  if (this.sceneViewer.shouldUpdatePaths) {
652
655
  try {
@@ -1946,6 +1949,69 @@ var TransformOperationsManager = /*#__PURE__*/function () {
1946
1949
  }
1947
1950
  }
1948
1951
 
1952
+ /**
1953
+ * Update component rotation and child connectors in currentSceneData after rotation
1954
+ * @param {THREE.Object3D} component - The component that was rotated
1955
+ * @private
1956
+ */
1957
+ }, {
1958
+ key: "updateComponentRotationInSceneData",
1959
+ value: function updateComponentRotationInSceneData(component) {
1960
+ var _this$sceneViewer12;
1961
+ if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
1962
+ console.warn('⚠️ Cannot update component rotation: currentSceneData not available');
1963
+ return;
1964
+ }
1965
+ var cleanValue = function cleanValue(value) {
1966
+ return Math.abs(value) < 1e-10 ? 0 : value;
1967
+ };
1968
+
1969
+ // Find the component in scene data
1970
+ // Use the same logic as other methods to match by UUID or originalUuid
1971
+ var sceneDataComponent = this.sceneViewer.currentSceneData.scene.children.find(function (child) {
1972
+ var _component$userData6;
1973
+ return child.uuid === component.uuid || child.uuid === ((_component$userData6 = component.userData) === null || _component$userData6 === void 0 ? void 0 : _component$userData6.originalUuid);
1974
+ });
1975
+ if (sceneDataComponent) {
1976
+ // Update rotation
1977
+ if (!sceneDataComponent.rotation) {
1978
+ sceneDataComponent.rotation = {};
1979
+ }
1980
+ sceneDataComponent.rotation.x = cleanValue(component.rotation.x);
1981
+ sceneDataComponent.rotation.y = cleanValue(component.rotation.y);
1982
+ sceneDataComponent.rotation.z = cleanValue(component.rotation.z);
1983
+ console.log("\u2705 Updated component ".concat(component.uuid, " rotation in scene data"));
1984
+
1985
+ // Also update child connectors' positions if they exist (rotation moves them in world space)
1986
+ if (sceneDataComponent.children) {
1987
+ sceneDataComponent.children.forEach(function (child) {
1988
+ var _child$userData24;
1989
+ if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'connector') {
1990
+ // Find the actual connector object in the scene
1991
+ var connectorObj = component.children.find(function (c) {
1992
+ var _c$userData2;
1993
+ return c.uuid === child.uuid || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === child.uuid;
1994
+ });
1995
+ if (connectorObj) {
1996
+ // Get world position of connector
1997
+ var worldPos = new THREE.Vector3();
1998
+ connectorObj.getWorldPosition(worldPos);
1999
+
2000
+ // Update connector's position in userData as array
2001
+ if (!child.userData) {
2002
+ child.userData = {};
2003
+ }
2004
+ child.userData.position = [cleanValue(worldPos.x), cleanValue(worldPos.y), cleanValue(worldPos.z)];
2005
+ console.log(" \u21B3 Updated child connector ".concat(child.uuid, " position to [").concat(child.userData.position.join(', '), "]"));
2006
+ }
2007
+ }
2008
+ });
2009
+ }
2010
+ } else {
2011
+ console.warn("\u26A0\uFE0F Component ".concat(component.uuid, " not found in scene data"));
2012
+ }
2013
+ }
2014
+
1949
2015
  /**
1950
2016
  * Update a connector's position in scene data
1951
2017
  * @param {THREE.Object3D} connector - The connector to update
@@ -1956,9 +2022,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
1956
2022
  }, {
1957
2023
  key: "updateConnectorPositionInSceneData",
1958
2024
  value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
1959
- var _this$sceneViewer12;
2025
+ var _this$sceneViewer13;
1960
2026
  // Update scene data if available
1961
- if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
2027
+ if (!((_this$sceneViewer13 = this.sceneViewer) !== null && _this$sceneViewer13 !== void 0 && (_this$sceneViewer13 = _this$sceneViewer13.currentSceneData) !== null && _this$sceneViewer13 !== void 0 && _this$sceneViewer13.scene)) {
1962
2028
  return;
1963
2029
  }
1964
2030
  var cleanPosition = function cleanPosition(value) {
@@ -2249,8 +2315,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
2249
2315
  // Check if either external connector belongs to the active segment
2250
2316
  var activeSegmentConnectors = [];
2251
2317
  activeSegment.traverse(function (child) {
2252
- var _child$userData24;
2253
- if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'segment-connector') {
2318
+ var _child$userData25;
2319
+ if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
2254
2320
  activeSegmentConnectors.push(child.uuid);
2255
2321
  }
2256
2322
  });
@@ -2298,8 +2364,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
2298
2364
  // Get all connectors of the active segment
2299
2365
  var activeConnectors = [];
2300
2366
  activeSegment.traverse(function (child) {
2301
- var _child$userData25;
2302
- if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
2367
+ var _child$userData26;
2368
+ if (((_child$userData26 = child.userData) === null || _child$userData26 === void 0 ? void 0 : _child$userData26.objectType) === 'segment-connector') {
2303
2369
  activeConnectors.push(child);
2304
2370
  }
2305
2371
  });
@@ -91,7 +91,8 @@ var TransformControlsManager = /*#__PURE__*/function () {
91
91
  onTransform: null,
92
92
  onTransformEnd: null,
93
93
  onModeChange: null,
94
- onObjectRemoved: null
94
+ onObjectRemoved: null,
95
+ onSelectionChanged: null
95
96
  };
96
97
  this.init();
97
98
  }
@@ -166,6 +167,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
166
167
  if (callbacks.onObjectRemoved) {
167
168
  this.callbacks.onObjectRemoved = callbacks.onObjectRemoved;
168
169
  }
170
+ if (callbacks.onSelectionChanged) {
171
+ this.callbacks.onSelectionChanged = callbacks.onSelectionChanged;
172
+ }
169
173
  console.log('🔗 Transform controls callbacks registered');
170
174
  }
171
175
  /**
@@ -735,6 +739,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
735
739
  if (this.callbacks.onObjectSelect) {
736
740
  this.callbacks.onObjectSelect(object);
737
741
  }
742
+
743
+ // Trigger explicit selection change callback
744
+ if (this.callbacks.onSelectionChanged) {
745
+ this.callbacks.onSelectionChanged(object);
746
+ }
738
747
  console.log("\uD83C\uDFAF Object selected: ".concat(object.name || object.uuid));
739
748
  return true;
740
749
  }
@@ -758,9 +767,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
758
767
  // Update the multi-selection display (works for single object too)
759
768
  this.updateMultiSelection();
760
769
 
761
- // NOTE: We deliberately do NOT call any callback here
762
- // This allows transform controls and bounding box to show without triggering tooltips
763
-
770
+ // NOTE: We deliberately do NOT call onObjectSelect here to avoid tooltips
771
+ // But we DO call onSelectionChanged to sync UI
772
+ if (this.callbacks.onSelectionChanged) {
773
+ this.callbacks.onSelectionChanged(object);
774
+ }
764
775
  console.log("\uD83C\uDFAF Object selected for transform only: ".concat(object.name || object.uuid));
765
776
  return true;
766
777
  }
@@ -964,6 +975,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
964
975
  if (this.callbacks.onObjectSelect) {
965
976
  this.callbacks.onObjectSelect(null);
966
977
  }
978
+
979
+ // Trigger explicit selection change callback
980
+ if (this.callbacks.onSelectionChanged) {
981
+ this.callbacks.onSelectionChanged(null);
982
+ }
967
983
  }
968
984
 
969
985
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2112-lab/central-plant",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "description": "Utility modules for the Central Plant Application",
5
5
  "main": "dist/bundle/index.js",
6
6
  "module": "dist/esm/index.js",