@2112-lab/central-plant 0.1.20 → 0.1.22

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.
@@ -21447,7 +21447,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
21447
21447
  case 0:
21448
21448
  component = this.sceneViewer;
21449
21449
  _context6.p = 1;
21450
- defaultCentralPlantUrl = './mock-data/cp-01-01.json';
21450
+ defaultCentralPlantUrl = process.env.DEFAULT_CENTRAL_PLANT_URL;
21451
21451
  _context6.n = 2;
21452
21452
  return fetch(defaultCentralPlantUrl);
21453
21453
  case 2:
@@ -21600,6 +21600,115 @@ var SceneOperationsManager = /*#__PURE__*/function () {
21600
21600
  });
21601
21601
  }
21602
21602
 
21603
+ /**
21604
+ * Add a new component to the scene data
21605
+ * @param {Object} componentModel - The Three.js component model that was added to the scene
21606
+ * @param {Object} currentSceneData - The current scene data structure
21607
+ * @returns {boolean} True if the component was successfully added to scene data
21608
+ */
21609
+ }, {
21610
+ key: "addComponentToSceneData",
21611
+ value: function addComponentToSceneData(componentModel, currentSceneData) {
21612
+ if (!componentModel || !currentSceneData) {
21613
+ console.error('❌ addComponentToSceneData: Missing componentModel or currentSceneData');
21614
+ return false;
21615
+ }
21616
+ if (!currentSceneData.scene || !currentSceneData.scene.object) {
21617
+ console.error('❌ addComponentToSceneData: Invalid scene data structure');
21618
+ return false;
21619
+ }
21620
+ try {
21621
+ var _componentModel$userD;
21622
+ // Calculate world bounding box for the component
21623
+ var boundingBox = new THREE__namespace.Box3().setFromObject(componentModel);
21624
+
21625
+ // Create scene data entry for the new component
21626
+ var componentSceneData = {
21627
+ uuid: componentModel.uuid,
21628
+ name: componentModel.name,
21629
+ type: 'Group',
21630
+ matrix: componentModel.matrix.elements,
21631
+ position: {
21632
+ x: componentModel.position.x,
21633
+ y: componentModel.position.y,
21634
+ z: componentModel.position.z
21635
+ },
21636
+ rotation: {
21637
+ x: componentModel.rotation.x,
21638
+ y: componentModel.rotation.y,
21639
+ z: componentModel.rotation.z
21640
+ },
21641
+ scale: {
21642
+ x: componentModel.scale.x,
21643
+ y: componentModel.scale.y,
21644
+ z: componentModel.scale.z
21645
+ },
21646
+ userData: _objectSpread2(_objectSpread2({}, componentModel.userData), {}, {
21647
+ worldBoundingBox: {
21648
+ min: boundingBox.min.toArray(),
21649
+ max: boundingBox.max.toArray()
21650
+ }
21651
+ }),
21652
+ children: []
21653
+ };
21654
+
21655
+ // Process children (connectors, etc.) if they exist
21656
+ if (componentModel.children && componentModel.children.length > 0) {
21657
+ componentModel.children.forEach(function (child) {
21658
+ var _child$userData17;
21659
+ if (((_child$userData17 = child.userData) === null || _child$userData17 === void 0 ? void 0 : _child$userData17.componentType) === 'connector') {
21660
+ var _child$geometry5;
21661
+ var childBoundingBox = new THREE__namespace.Box3().setFromObject(child);
21662
+ var childSceneData = {
21663
+ uuid: child.uuid,
21664
+ name: child.name,
21665
+ type: child.type,
21666
+ position: {
21667
+ x: child.position.x,
21668
+ y: child.position.y,
21669
+ z: child.position.z
21670
+ },
21671
+ rotation: {
21672
+ x: child.rotation.x,
21673
+ y: child.rotation.y,
21674
+ z: child.rotation.z
21675
+ },
21676
+ scale: {
21677
+ x: child.scale.x,
21678
+ y: child.scale.y,
21679
+ z: child.scale.z
21680
+ },
21681
+ userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
21682
+ worldBoundingBox: {
21683
+ min: childBoundingBox.min.toArray(),
21684
+ max: childBoundingBox.max.toArray()
21685
+ }
21686
+ }),
21687
+ geometry: ((_child$geometry5 = child.geometry) === null || _child$geometry5 === void 0 ? void 0 : _child$geometry5.uuid) || 'CONNECTOR-GEO'
21688
+ };
21689
+ componentSceneData.children.push(childSceneData);
21690
+ }
21691
+ });
21692
+ }
21693
+
21694
+ // Add the component to the scene data
21695
+ if (!currentSceneData.scene.object.children) {
21696
+ currentSceneData.scene.object.children = [];
21697
+ }
21698
+ currentSceneData.scene.object.children.push(componentSceneData);
21699
+ console.log('✅ addComponentToSceneData: Component added to scene data successfully', {
21700
+ componentId: componentModel.uuid,
21701
+ libraryId: (_componentModel$userD = componentModel.userData) === null || _componentModel$userD === void 0 ? void 0 : _componentModel$userD.libraryId,
21702
+ childrenCount: componentSceneData.children.length,
21703
+ totalSceneChildren: currentSceneData.scene.object.children.length
21704
+ });
21705
+ return true;
21706
+ } catch (error) {
21707
+ console.error('❌ addComponentToSceneData: Error adding component to scene data:', error);
21708
+ return false;
21709
+ }
21710
+ }
21711
+
21603
21712
  /**
21604
21713
  * Update scene data after object transform
21605
21714
  */
