@2112-lab/central-plant 0.1.78 → 0.1.80

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.
@@ -19,7 +19,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
19
19
  * Initialize the CentralPlant manager
20
20
  *
21
21
  * @constructor
22
- * @version 0.1.78
22
+ * @version 0.1.80
23
23
  * @updated 2025-10-22
24
24
  *
25
25
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -23,6 +23,7 @@ var animationManager = require('../managers/scene/animationManager.js');
23
23
  var cameraControlsManager = require('../managers/controls/cameraControlsManager.js');
24
24
  var componentDragManager = require('../managers/controls/componentDragManager.js');
25
25
  var sceneTooltipsManager = require('../managers/scene/sceneTooltipsManager.js');
26
+ var componentTooltipManager = require('../managers/scene/componentTooltipManager.js');
26
27
  var viewport2DManager = require('../managers/scene/viewport2DManager.js');
27
28
  var nameUtils = require('../utils/nameUtils.js');
28
29
  var modelPreloader = require('../rendering/modelPreloader.js');
@@ -175,6 +176,11 @@ var CentralPlantInternals = /*#__PURE__*/function () {
175
176
  this.centralPlant.managers.tooltipsManager = new sceneTooltipsManager.SceneTooltipsManager(this.centralPlant.sceneViewer.$refs.container, this.centralPlant.sceneViewer.camera, this.centralPlant.sceneViewer.scene);
176
177
  this.centralPlant.sceneViewer.tooltipsManager = this.centralPlant.managers.tooltipsManager;
177
178
  console.log('🔍 Tooltip manager initialized:', this.centralPlant.managers.tooltipsManager);
179
+
180
+ // Initialize the component tooltip manager (screen-space tooltip on selection)
181
+ this.centralPlant.managers.componentTooltipManager = new componentTooltipManager.ComponentTooltipManager(this.centralPlant.sceneViewer);
182
+ this.centralPlant.sceneViewer.componentTooltipManager = this.centralPlant.managers.componentTooltipManager;
183
+ console.log('🔍 Component tooltip manager initialized');
178
184
  }
179
185
  }
180
186
 
