@2112-lab/central-plant 0.1.73 → 0.1.75

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
  /**
@@ -19512,7 +19528,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19512
19528
  var component = null;
19513
19529
  this.sceneViewer.scene.traverse(function (child) {
19514
19530
  var _child$userData;
19515
- if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId) {
19531
+ if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId || child.name === componentId) {
19516
19532
  component = child;
19517
19533
  }
19518
19534
  });
@@ -19978,7 +19994,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19978
19994
  var gateway = null;
19979
19995
  this.sceneViewer.scene.traverse(function (child) {
19980
19996
  var _child$userData3;
19981
- if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId) {
19997
+ if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId || child.name === gatewayId) {
19982
19998
  gateway = child;
19983
19999
  }
19984
20000
  });
@@ -20075,7 +20091,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20075
20091
  var component = null;
20076
20092
  this.sceneViewer.scene.traverse(function (child) {
20077
20093
  var _child$userData4;
20078
- if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId) {
20094
+ if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId || child.name === componentId) {
20079
20095
  component = child;
20080
20096
  }
20081
20097
  });
@@ -20111,6 +20127,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20111
20127
  component.updateMatrix();
20112
20128
  component.updateMatrixWorld(true);
20113
20129
 
20130
+ // Update component rotation and connector positions in scene data
20131
+ this.updateComponentRotationInSceneData(component);
20132
+
20114
20133
  // Auto-update paths if enabled (matches behavior of translateComponent)
20115
20134
  if (this.sceneViewer.shouldUpdatePaths) {
20116
20135
  try {
@@ -21410,6 +21429,69 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21410
21429
  }
21411
21430
  }
21412
21431
 
21432
+ /**
21433
+ * Update component rotation and child connectors in currentSceneData after rotation
21434
+ * @param {THREE.Object3D} component - The component that was rotated
21435
+ * @private
21436
+ */
21437
+ }, {
21438
+ key: "updateComponentRotationInSceneData",
21439
+ value: function updateComponentRotationInSceneData(component) {
21440
+ var _this$sceneViewer12;
21441
+ if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
21442
+ console.warn('⚠️ Cannot update component rotation: currentSceneData not available');
21443
+ return;
21444
+ }
21445
+ var cleanValue = function cleanValue(value) {
21446
+ return Math.abs(value) < 1e-10 ? 0 : value;
21447
+ };
21448
+
21449
+ // Find the component in scene data
21450
+ // Use the same logic as other methods to match by UUID or originalUuid
21451
+ var sceneDataComponent = this.sceneViewer.currentSceneData.scene.children.find(function (child) {
21452
+ var _component$userData6;
21453
+ return child.uuid === component.uuid || child.uuid === ((_component$userData6 = component.userData) === null || _component$userData6 === void 0 ? void 0 : _component$userData6.originalUuid);
21454
+ });
21455
+ if (sceneDataComponent) {
21456
+ // Update rotation
21457
+ if (!sceneDataComponent.rotation) {
21458
+ sceneDataComponent.rotation = {};
21459
+ }
21460
+ sceneDataComponent.rotation.x = cleanValue(component.rotation.x);
21461
+ sceneDataComponent.rotation.y = cleanValue(component.rotation.y);
21462
+ sceneDataComponent.rotation.z = cleanValue(component.rotation.z);
21463
+ console.log("\u2705 Updated component ".concat(component.uuid, " rotation in scene data"));
21464
+
21465
+ // Also update child connectors' positions if they exist (rotation moves them in world space)
21466
+ if (sceneDataComponent.children) {
21467
+ sceneDataComponent.children.forEach(function (child) {
21468
+ var _child$userData24;
21469
+ if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'connector') {
21470
+ // Find the actual connector object in the scene
21471
+ var connectorObj = component.children.find(function (c) {
21472
+ var _c$userData2;
21473
+ return c.uuid === child.uuid || ((_c$userData2 = c.userData) === null || _c$userData2 === void 0 ? void 0 : _c$userData2.originalUuid) === child.uuid;
21474
+ });
21475
+ if (connectorObj) {
21476
+ // Get world position of connector
21477
+ var worldPos = new THREE__namespace.Vector3();
21478
+ connectorObj.getWorldPosition(worldPos);
21479
+
21480
+ // Update connector's position in userData as array
21481
+ if (!child.userData) {
21482
+ child.userData = {};
21483
+ }
21484
+ child.userData.position = [cleanValue(worldPos.x), cleanValue(worldPos.y), cleanValue(worldPos.z)];
21485
+ console.log(" \u21B3 Updated child connector ".concat(child.uuid, " position to [").concat(child.userData.position.join(', '), "]"));
21486
+ }
21487
+ }
21488
+ });
21489
+ }
21490
+ } else {
21491
+ console.warn("\u26A0\uFE0F Component ".concat(component.uuid, " not found in scene data"));
21492
+ }
21493
+ }
21494
+
21413
21495
  /**
21414
21496
  * Update a connector's position in scene data
21415
21497
  * @param {THREE.Object3D} connector - The connector to update
@@ -21420,9 +21502,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21420
21502
  }, {
21421
21503
  key: "updateConnectorPositionInSceneData",
21422
21504
  value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
21423
- var _this$sceneViewer12;
21505
+ var _this$sceneViewer13;
21424
21506
  // 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)) {
21507
+ if (!((_this$sceneViewer13 = this.sceneViewer) !== null && _this$sceneViewer13 !== void 0 && (_this$sceneViewer13 = _this$sceneViewer13.currentSceneData) !== null && _this$sceneViewer13 !== void 0 && _this$sceneViewer13.scene)) {
21426
21508
  return;
21427
21509
  }
21428
21510
  var cleanPosition = function cleanPosition(value) {
@@ -21713,8 +21795,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21713
21795
  // Check if either external connector belongs to the active segment
21714
21796
  var activeSegmentConnectors = [];
21715
21797
  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') {
21798
+ var _child$userData25;
21799
+ if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
21718
21800
  activeSegmentConnectors.push(child.uuid);
21719
21801
  }
21720
21802
  });
@@ -21762,8 +21844,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
21762
21844
  // Get all connectors of the active segment
21763
21845
  var activeConnectors = [];
21764
21846
  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') {
21847
+ var _child$userData26;
21848
+ if (((_child$userData26 = child.userData) === null || _child$userData26 === void 0 ? void 0 : _child$userData26.objectType) === 'segment-connector') {
21767
21849
  activeConnectors.push(child);
21768
21850
  }
21769
21851
  });
@@ -34503,7 +34585,15 @@ var CentralPlantInternals = /*#__PURE__*/function () {
34503
34585
  componentModel.position.set(position.x, position.y, position.z);
34504
34586
 
34505
34587
  // Rotate the component
34506
- componentModel.rotation.set(rotation.x, rotation.y, rotation.z);
34588
+ if (options.rotation) {
34589
+ componentModel.rotation.set(rotation.x, rotation.y, rotation.z);
34590
+ } else {
34591
+ console.log("\u2139\uFE0F addComponent(): No rotation provided, keeping model default:", {
34592
+ x: componentModel.rotation.x,
34593
+ y: componentModel.rotation.y,
34594
+ z: componentModel.rotation.z
34595
+ });
34596
+ }
34507
34597
 
34508
34598
  // Set user data for identification and management
34509
34599
  componentModel.userData = {
@@ -34694,7 +34784,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
34694
34784
  * Initialize the CentralPlant manager
34695
34785
  *
34696
34786
  * @constructor
34697
- * @version 0.1.73
34787
+ * @version 0.1.75
34698
34788
  * @updated 2025-10-22
34699
34789
  *
34700
34790
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -37221,7 +37311,28 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37221
37311
 
37222
37312
  // Setup callbacks
37223
37313
  this.transformManager.on({
37224
- onModeChange: this.onModeChange.bind(this)
37314
+ onModeChange: this.onModeChange.bind(this),
37315
+ onSelectionChanged: function onSelectionChanged(object) {
37316
+ if (object) {
37317
+ var _object$userData;
37318
+ // Object selected
37319
+ var componentId = object.name || object.uuid;
37320
+ var objectType = ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) || 'component';
37321
+ _this4.selectedObjectForTransform = object;
37322
+ console.log("\uD83D\uDCE1 Emitting component-selected for: ".concat(componentId));
37323
+ _this4.emit('component-selected', {
37324
+ id: componentId,
37325
+ uuid: object.uuid,
37326
+ type: objectType,
37327
+ object: object
37328
+ });
37329
+ } else {
37330
+ // Object deselected
37331
+ _this4.selectedObjectForTransform = null;
37332
+ console.log("\uD83D\uDCE1 Emitting component-deselected");
37333
+ _this4.emit('component-deselected');
37334
+ }
37335
+ }
37225
37336
  });
37226
37337
 
37227
37338
  // Setup SceneViewer event listeners for bounding box synchronization
@@ -37440,13 +37551,13 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37440
37551
  }, {
37441
37552
  key: "isSelectableObject",
37442
37553
  value: function isSelectableObject(object) {
37443
- var _object$userData;
37554
+ var _object$userData2;
37444
37555
  if (object.type == "TransformControlsPlane") {
37445
37556
  object = object.object;
37446
37557
  }
37447
37558
 
37448
37559
  // Allow pipe segments to be selected
37449
- if (((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === "segment") {
37560
+ if (((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) === "segment") {
37450
37561
  return true;
37451
37562
  }
37452
37563
 
@@ -37503,7 +37614,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37503
37614
  }, {
37504
37615
  key: "selectObject",
37505
37616
  value: function selectObject(object) {
37506
- var _object$userData2;
37617
+ var _object$userData3;
37507
37618
  if (!object || !object.uuid) {
37508
37619
  console.warn('⚠️ Cannot select invalid object');
37509
37620
  return false;
@@ -37514,7 +37625,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
37514
37625
 
37515
37626
  // Emit selection event with component details
37516
37627
  var componentId = object.name || object.uuid;
37517
- var objectType = ((_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2.objectType) || 'component';
37628
+ var objectType = ((_object$userData3 = object.userData) === null || _object$userData3 === void 0 ? void 0 : _object$userData3.objectType) || 'component';
37518
37629
  this.emit('component-selected', {
37519
37630
  id: componentId,
37520
37631
  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.73
22
+ * @version 0.1.75
23
23
  * @updated 2025-10-22
24
24
  *
25
25
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -938,7 +938,15 @@ var CentralPlantInternals = /*#__PURE__*/function () {
938
938
  componentModel.position.set(position.x, position.y, position.z);
939
939
 
940
940
  // Rotate the component
941
- componentModel.rotation.set(rotation.x, rotation.y, rotation.z);
941
+ if (options.rotation) {
942
+ componentModel.rotation.set(rotation.x, rotation.y, rotation.z);
943
+ } else {
944
+ console.log("\u2139\uFE0F addComponent(): No rotation provided, keeping model default:", {
945
+ x: componentModel.rotation.x,
946
+ y: componentModel.rotation.y,
947
+ z: componentModel.rotation.z
948
+ });
949
+ }
942
950
 
943
951
  // Set user data for identification and management
944
952
  componentModel.userData = {
@@ -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,
@@ -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.73
18
+ * @version 0.1.75
19
19
  * @updated 2025-10-22
20
20
  *
21
21
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -914,7 +914,15 @@ var CentralPlantInternals = /*#__PURE__*/function () {
914
914
  componentModel.position.set(position.x, position.y, position.z);
915
915
 
916
916
  // Rotate the component
917
- componentModel.rotation.set(rotation.x, rotation.y, rotation.z);
917
+ if (options.rotation) {
918
+ componentModel.rotation.set(rotation.x, rotation.y, rotation.z);
919
+ } else {
920
+ console.log("\u2139\uFE0F addComponent(): No rotation provided, keeping model default:", {
921
+ x: componentModel.rotation.x,
922
+ y: componentModel.rotation.y,
923
+ z: componentModel.rotation.z
924
+ });
925
+ }
918
926
 
919
927
  // Set user data for identification and management
920
928
  componentModel.userData = {
@@ -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,
@@ -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.73",
3
+ "version": "0.1.75",
4
4
  "description": "Utility modules for the Central Plant Application",
5
5
  "main": "dist/bundle/index.js",
6
6
  "module": "dist/esm/index.js",