@@ -21621,9 +21730,9 @@ var SceneOperationsManager = /*#__PURE__*/function () {
21621
21730
 
21622
21731
  // Also update the corresponding scene data object
21623
21732
  for (var i = 0; i < currentSceneData.scene.object.children.length; i++) {
21624
- var _object$userData4, _child$userData17;
21733
+ var _object$userData4, _child$userData18;
21625
21734
  var child = currentSceneData.scene.object.children[i];
21626
- if (child.uuid === object.uuid || child.uuid === ((_object$userData4 = object.userData) === null || _object$userData4 === void 0 ? void 0 : _object$userData4.originalUuid) || object.uuid === ((_child$userData17 = child.userData) === null || _child$userData17 === void 0 ? void 0 : _child$userData17.originalUuid)) {
21735
+ if (child.uuid === object.uuid || child.uuid === ((_object$userData4 = object.userData) === null || _object$userData4 === void 0 ? void 0 : _object$userData4.originalUuid) || object.uuid === ((_child$userData18 = child.userData) === null || _child$userData18 === void 0 ? void 0 : _child$userData18.originalUuid)) {
21627
21736
  if (!child.userData) child.userData = {};
21628
21737
  child.userData.origin = 'declared';
21629
21738
  break;
@@ -21672,20 +21781,20 @@ var SceneOperationsManager = /*#__PURE__*/function () {
21672
21781
 
21673
21782
  // Update the corresponding child in currentSceneData with the transformed object
21674
21783
  var _loop = function _loop() {
21675
- var _object$userData6, _child$userData18, _object$userData7, _child$userData19;
21784
+ var _object$userData6, _child$userData19, _object$userData7, _child$userData20;
21676
21785
  var child = currentSceneData.scene.object.children[_i2];
21677
21786
  console.log("onTransformEnd child.uuid:", child.uuid);
21678
21787
  // Enhanced matching logic with hardcoded UUID priority
21679
21788
  var isMatch = false;
21680
21789
 
21681
21790
  // Strategy 1: Direct hardcoded UUID match (HIGHEST PRIORITY)
21682
- if (child.uuid === object.uuid || child.uuid === ((_object$userData6 = object.userData) === null || _object$userData6 === void 0 ? void 0 : _object$userData6.originalUuid) || object.uuid === ((_child$userData18 = child.userData) === null || _child$userData18 === void 0 ? void 0 : _child$userData18.originalUuid)) {
21791
+ if (child.uuid === object.uuid || child.uuid === ((_object$userData6 = object.userData) === null || _object$userData6 === void 0 ? void 0 : _object$userData6.originalUuid) || object.uuid === ((_child$userData19 = child.userData) === null || _child$userData19 === void 0 ? void 0 : _child$userData19.originalUuid)) {
21683
21792
  isMatch = true;
21684
21793
  console.log('🎯 Matched by hardcoded UUID');
21685
21794
  }
21686
21795
 
21687
21796
  // Strategy 4: Component type and library ID match
21688
- if (!isMatch && (_object$userData7 = object.userData) !== null && _object$userData7 !== void 0 && _object$userData7.libraryId && (_child$userData19 = child.userData) !== null && _child$userData19 !== void 0 && _child$userData19.libraryId && object.userData.libraryId === child.userData.libraryId) {
21797
+ if (!isMatch && (_object$userData7 = object.userData) !== null && _object$userData7 !== void 0 && _object$userData7.libraryId && (_child$userData20 = child.userData) !== null && _child$userData20 !== void 0 && _child$userData20.libraryId && object.userData.libraryId === child.userData.libraryId) {
21689
21798
  // For library components, also check position similarity
21690
21799
  var positionTolerance = 1.0; // Larger tolerance for main components
21691
21800
  if (child.position && object.position) {
@@ -25336,6 +25445,9 @@ var CentralPlant = /*#__PURE__*/function () {
25336
25445
  lastTransform: null
25337
25446
  };
25338
25447
 
25448
+ // Add component counter for unique ID generation
25449
+ this.componentCounter = 0;
25450
+
25339
25451
  // Set default scene metadata
25340
25452
  this.setDefaultSceneMetadata();
25341
25453
 
@@ -25520,6 +25632,9 @@ var CentralPlant = /*#__PURE__*/function () {
25520
25632
  timestamp: new Date().toISOString()
25521
25633
  });
25522
25634
 
25635
+ // Reset component counter based on imported components to avoid ID conflicts
25636
+ this.resetComponentCounter();
25637
+
25523
25638
  // Set default metadata for imported scene data
25524
25639
  this.setDefaultImportedSceneMetadata(sceneData);
25525
25640
 
@@ -26534,7 +26649,7 @@ var CentralPlant = /*#__PURE__*/function () {
26534
26649
 
26535
26650
  // Perform the translation
26536
26651
  var normalizedAxis = axis.toLowerCase();
26537
- var previousPosition = component.position[normalizedAxis];
26652
+ component.position[normalizedAxis];
26538
26653
  try {
26539
26654
  // Apply the translation
26540
26655
  component.position[normalizedAxis] += value;
@@ -26588,22 +26703,18 @@ var CentralPlant = /*#__PURE__*/function () {
26588
26703
  });
26589
26704
  }
26590
26705
 
26706
+ // If there's a scene operations manager, update scene data
26707
+ if (this.sceneViewer.sceneOperationsManager && this.sceneViewer.currentSceneData) {
26708
+ this.sceneViewer.sceneOperationsManager.updateSceneDataAfterTransform(component, this.sceneViewer.currentSceneData);
26709
+ }
26710
+
26711
+ // if (this.sceneViewer.shouldUpdatePaths && this.sceneViewer.updatePaths) {
26712
+ // this.sceneViewer.updatePaths()
26713
+ // }
26714
+
26591
26715
  // // Update scene data and paths after successful translation
26592
26716
  // this.updatePaths(component)
26593
26717
 
26594
- // Log successful translation
26595
- console.log("\u2705 translate(): Component ".concat(componentId, " translated ").concat(value, " units along ").concat(normalizedAxis.toUpperCase(), "-axis"), {
26596
- componentId: componentId,
26597
- axis: normalizedAxis,
26598
- value: value,
26599
- previousPosition: previousPosition,
26600
- newPosition: component.position[normalizedAxis],
26601
- totalPosition: {
26602
- x: component.position.x.toFixed(3),
26603
- y: component.position.y.toFixed(3),
26604
- z: component.position.z.toFixed(3)
26605
- }
26606
- });
26607
26718
  return component;
26608
26719
  } catch (error) {
26609
26720
  console.error("\u274C translate(): Error translating component ".concat(componentId, ":"), error);
@@ -26620,18 +26731,639 @@ var CentralPlant = /*#__PURE__*/function () {
26620
26731
  return false;
26621
26732
  }
26622
26733
  }
26734
+
26735
+ /**
26736
+ * Generate a unique component ID that doesn't conflict with existing components
26737
+ * @param {string} libraryId - The library identifier for the component type
26738
+ * @returns {string} A unique component ID
26739
+ */
26623
26740
  }, {
26624
- key: "updatePaths",
26625
- value: function updatePaths(component) {
26626
- // If there's a scene operations manager, update scene data
26627
- if (this.sceneViewer.sceneOperationsManager && this.sceneViewer.currentSceneData) {
26628
- this.sceneViewer.sceneOperationsManager.updateSceneDataAfterTransform(component, this.sceneViewer.currentSceneData);
26741
+ key: "generateUniqueComponentId",
26742
+ value: function generateUniqueComponentId(libraryId) {
26743
+ // Get all existing component IDs
26744
+ var existingIds = this.getComponentIds();
26745
+ var existingIdSet = new Set(existingIds);
26746
+ var attempts = 0;
26747
+ var maxAttempts = 1000; // Safety limit to prevent infinite loops
26748
+
26749
+ while (attempts < maxAttempts) {
26750
+ // Generate a candidate ID using the current counter
26751
+ var candidateId = this.utilities.generateUuidFromName(libraryId + '-' + (this.componentCounter + 1));
26752
+
26753
+ // Check if this ID already exists
26754
+ if (!existingIdSet.has(candidateId)) {
26755
+ // ID is unique, increment counter and return it
26756
+ this.componentCounter++;
26757
+ console.log("\u2705 generateUniqueComponentId(): Generated unique ID ".concat(candidateId, " for ").concat(libraryId, " (counter: ").concat(this.componentCounter, ")"));
26758
+ return candidateId;
26759
+ }
26760
+
26761
+ // ID exists, increment counter and try again
26762
+ this.componentCounter++;
26763
+ attempts++;
26764
+ console.warn("\u26A0\uFE0F generateUniqueComponentId(): ID collision detected for ".concat(candidateId, ", trying again (attempt ").concat(attempts, ")"));
26629
26765
  }
26630
26766
 
26631
- // Update paths if pathfinding is enabled and should update paths
26632
- if (this.sceneViewer.shouldUpdatePaths && this.sceneViewer.updatePaths) {
26633
- this.sceneViewer.updatePaths();
26767
+ // Fallback: use timestamp + random number if we can't find a unique ID with counter
26768
+ var fallbackId = this.utilities.generateUuidFromName(libraryId + '-' + Date.now() + '-' + Math.random().toString(36).substring(2, 8));
26769
+ console.warn("\u26A0\uFE0F generateUniqueComponentId(): Max attempts reached, using fallback ID: ".concat(fallbackId));
26770
+ return fallbackId;
26771
+ }
26772
+
26773
+ /**
26774
+ * Reset the component counter based on existing components in the scene
26775
+ * This is useful when loading scenes that already have numbered components
26776
+ */
26777
+ }, {
26778
+ key: "resetComponentCounter",
26779
+ value: function resetComponentCounter() {
26780
+ var existingIds = this.getComponentIds();
26781
+ var maxCounter = 0;
26782
+
26783
+ // Extract counter values from existing component IDs
26784
+ existingIds.forEach(function (id) {
26785
+ // Look for patterns like "PUMP-1", "CHILLER-2", etc.
26786
+ var match = id.match(/-(\d+)(?:-|$)/);
26787
+ if (match) {
26788
+ var counter = parseInt(match[1], 10);
26789
+ if (!isNaN(counter) && counter > maxCounter) {
26790
+ maxCounter = counter;
26791
+ }
26792
+ }
26793
+ });
26794
+
26795
+ // Set the counter to one more than the highest found
26796
+ this.componentCounter = maxCounter;
26797
+ console.log("\uD83D\uDD04 resetComponentCounter(): Counter reset to ".concat(this.componentCounter, " based on ").concat(existingIds.length, " existing components"));
26798
+ }
26799
+
26800
+ /**
26801
+ * Add a new component to the scene using its library ID
26802
+ * @param {string} libraryId - The library identifier for the component type (e.g., 'PUMP', 'CHILLER', 'COOLING-TOWER')
26803
+ * @param {Object} options - Optional configuration for the new component
26804
+ * @param {Object} options.position - Initial position for the component (default: random position within scene bounds)
26805
+ * @param {Object} options.rotation - Initial rotation for the component (default: no rotation)
26806
+ * @param {Object} options.scale - Initial scale for the component (default: 1.0 on all axes)
26807
+ * @param {string} options.customId - Custom identifier for the component (default: auto-generated UUID)
26808
+ * @returns {Object|false} The added component object if successful, false otherwise
26809
+ */
26810
+ }, {
26811
+ key: "addComponent",
26812
+ value: function addComponent(libraryId) {
26813
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
26814
+ // Validate input parameters
26815
+ if (!libraryId || typeof libraryId !== 'string') {
26816
+ console.error('❌ addComponent(): Invalid library ID provided. Must be a non-empty string.');
26817
+ return false;
26634
26818
  }
26819
+
26820
+ // Check if scene viewer is available
26821
+ if (!this.sceneViewer || !this.sceneViewer.scene) {
26822
+ console.error('❌ addComponent(): Scene viewer or scene not available');
26823
+ return false;
26824
+ }
26825
+
26826
+ // Check if component manager is available
26827
+ var componentManager = this.sceneViewer.componentManager;
26828
+ if (!componentManager) {
26829
+ console.error('❌ addComponent(): Component manager not available');
26830
+ return false;
26831
+ }
26832
+
26833
+ // Check if model preloader is available
26834
+ var modelPreloader = this.utilities.modelPreloader;
26835
+ if (!modelPreloader) {
26836
+ console.error('❌ addComponent(): Model preloader not available');
26837
+ return false;
26838
+ }
26839
+ try {
26840
+ // Generate a unique component ID if not provided
26841
+ var componentId = options.customId || this.generateUniqueComponentId(libraryId);
26842
+
26843
+ // Validate that custom IDs don't conflict with existing components
26844
+ if (options.customId) {
26845
+ var existingIds = this.getComponentIds();
26846
+ if (existingIds.includes(options.customId)) {
26847
+ console.error("\u274C addComponent(): Custom ID '".concat(options.customId, "' already exists in scene. Existing IDs:"), existingIds);
26848
+ return false;
26849
+ }
26850
+ }
26851
+
26852
+ // Set default position within scene boundaries if not provided
26853
+ var position = options.position || {
26854
+ x: 0,
26855
+ y: 0,
26856
+ z: 0
26857
+ };
26858
+
26859
+ // Set default rotation if not provided
26860
+ var rotation = options.rotation || {
26861
+ x: 0,
26862
+ y: 0,
26863
+ z: 0
26864
+ };
26865
+ console.log("\uD83D\uDD04 addComponent(): Adding component ".concat(libraryId, " at position:"), position);
26866
+
26867
+ // Get the component data from the preloader's component dictionary
26868
+ if (!modelPreloader.componentDictionary) {
26869
+ console.error("\u274C addComponent(): Component dictionary not available in model preloader");
26870
+ return false;
26871
+ }
26872
+ var componentData = modelPreloader.componentDictionary[libraryId];
26873
+ if (!componentData || !componentData.modelKey) {
26874
+ console.error("\u274C addComponent(): Component data not found for library ID '".concat(libraryId, "'. Available components:"), Object.keys(modelPreloader.componentDictionary));
26875
+ return false;
26876
+ }
26877
+
26878
+ // Get the cached model using the modelKey
26879
+ var cachedModel = modelPreloader.getCachedModelWithDimensions(componentData.modelKey, libraryId);
26880
+ if (!cachedModel) {
26881
+ var status = modelPreloader.getStatus();
26882
+ console.error("\u274C addComponent(): Model for library ID '".concat(libraryId, "' (modelKey: '").concat(componentData.modelKey, "') not found in cache. Cache status:"), {
26883
+ cachedModels: status.cachedModels,
26884
+ totalCached: status.totalCached,
26885
+ isPreloading: status.isPreloading,
26886
+ currentlyLoading: status.currentlyLoading
26887
+ });
26888
+ return false;
26889
+ }
26890
+
26891
+ // Clone the cached model to create a new instance
26892
+ var componentModel = cachedModel;
26893
+
26894
+ // Set the component properties
26895
+ componentModel.uuid = componentId;
26896
+ componentModel.name = libraryId + '_' + componentId.substring(0, 8);
26897
+
26898
+ // Set position and rotation
26899
+ componentModel.position.set(position.x, position.y, position.z);
26900
+ componentModel.rotation.set(rotation.x, rotation.y, rotation.z);
26901
+
26902
+ // Set up component metadata
26903
+ componentModel.userData = {
26904
+ componentType: 'component',
26905
+ libraryId: libraryId,
26906
+ originalUuid: componentId,
26907
+ hardcodedUuid: componentId,
26908
+ addedTimestamp: new Date().toISOString(),
26909
+ addedBy: 'centralPlant.addComponent()',
26910
+ isUserAdded: true,
26911
+ initialPosition: _objectSpread2({}, position),
26912
+ initialRotation: _objectSpread2({}, rotation)
26913
+ };
26914
+
26915
+ // Add the component to the scene
26916
+ this.sceneViewer.scene.add(componentModel);
26917
+
26918
+ // Update matrices to ensure proper positioning
26919
+ componentModel.updateMatrix();
26920
+ componentModel.updateMatrixWorld(true);
26921
+
26922
+ // Add children connectors from component dictionary
26923
+ if (componentData.children && Array.isArray(componentData.children)) {
26924
+ console.log("\uD83D\uDD0C addComponent(): Adding ".concat(componentData.children.length, " connectors for ").concat(libraryId));
26925
+ componentData.children.forEach(function (childData, index) {
26926
+ try {
26927
+ var _childData$userData, _childData$userData2, _childData$userData3;
26928
+ // Create connector geometry (simple sphere for now)
26929
+ var connectorGeometry = new THREE__namespace.SphereGeometry(0.1, 8, 6);
26930
+ var connectorMaterial = new THREE__namespace.MeshPhysicalMaterial({
26931
+ color: 0xC0C0C0,
26932
+ roughness: 0.15,
26933
+ metalness: 0.9,
26934
+ emissive: 0x000000,
26935
+ envMapIntensity: 1.5,
26936
+ transparent: true,
26937
+ opacity: 0.8
26938
+ });
26939
+
26940
+ // Create connector mesh
26941
+ var connectorMesh = new THREE__namespace.Mesh(connectorGeometry, connectorMaterial);
26942
+
26943
+ // Set connector properties from child data
26944
+ if (childData.uuid) {
26945
+ connectorMesh.uuid = "".concat(componentId, "_").concat(childData.uuid);
26946
+ }
26947
+ connectorMesh.name = "".concat(libraryId, "_connector_").concat(index);
26948
+
26949
+ // Set connector position relative to component
26950
+ if (childData.position) {
26951
+ connectorMesh.position.set(childData.position.x || 0, childData.position.y || 0, childData.position.z || 0);
26952
+ }
26953
+
26954
+ // Set connector user data
26955
+ connectorMesh.userData = {
26956
+ componentType: 'connector',
26957
+ parentComponentId: componentId,
26958
+ connectorIndex: index,
26959
+ direction: ((_childData$userData = childData.userData) === null || _childData$userData === void 0 ? void 0 : _childData$userData.direction) || [0, 1, 0],
26960
+ group: ((_childData$userData2 = childData.userData) === null || _childData$userData2 === void 0 ? void 0 : _childData$userData2.group) || null,
26961
+ forExport: ((_childData$userData3 = childData.userData) === null || _childData$userData3 === void 0 ? void 0 : _childData$userData3.forExport) || false,
26962
+ originalChildData: childData
26963
+ };
26964
+
26965
+ // Add connector as child of the component
26966
+ componentModel.add(connectorMesh);
26967
+ console.log("\u2705 Added connector ".concat(index, " to component ").concat(libraryId, ":"), {
26968
+ uuid: connectorMesh.uuid,
26969
+ position: connectorMesh.position,
26970
+ direction: connectorMesh.userData.direction,
26971
+ group: connectorMesh.userData.group
26972
+ });
26973
+ } catch (connectorError) {
26974
+ console.error("\u274C Error creating connector ".concat(index, " for ").concat(libraryId, ":"), connectorError);
26975
+ }
26976
+ });
26977
+ }
26978
+
26979
+ // Notify the component manager about the new component
26980
+ if (componentManager.registerComponent) {
26981
+ componentManager.registerComponent(componentModel);
26982
+ }
26983
+
26984
+ // Update scene data if available
26985
+ if (this.sceneViewer.sceneOperationsManager && this.sceneViewer.currentSceneData) {
26986
+ var success = this.sceneViewer.sceneOperationsManager.addComponentToSceneData(componentModel, this.sceneViewer.currentSceneData);
26987
+ if (success) {
26988
+ console.log('✅ Component successfully added to scene data');
26989
+ } else {
26990
+ console.warn('⚠️ Failed to add component to scene data');
26991
+ }
26992
+ }
26993
+
26994
+ // Record the add operation in metadata
26995
+ this.recordComponentAddition(componentModel, libraryId, options);
26996
+
26997
+ // Log successful addition
26998
+ console.log("\u2705 addComponent(): Component ".concat(libraryId, " added successfully"), componentModel);
26999
+ return componentModel;
27000
+ } catch (error) {
27001
+ console.error("\u274C addComponent(): Error adding component ".concat(libraryId, ":"), error);
27002
+ return false;
27003
+ }
27004
+ }
27005
+
27006
+ /**
27007
+ * Record component addition in metadata for tracking and potential undo
27008
+ * @param {Object} component - The added component
27009
+ * @param {string} libraryId - The library ID used
27010
+ * @param {Object} options - The options used for addition
27011
+ */
27012
+ }, {
27013
+ key: "recordComponentAddition",
27014
+ value: function recordComponentAddition(component, libraryId, options) {
27015
+ // Get existing addition history or create new array
27016
+ var additionHistory = this.getMetadata('componentAdditionHistory') || [];
27017
+ var additionRecord = {
27018
+ componentId: component.uuid,
27019
+ libraryId: libraryId,
27020
+ position: {
27021
+ x: component.position.x,
27022
+ y: component.position.y,
27023
+ z: component.position.z
27024
+ },
27025
+ rotation: {
27026
+ x: component.rotation.x,
27027
+ y: component.rotation.y,
27028
+ z: component.rotation.z
27029
+ },
27030
+ scale: {
27031
+ x: component.scale.x,
27032
+ y: component.scale.y,
27033
+ z: component.scale.z
27034
+ },
27035
+ options: options,
27036
+ timestamp: new Date().toISOString(),
27037
+ sessionId: this.getMetadata('sessionId') || 'unknown'
27038
+ };
27039
+
27040
+ // Add to history (keep only last 50 additions to prevent memory issues)
27041
+ additionHistory.push(additionRecord);
27042
+ if (additionHistory.length > 50) {
27043
+ additionHistory.shift(); // Remove oldest entry
27044
+ }
27045
+
27046
+ // Update metadata
27047
+ this.setMetadata('componentAdditionHistory', additionHistory);
27048
+ this.setMetadata('lastComponentAddition', additionRecord);
27049
+ console.log('📝 Component addition recorded in metadata:', {
27050
+ componentId: component.uuid,
27051
+ libraryId: libraryId,
27052
+ totalAdditions: additionHistory.length
27053
+ });
27054
+ }
27055
+
27056
+ /**
27057
+ * Add a connection between two connector IDs to the connections list
27058
+ * This method adds a new connection to the currentSceneData.connections array
27059
+ * @param {string} fromConnectorId - The ID of the source connector
27060
+ * @param {string} toConnectorId - The ID of the destination connector
27061
+ * @returns {Object|false} The added connection object if successful, false otherwise
27062
+ */
27063
+ }, {
27064
+ key: "addConnection",
27065
+ value: function addConnection(fromConnectorId, toConnectorId) {
27066
+ // Validate input parameters
27067
+ if (!fromConnectorId || typeof fromConnectorId !== 'string') {
27068
+ console.error('❌ addConnection(): Invalid fromConnectorId provided. Must be a non-empty string:', fromConnectorId);
27069
+ return false;
27070
+ }
27071
+ if (!toConnectorId || typeof toConnectorId !== 'string') {
27072
+ console.error('❌ addConnection(): Invalid toConnectorId provided. Must be a non-empty string:', toConnectorId);
27073
+ return false;
27074
+ }
27075
+
27076
+ // Check if the same connector IDs (avoid self-connection)
27077
+ if (fromConnectorId === toConnectorId) {
27078
+ console.error('❌ addConnection(): Cannot connect a connector to itself:', fromConnectorId);
27079
+ return false;
27080
+ }
27081
+
27082
+ // Check if scene viewer and currentSceneData are available
27083
+ if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
27084
+ console.error('❌ addConnection(): Scene viewer or current scene data not available');
27085
+ return false;
27086
+ }
27087
+ try {
27088
+ // Initialize connections array if it doesn't exist
27089
+ if (!this.sceneViewer.currentSceneData.connections) {
27090
+ this.sceneViewer.currentSceneData.connections = [];
27091
+ console.log('🔄 addConnection(): Initialized connections array in currentSceneData');
27092
+ }
27093
+
27094
+ // Check if connection already exists
27095
+ var existingConnection = this.sceneViewer.currentSceneData.connections.find(function (connection) {
27096
+ return connection.from === fromConnectorId && connection.to === toConnectorId || connection.from === toConnectorId && connection.to === fromConnectorId;
27097
+ });
27098
+ if (existingConnection) {
27099
+ console.warn("\u26A0\uFE0F addConnection(): Connection already exists between ".concat(fromConnectorId, " and ").concat(toConnectorId));
27100
+ return existingConnection;
27101
+ }
27102
+
27103
+ // Create the new connection object
27104
+ var newConnection = {
27105
+ from: fromConnectorId,
27106
+ to: toConnectorId
27107
+ };
27108
+
27109
+ // Add the connection to the connections array
27110
+ this.sceneViewer.currentSceneData.connections.push(newConnection);
27111
+
27112
+ // Log successful addition
27113
+ console.log("\u2705 addConnection(): Connection added successfully", {
27114
+ from: fromConnectorId,
27115
+ to: toConnectorId,
27116
+ totalConnections: this.sceneViewer.currentSceneData.connections.length
27117
+ });
27118
+
27119
+ // Record the connection addition in metadata for tracking
27120
+ this.recordConnectionAddition(newConnection);
27121
+ return newConnection;
27122
+ } catch (error) {
27123
+ console.error("\u274C addConnection(): Error adding connection from ".concat(fromConnectorId, " to ").concat(toConnectorId, ":"), error);
27124
+ return false;
27125
+ }
27126
+ }
27127
+
27128
+ /**
27129
+ * Record connection addition in metadata for tracking and potential undo
27130
+ * @param {Object} connection - The added connection object
27131
+ */
27132
+ }, {
27133
+ key: "recordConnectionAddition",
27134
+ value: function recordConnectionAddition(connection) {
27135
+ try {
27136
+ // Get existing connection history or create new array
27137
+ var connectionHistory = this.getMetadata('connectionAdditionHistory') || [];
27138
+ var connectionRecord = {
27139
+ from: connection.from,
27140
+ to: connection.to,
27141
+ timestamp: new Date().toISOString(),
27142
+ addedBy: 'centralPlant.addConnection()'
27143
+ };
27144
+
27145
+ // Add to history
27146
+ connectionHistory.push(connectionRecord);
27147
+
27148
+ // Store updated history (keep last 100 entries to prevent memory issues)
27149
+ this.setMetadata('connectionAdditionHistory', connectionHistory.slice(-100));
27150
+
27151
+ // Update connection statistics
27152
+ var stats = this.getMetadata('connectionStats') || {
27153
+ totalAdded: 0
27154
+ };
27155
+ stats.totalAdded = (stats.totalAdded || 0) + 1;
27156
+ stats.lastAddedTimestamp = new Date().toISOString();
27157
+ this.setMetadata('connectionStats', stats);
27158
+ } catch (error) {
27159
+ console.warn('⚠️ Failed to record connection addition in metadata:', error);
27160
+ }
27161
+ }
27162
+
27163
+ /**
27164
+ * Get all current connections from the scene data
27165
+ * @returns {Array} Array of connection objects or empty array if none exist
27166
+ */
27167
+ }, {
27168
+ key: "getConnections",
27169
+ value: function getConnections() {
27170
+ if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
27171
+ console.warn('⚠️ getConnections(): Scene viewer or current scene data not available');
27172
+ return [];
27173
+ }
27174
+ return this.sceneViewer.currentSceneData.connections || [];
27175
+ }
27176
+
27177
+ /**
27178
+ * Get all connector IDs from the currentSceneData
27179
+ * @returns {Array} Array of all connector ID strings, or empty array if none exist
27180
+ */
27181
+ }, {
27182
+ key: "getAllConnectorIds",
27183
+ value: function getAllConnectorIds() {
27184
+ if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
27185
+ console.warn('⚠️ getAllConnectorIds(): Scene viewer or current scene data not available');
27186
+ return [];
27187
+ }
27188
+ var allConnectorIds = [];
27189
+ var sceneData = this.sceneViewer.currentSceneData;
27190
+
27191
+ // Check if scene data has the expected structure
27192
+ if (!sceneData.scene || !sceneData.scene.object || !sceneData.scene.object.children) {
27193
+ console.warn('⚠️ getAllConnectorIds(): Invalid scene data structure');
27194
+ return [];
27195
+ }
27196
+
27197
+ // Traverse through all components in the scene data
27198
+ sceneData.scene.object.children.forEach(function (component) {
27199
+ // Each component may have connector children
27200
+ if (component.children && Array.isArray(component.children)) {
27201
+ component.children.forEach(function (child) {
27202
+ // Check if this child is a connector
27203
+ if (child.userData && child.userData.componentType === 'connector' && child.uuid) {
27204
+ allConnectorIds.push(child.uuid);
27205
+ }
27206
+ });
27207
+ }
27208
+ });
27209
+ console.log("\uD83D\uDD0C getAllConnectorIds(): Found ".concat(allConnectorIds.length, " total connector IDs in currentSceneData"));
27210
+ return allConnectorIds;
27211
+ }
27212
+
27213
+ /**
27214
+ * Get all available connector IDs that are not currently used in connections
27215
+ * @returns {Array} Array of available connector ID strings, or empty array if none exist
27216
+ */
27217
+ }, {
27218
+ key: "getAvailableConnections",
27219
+ value: function getAvailableConnections() {
27220
+ if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
27221
+ console.warn('⚠️ getAvailableConnections(): Scene viewer or current scene data not available');
27222
+ return [];
27223
+ }
27224
+
27225
+ // Get all connector IDs from the currentSceneData
27226
+ var allConnectorIds = this.getAllConnectorIds();
27227
+
27228
+ // Get existing connections
27229
+ var existingConnections = this.getConnections();
27230
+
27231
+ // Collect all connector IDs that are already used in connections
27232
+ var usedConnectorIds = new Set();
27233
+ existingConnections.forEach(function (connection) {
27234
+ if (connection.from) usedConnectorIds.add(connection.from);
27235
+ if (connection.to) usedConnectorIds.add(connection.to);
27236
+ });
27237
+
27238
+ // Filter out used connectors to get only available ones
27239
+ var availableConnectorIds = allConnectorIds.filter(function (id) {
27240
+ return !usedConnectorIds.has(id);
27241
+ });
27242
+ console.log("\uD83D\uDD0C getAvailableConnections(): Found ".concat(availableConnectorIds.length, " available connectors out of ").concat(allConnectorIds.length, " total connectors"));
27243
+ console.log('📋 Available connector IDs:', availableConnectorIds);
27244
+ return availableConnectorIds;
27245
+ }
27246
+
27247
+ /**
27248
+ * Get all component IDs from the scene
27249
+ * @returns {Array} Array of component ID strings, or empty array if none exist
27250
+ */
27251
+ }, {
27252
+ key: "getComponentIds",
27253
+ value: function getComponentIds() {
27254
+ if (!this.sceneViewer || !this.sceneViewer.scene) {
27255
+ console.warn('⚠️ getComponentIds(): Scene viewer or scene not available');
27256
+ return [];
27257
+ }
27258
+ var componentIds = [];
27259
+
27260
+ // Traverse the scene to find all components
27261
+ this.sceneViewer.scene.traverse(function (child) {
27262
+ if (child.userData && child.userData.componentType === 'component') {
27263
+ var id = child.uuid || child.userData.originalUuid || child.name;
27264
+ if (id) {
27265
+ componentIds.push(id);
27266
+ }
27267
+ }
27268
+ });
27269
+ console.log("\uD83D\uDCCB getComponentIds(): Found ".concat(componentIds.length, " component IDs in scene:"), componentIds);
27270
+ return componentIds;
27271
+ }
27272
+
27273
+ /**
27274
+ * Remove a connection between two connector IDs from the connections list
27275
+ * @param {string} fromConnectorId - The ID of the source connector
27276
+ * @param {string} toConnectorId - The ID of the destination connector
27277
+ * @returns {boolean} True if connection was removed, false otherwise
27278
+ */
27279
+ }, {
27280
+ key: "removeConnection",
27281
+ value: function removeConnection(fromConnectorId, toConnectorId) {
27282
+ // Validate input parameters
27283
+ if (!fromConnectorId || typeof fromConnectorId !== 'string') {
27284
+ console.error('❌ removeConnection(): Invalid fromConnectorId provided. Must be a non-empty string:', fromConnectorId);
27285
+ return false;
27286
+ }
27287
+ if (!toConnectorId || typeof toConnectorId !== 'string') {
27288
+ console.error('❌ removeConnection(): Invalid toConnectorId provided. Must be a non-empty string:', toConnectorId);
27289
+ return false;
27290
+ }
27291
+
27292
+ // Check if scene viewer and currentSceneData are available
27293
+ if (!this.sceneViewer || !this.sceneViewer.currentSceneData || !this.sceneViewer.currentSceneData.connections) {
27294
+ console.error('❌ removeConnection(): Scene viewer, current scene data, or connections array not available');
27295
+ return false;
27296
+ }
27297
+ try {
27298
+ // Find the connection to remove (check both directions)
27299
+ var connectionIndex = this.sceneViewer.currentSceneData.connections.findIndex(function (connection) {
27300
+ return connection.from === fromConnectorId && connection.to === toConnectorId || connection.from === toConnectorId && connection.to === fromConnectorId;
27301
+ });
27302
+ if (connectionIndex === -1) {
27303
+ console.warn("\u26A0\uFE0F removeConnection(): Connection not found between ".concat(fromConnectorId, " and ").concat(toConnectorId));
27304
+ return false;
27305
+ }
27306
+
27307
+ // Remove the connection
27308
+ var removedConnection = this.sceneViewer.currentSceneData.connections.splice(connectionIndex, 1)[0];
27309
+
27310
+ // Log successful removal
27311
+ console.log("\u2705 removeConnection(): Connection removed successfully", {
27312
+ from: removedConnection.from,
27313
+ to: removedConnection.to,
27314
+ remainingConnections: this.sceneViewer.currentSceneData.connections.length
27315
+ });
27316
+
27317
+ // Record the connection removal in metadata
27318
+ this.recordConnectionRemoval(removedConnection);
27319
+ return true;
27320
+ } catch (error) {
27321
+ console.error("\u274C removeConnection(): Error removing connection from ".concat(fromConnectorId, " to ").concat(toConnectorId, ":"), error);
27322
+ return false;
27323
+ }
27324
+ }
27325
+
27326
+ /**
27327
+ * Record connection removal in metadata for tracking
27328
+ * @param {Object} connection - The removed connection object
27329
+ */
27330
+ }, {
27331
+ key: "recordConnectionRemoval",
27332
+ value: function recordConnectionRemoval(connection) {
27333
+ try {
27334
+ // Get existing removal history or create new array
27335
+ var removalHistory = this.getMetadata('connectionRemovalHistory') || [];
27336
+ var removalRecord = {
27337
+ from: connection.from,
27338
+ to: connection.to,
27339
+ timestamp: new Date().toISOString(),
27340
+ removedBy: 'centralPlant.removeConnection()'
27341
+ };
27342
+
27343
+ // Add to history
27344
+ removalHistory.push(removalRecord);
27345
+
27346
+ // Store updated history (keep last 100 entries to prevent memory issues)
27347
+ this.setMetadata('connectionRemovalHistory', removalHistory.slice(-100));
27348
+
27349
+ // Update connection statistics
27350
+ var stats = this.getMetadata('connectionStats') || {
27351
+ totalAdded: 0,
27352
+ totalRemoved: 0
27353
+ };
27354
+ stats.totalRemoved = (stats.totalRemoved || 0) + 1;
27355
+ stats.lastRemovedTimestamp = new Date().toISOString();
27356
+ this.setMetadata('connectionStats', stats);
27357
+ } catch (error) {
27358
+ console.warn('⚠️ Failed to record connection removal in metadata:', error);
27359
+ }
27360
+ }
27361
+ }, {
27362
+ key: "updatePaths",
27363
+ value: function updatePaths() {
27364
+ var componentId = this.sceneViewer.currentSceneData.scene.object.children[0].uuid;
27365
+ this.translate(componentId, "x", 0);
27366
+ this.sceneViewer.updatePaths();
26635
27367
  }
26636
27368
  }]);
26637
27369
  }();