@@ -925,8 +931,21 @@ var CentralPlantInternals = /*#__PURE__*/function () {
925
931
  // Clone the cached model to create a new instance
926
932
  var componentModel = cachedModel;
927
933
 
928
- // Set the component properties
929
- componentModel.uuid = componentId;
934
+ // Clone materials to isolate this component instance from the model cache.
935
+ // Without this, shared materials would cause visual side-effects when one
936
+ // component's material is modified (e.g., selection highlighting).
937
+ componentModel.traverse(function (child) {
938
+ if (child.isMesh && child.material) {
939
+ if (Array.isArray(child.material)) {
940
+ child.material = child.material.map(function (m) {
941
+ return m.clone();
942
+ });
943
+ } else {
944
+ child.material = child.material.clone();
945
+ }
946
+ }
947
+ });
948
+
930
949
  // Set the component properties
931
950
  componentModel.uuid = componentId;
932
951
 
@@ -102,7 +102,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
102
102
  this.centralPlant.attachToComponent();
103
103
 
104
104
  // Sync our managers tracking object after attachment
105
- managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager']; // Populate our managers tracking object
105
+ managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
106
106
  managerKeys.forEach(function (key) {
107
107
  if (_this2[key]) {
108
108
  _this2.managers[key] = _this2[key];
@@ -380,6 +380,10 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
380
380
  this.transformManager.on({
381
381
  onModeChange: this.onModeChange.bind(this),
382
382
  onSelectionChanged: function onSelectionChanged(object) {
383
+ // Update the component tooltip on selection changes
384
+ if (_this4.componentTooltipManager) {
385
+ _this4.componentTooltipManager.onSelectionChanged(object);
386
+ }
383
387
  if (object) {
384
388
  var _object$userData;
385
389
  // Object selected
@@ -805,6 +809,12 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
805
809
  this.tooltipsManager = null;
806
810
  }
807
811
 
812
+ // Clean up component tooltip manager
813
+ if (this.componentTooltipManager) {
814
+ this.componentTooltipManager.dispose('ComponentTooltipManager');
815
+ this.componentTooltipManager = null;
816
+ }
817
+
808
818
  // Fallback cleanup if Three.js resource manager not available
809
819
  if (!this.threeJSResourceManager) {
810
820
  // Fallback cleanup if disposal manager not available
@@ -11,6 +11,7 @@ var sceneInitializationManager = require('./managers/scene/sceneInitializationMa
11
11
  var sceneOperationsManager = require('./managers/scene/sceneOperationsManager.js');
12
12
  var sceneExportManager = require('./managers/scene/sceneExportManager.js');
13
13
  var sceneTooltipsManager = require('./managers/scene/sceneTooltipsManager.js');
14
+ var componentTooltipManager = require('./managers/scene/componentTooltipManager.js');
14
15
  var sceneHierarchyManager = require('./managers/scene/sceneHierarchyManager.js');
15
16
  var componentManager = require('./managers/components/componentManager.js');
16
17
  var animationManager = require('./managers/scene/animationManager.js');
@@ -58,6 +59,7 @@ exports.SceneInitializationManager = sceneInitializationManager.SceneInitializat
58
59
  exports.SceneOperationsManager = sceneOperationsManager.SceneOperationsManager;
59
60
  exports.SceneExportManager = sceneExportManager.SceneExportManager;
60
61
  exports.SceneTooltipsManager = sceneTooltipsManager.SceneTooltipsManager;
62
+ exports.ComponentTooltipManager = componentTooltipManager.ComponentTooltipManager;
61
63
  exports.SceneHierarchyManager = sceneHierarchyManager.SceneHierarchyManager;
62
64
  exports.ComponentManager = componentManager.ComponentManager;
63
65
  exports.AnimationManager = animationManager.AnimationManager;
@@ -252,7 +252,10 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
252
252
  }
253
253
  this.dragData.previewObject = cachedModel.clone();
254
254
 
255
- // Clone materials to avoid affecting other objects
255
+ // Clone geometries and materials to fully isolate the preview from the cache.
256
+ // Without this, disposing the preview would invalidate shared GPU buffers
257
+ // and cause the scene to go white.
258
+ this._cloneGeometries(this.dragData.previewObject);
256
259
  this._cloneMaterials(this.dragData.previewObject);
257
260
 
258
261
  // Store original colors BEFORE making transparent
@@ -391,6 +394,7 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
391
394
  return _context3.a(3, 11);
392
395
  case 9:
393
396
  deviceModel = cachedDevice.clone();
397
+ this._cloneGeometries(deviceModel);
394
398
  this._cloneMaterials(deviceModel);
395
399
  this._storeOriginalColors(deviceModel);
396
400
  deviceModel.userData = {
@@ -443,16 +447,38 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
443
447
  if (Array.isArray(child.material)) {
444
448
  // Handle material arrays
445
449
  child.material = child.material.map(function (material) {
446
- return material.clone();
450
+ var cloned = material.clone();
451
+ cloned.userData._isClonedMaterial = true;
452
+ return cloned;
447
453
  });
448
454
  } else {
449
455
  // Handle single materials
450
456
  child.material = child.material.clone();
457
+ child.material.userData._isClonedMaterial = true;
451
458
  }
452
459
  }
453
460
  });
454
461
  }
455
462
 
463
+ /**
464
+ * Clone all geometries in an object hierarchy to avoid shared geometry buffer issues.
465
+ * Three.js Object3D.clone() shares geometry references between the original and clone.
466
+ * Disposing shared geometry invalidates GPU buffers for ALL objects using that geometry,
467
+ * which causes the scene to go white. This method gives each mesh its own geometry copy.
468
+ * @param {THREE.Object3D} object - The object to clone geometries for
469
+ * @private
470
+ */
471
+ }, {
472
+ key: "_cloneGeometries",
473
+ value: function _cloneGeometries(object) {
474
+ object.traverse(function (child) {
475
+ if (child.isMesh && child.geometry) {
476
+ child.geometry = child.geometry.clone();
477
+ child.userData._isClonedGeometry = true;
478
+ }
479
+ });
480
+ }
481
+
456
482
  /**
457
483
  * Store original colors from all materials in an object hierarchy
458
484
  * @param {THREE.Object3D} object - The object to store colors from
@@ -831,18 +857,27 @@ var ComponentDragManager = /*#__PURE__*/function (_BaseDisposable) {
831
857
  if (this.dragData.previewObject) {
832
858
  this.sceneViewer.scene.remove(this.dragData.previewObject);
833
859
 
834
- // Dispose of geometry and materials properly
860
+ // Dispose of CLONED geometry and materials only.
861
+ // Both geometries and materials were cloned during preview creation
862
+ // via _cloneGeometries() and _cloneMaterials(), so they are safe to dispose.
863
+ // IMPORTANT: Never dispose geometry/materials that are shared with the model cache.
835
864
  this.dragData.previewObject.traverse(function (child) {
836
- if (child.geometry) {
837
- child.geometry.dispose();
838
- }
839
- if (child.material) {
840
- if (Array.isArray(child.material)) {
841
- child.material.forEach(function (material) {
842
- return material.dispose();
843
- });
844
- } else {
845
- child.material.dispose();
865
+ if (child.isMesh) {
866
+ // Only dispose geometry if it was cloned for this preview
867
+ if (child.geometry && child.userData._isClonedGeometry) {
868
+ child.geometry.dispose();
869
+ }
870
+ // Only dispose material if it was cloned for this preview
871
+ if (child.material) {
872
+ if (Array.isArray(child.material)) {
873
+ child.material.forEach(function (material) {
874
+ if (material.userData._isClonedMaterial) {
875
+ material.dispose();
876
+ }
877
+ });
878
+ } else if (child.material.userData._isClonedMaterial) {
879
+ child.material.dispose();
880
+ }
846
881
  }
847
882
  }
848
883
  });