@2112-lab/central-plant 0.3.35 → 0.3.37

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.
@@ -11650,7 +11650,8 @@ var SceneExportManager = /*#__PURE__*/function () {
11650
11650
  }, {
11651
11651
  key: "exportSceneData",
11652
11652
  value: function exportSceneData() {
11653
- var _this = this;
11653
+ var _this = this,
11654
+ _this$sceneViewer$cur2;
11654
11655
  console.log('📤 Starting scene export...');
11655
11656
  if (!this.sceneViewer.scene) {
11656
11657
  console.warn('⚠️ No scene available for export');
@@ -11862,6 +11863,12 @@ var SceneExportManager = /*#__PURE__*/function () {
11862
11863
  children: sceneChildren
11863
11864
  }
11864
11865
  };
11866
+
11867
+ // Preserve cross-component behaviors authored in the Behavior window
11868
+ var sceneBehaviors = (_this$sceneViewer$cur2 = this.sceneViewer.currentSceneData) === null || _this$sceneViewer$cur2 === void 0 ? void 0 : _this$sceneViewer$cur2.behaviors;
11869
+ if (sceneBehaviors && sceneBehaviors.length > 0) {
11870
+ exportData.behaviors = sceneBehaviors;
11871
+ }
11865
11872
  console.log('✅ Scene export completed:', exportData);
11866
11873
  console.log("\uD83D\uDCCA Exported ".concat(sceneChildren.length, " components and ").concat(exportData.connections.length, " connections"));
11867
11874
  return exportData;
@@ -11927,7 +11934,7 @@ var SceneExportManager = /*#__PURE__*/function () {
11927
11934
  }, {
11928
11935
  key: "getExportMetadata",
11929
11936
  value: function getExportMetadata() {
11930
- var _this$sceneViewer$cur2;
11937
+ var _this$sceneViewer$cur3;
11931
11938
  if (!this.sceneViewer.scene) {
11932
11939
  return null;
11933
11940
  }
@@ -11938,7 +11945,7 @@ var SceneExportManager = /*#__PURE__*/function () {
11938
11945
  return {
11939
11946
  totalObjects: objectCount,
11940
11947
  hasCurrentSceneData: !!this.sceneViewer.currentSceneData,
11941
- connectionsCount: ((_this$sceneViewer$cur2 = this.sceneViewer.currentSceneData) === null || _this$sceneViewer$cur2 === void 0 || (_this$sceneViewer$cur2 = _this$sceneViewer$cur2.connections) === null || _this$sceneViewer$cur2 === void 0 ? void 0 : _this$sceneViewer$cur2.length) || 0,
11948
+ connectionsCount: ((_this$sceneViewer$cur3 = this.sceneViewer.currentSceneData) === null || _this$sceneViewer$cur3 === void 0 || (_this$sceneViewer$cur3 = _this$sceneViewer$cur3.connections) === null || _this$sceneViewer$cur3 === void 0 ? void 0 : _this$sceneViewer$cur3.length) || 0,
11942
11949
  exportTimestamp: new Date().toISOString()
11943
11950
  };
11944
11951
  }
@@ -19286,17 +19293,14 @@ var ModelPreloader = /*#__PURE__*/function () {
19286
19293
  _context3.n = 1;
19287
19294
  break;
19288
19295
  }
19289
- console.log("\uD83C\uDFAF Model ".concat(modelKey, " already cached, skipping"));
19290
19296
  return _context3.a(2, this.modelCache.get(modelKey));
19291
19297
  case 1:
19292
19298
  if (!this.loadingPromises.has(modelKey)) {
19293
19299
  _context3.n = 2;
19294
19300
  break;
19295
19301
  }
19296
- console.log("\u23F3 Model ".concat(modelKey, " already loading, waiting for completion"));
19297
19302
  return _context3.a(2, this.loadingPromises.get(modelKey));
19298
19303
  case 2:
19299
- console.log("\uD83D\uDD04 Starting preload of GLB model: ".concat(modelKey));
19300
19304
  loadPromise = new Promise(/*#__PURE__*/function () {
19301
19305
  var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(resolve, reject) {
19302
19306
  var modelPath, _t;
@@ -19312,7 +19316,6 @@ var ModelPreloader = /*#__PURE__*/function () {
19312
19316
  return _this2.urlResolver(modelKey);
19313
19317
  case 2:
19314
19318
  modelPath = _context2.v;
19315
- console.log("\uD83D\uDD17 Resolved URL for ".concat(modelKey, ":"), modelPath.substring(0, 100) + '...');
19316
19319
  _context2.n = 4;
19317
19320
  break;
19318
19321
  case 3:
@@ -19326,11 +19329,9 @@ var ModelPreloader = /*#__PURE__*/function () {
19326
19329
  break;
19327
19330
  case 5:
19328
19331
  modelPath = "".concat(_this2.modelsBasePath).concat(modelKey);
19329
- console.log("\uD83D\uDCC2 Loading from: ".concat(modelPath));
19330
19332
  case 6:
19331
19333
  // Load GLB model
19332
19334
  _this2.gltfLoader.load(modelPath, function (gltf) {
19333
- console.log("\u2705 Successfully preloaded GLB model: ".concat(modelKey));
19334
19335
  // Cache the scene for future use
19335
19336
  _this2.modelCache.set(modelKey, gltf.scene);
19336
19337
 
@@ -19349,13 +19350,6 @@ var ModelPreloader = /*#__PURE__*/function () {
19349
19350
  resolve(gltf.scene);
19350
19351
  }, function (progress) {
19351
19352
  // Optional: track loading progress
19352
- if (progress.lengthComputable) {
19353
- var percentage = progress.loaded / progress.total * 100;
19354
- if (percentage % 25 === 0) {
19355
- // Log every 25%
19356
- console.log("\uD83D\uDCCA Loading GLB ".concat(modelKey, ": ").concat(percentage.toFixed(0), "%"));
19357
- }
19358
- }
19359
19353
  }, function (error) {
19360
19354
  console.error("\u274C Failed to preload GLB model ".concat(modelKey, ":"), error);
19361
19355
  // Remove from loading promises
@@ -19393,13 +19387,10 @@ var ModelPreloader = /*#__PURE__*/function () {
19393
19387
  value: function getCachedModel(modelKey) {
19394
19388
  var useIndexedGeometry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
19395
19389
  if (this.modelCache.has(modelKey)) {
19396
- console.log("\uD83C\uDFAF Returning cached model: ".concat(modelKey));
19397
19390
  var cachedData = this.modelCache.get(modelKey);
19398
19391
 
19399
19392
  // Handle OBJ models with processed geometry
19400
19393
  if (cachedData && cachedData.isObjModel && useIndexedGeometry && cachedData.processedGeometry) {
19401
- console.log("\uD83D\uDD27 Using indexed BufferGeometry for OBJ: ".concat(modelKey));
19402
-
19403
19394
  // Create a mesh from the processed indexed geometry
19404
19395
  var mesh = new THREE__namespace.Mesh(cachedData.processedGeometry.clone(), cachedData.materials.clone());
19405
19396
 
@@ -19635,7 +19626,7 @@ var ModelPreloader = /*#__PURE__*/function () {
19635
19626
  }
19636
19627
 
19637
19628
  // Model not cached, need to load it
19638
- console.log("\uD83D\uDD04 Loading model for library ID ".concat(libraryId, ": ").concat(modelKey));
19629
+ // Loading model for library ID
19639
19630
  this.preloadSingleModel(modelKey).then(function (model) {
19640
19631
  if (model) {
19641
19632
  var _clonedModel = model.clone();
@@ -20302,7 +20293,7 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
20302
20293
  value: (function () {
20303
20294
  var _extendComponentDictionary = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(additionalComponents) {
20304
20295
  var _this3 = this;
20305
- var _this$sceneViewer, newComponents, skippedCount, addedCount, modelPreloader, _t;
20296
+ var _this$sceneViewer, newComponents, modelPreloader, _t;
20306
20297
  return _regenerator().w(function (_context3) {
20307
20298
  while (1) switch (_context3.n) {
20308
20299
  case 0:
@@ -20326,7 +20317,6 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
20326
20317
  _context3.p = 3;
20327
20318
  // Filter out components that already exist in the dictionary (deduplication)
20328
20319
  newComponents = {};
20329
- skippedCount = 0;
20330
20320
  Object.entries(additionalComponents).forEach(function (_ref3) {
20331
20321
  var _ref4 = _slicedToArray(_ref3, 2),
20332
20322
  key = _ref4[0],
@@ -20334,13 +20324,12 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
20334
20324
  if (!_this3.componentDictionary[key]) {
20335
20325
  newComponents[key] = component;
20336
20326
  } else {
20337
- skippedCount++;
20338
20327
  console.log("\u26A0\uFE0F Skipping duplicate component: ".concat(key, " (").concat(component.name || 'unnamed', ")"));
20339
20328
  }
20340
20329
  });
20341
20330
 
20342
20331
  // Merge only new components into dictionary
20343
- addedCount = Object.keys(newComponents).length;
20332
+ Object.keys(newComponents).length;
20344
20333
  Object.assign(this.componentDictionary, newComponents);
20345
20334
 
20346
20335
  // Update ModelPreloader's dictionary reference
@@ -20348,12 +20337,10 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
20348
20337
  modelPreloader = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.centralPlant) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.utilities) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.modelPreloader;
20349
20338
  if (modelPreloader) {
20350
20339
  modelPreloader.componentDictionary = this.componentDictionary;
20351
- console.log("\uD83D\uDD04 Updated ModelPreloader's dictionary reference (".concat(Object.keys(this.componentDictionary).length, " total components)"));
20352
20340
  }
20353
20341
 
20354
20342
  // Clear cache to force refresh
20355
20343
  this.clearCache();
20356
- console.log("\u2705 extendComponentDictionary(): Added ".concat(addedCount, " new components (").concat(skippedCount, " duplicates skipped)"));
20357
20344
  return _context3.a(2, true);
20358
20345
  case 4:
20359
20346
  _context3.p = 4;
@@ -29875,7 +29862,6 @@ function _attachIODevicesToComponent() {
29875
29862
  _context.n = 10;
29876
29863
  break;
29877
29864
  }
29878
- console.log("\uD83D\uDD04 IO device model not in cache, preloading: ".concat(deviceData.modelKey));
29879
29865
  _context.p = 5;
29880
29866
  if (!((_modelPreloader$loadi = modelPreloader.loadingPromises) !== null && _modelPreloader$loadi !== void 0 && _modelPreloader$loadi.has(deviceData.modelKey))) {
29881
29867
  _context.n = 7;
@@ -29957,10 +29943,6 @@ function _attachIODevicesToComponent() {
29957
29943
 
29958
29944
  // Add as child of the component
29959
29945
  componentModel.add(deviceModel);
29960
- console.log("\u2705 Attached IO device: ".concat(attachment.attachmentLabel || attachment.deviceId, " at"), {
29961
- position: deviceModel.position,
29962
- scale: deviceModel.scale
29963
- });
29964
29946
  _context.n = 13;
29965
29947
  break;
29966
29948
  case 12:
@@ -33506,7 +33488,6 @@ var SceneOperationsManager = /*#__PURE__*/function () {
33506
33488
 
33507
33489
  // Check if dictionary has connector children and component doesn't already have them
33508
33490
  if (dictEntry !== null && dictEntry !== void 0 && dictEntry.children && Array.isArray(dictEntry.children) && dictEntry.children.length > 0) {
33509
- // Only inject if the component doesn't already have children
33510
33491
  if (!child.children || child.children.length === 0) {
33511
33492
  // Get component rotation (in degrees from JSON)
33512
33493
  var rotation = child.rotation || {
@@ -33536,7 +33517,6 @@ var SceneOperationsManager = /*#__PURE__*/function () {
33536
33517
  connectorsInjected++;
33537
33518
  return clonedConnector;
33538
33519
  });
33539
- console.log("\uD83D\uDD0C Injected ".concat(child.children.length, " connectors for ").concat(child.uuid, " (").concat(libraryId, ") with rotation [").concat(rotation.x, "\xB0, ").concat(rotation.y, "\xB0, ").concat(rotation.z, "\xB0]"));
33540
33520
  componentsProcessed++;
33541
33521
  }
33542
33522
  }
@@ -36562,7 +36542,7 @@ var SceneTooltipsManager = /*#__PURE__*/function (_BaseDisposable) {
36562
36542
  // ---------------------------------------------------------------------------
36563
36543
  // Inline styles (injected once into the document head)
36564
36544
  // ---------------------------------------------------------------------------
36565
- var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n}\n\n.cp-tooltip__card {\n background: rgba(28, 32, 40, 0.95);\n border: 1px solid rgba(255, 255, 255, 0.12);\n border-radius: 10px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);\n overflow: hidden;\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__header {\n padding: 10px 14px;\n font-weight: 600;\n font-size: 14px;\n color: #e8ecf1;\n background: rgba(255, 255, 255, 0.04);\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n letter-spacing: 0.2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 I/O Devices section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__io-section {\n position: relative;\n}\n\n.cp-tooltip__io-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px;\n color: #a4adba;\n cursor: pointer;\n transition: background 0.12s ease, color 0.12s ease;\n}\n\n.cp-tooltip__io-trigger:hover {\n background: rgba(255, 255, 255, 0.06);\n color: #e8ecf1;\n}\n\n.cp-tooltip__io-trigger-label {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n font-weight: 500;\n}\n\n.cp-tooltip__io-arrow {\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__io-arrow {\n transform: rotate(90deg);\n}\n\n/* \u2500\u2500 Device list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__device-list {\n max-height: 0;\n overflow: hidden;\n transition: max-height 0.25s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__device-list {\n max-height: 300px;\n}\n\n.cp-tooltip__device-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 14px 6px 20px;\n color: #c1c8d1;\n font-size: 12px;\n border-top: 1px solid rgba(255, 255, 255, 0.04);\n transition: background 0.1s ease;\n}\n\n.cp-tooltip__device-item:hover {\n background: rgba(255, 255, 255, 0.04);\n}\n\n.cp-tooltip__device-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #4fc3f7;\n flex-shrink: 0;\n}\n\n.cp-tooltip__device-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__no-devices {\n padding: 8px 14px;\n color: #6b7280;\n font-size: 12px;\n font-style: italic;\n}\n\n/* \u2500\u2500 Caret arrow pointing down \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__caret {\n width: 0;\n height: 0;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 7px solid rgba(28, 32, 40, 0.95);\n margin: 0 auto;\n position: relative;\n top: -1px;\n}\n\n/* \u2500\u2500 Data point rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__dp-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 4px 12px 4px 30px;\n font-size: 11.5px;\n border-top: 1px solid rgba(255, 255, 255, 0.025);\n min-height: 24px;\n}\n\n.cp-tooltip__dp-name {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: #7c8d9e;\n}\n\n/* Read-only state badge */\n.cp-tooltip__dp-badge {\n font-size: 10.5px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 8px;\n flex-shrink: 0;\n background: rgba(255, 255, 255, 0.07);\n color: #9aabb8;\n min-width: 30px;\n text-align: center;\n letter-spacing: 0.2px;\n}\n\n.cp-tooltip__dp-badge.active {\n background: rgba(76, 175, 80, 0.28);\n color: #a5d6a7;\n}\n\n/* Binary toggle button */\n.cp-tooltip__dp-toggle {\n font-size: 10.5px;\n font-weight: 600;\n padding: 2px 9px;\n border-radius: 8px;\n flex-shrink: 0;\n border: 1px solid rgba(255, 255, 255, 0.14);\n background: rgba(255, 255, 255, 0.06);\n color: #c1c8d1;\n cursor: pointer;\n min-width: 40px;\n text-align: center;\n transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n}\n\n.cp-tooltip__dp-toggle:hover {\n background: rgba(255, 255, 255, 0.12);\n border-color: rgba(255, 255, 255, 0.25);\n}\n\n.cp-tooltip__dp-toggle.on {\n background: rgba(76, 175, 80, 0.28);\n border-color: rgba(76, 175, 80, 0.55);\n color: #a5d6a7;\n}\n\n/* Number / float input */\n.cp-tooltip__dp-input {\n width: 62px;\n background: rgba(255, 255, 255, 0.06);\n border: 1px solid rgba(255, 255, 255, 0.14);\n border-radius: 4px;\n color: #e8ecf1;\n font-size: 11px;\n padding: 2px 5px;\n text-align: right;\n outline: none;\n flex-shrink: 0;\n}\n\n.cp-tooltip__dp-input:focus {\n border-color: rgba(79, 195, 247, 0.55);\n}\n\n/* Enum select */\n.cp-tooltip__dp-select {\n background: rgba(255, 255, 255, 0.06);\n border: 1px solid rgba(255, 255, 255, 0.14);\n border-radius: 4px;\n color: #e8ecf1;\n font-size: 11px;\n padding: 2px 4px;\n outline: none;\n flex-shrink: 0;\n max-width: 96px;\n cursor: pointer;\n}\n\n.cp-tooltip__dp-select:focus {\n border-color: rgba(79, 195, 247, 0.55);\n}\n\n/* Unit suffix */\n.cp-tooltip__dp-unit {\n font-size: 10px;\n color: #505c68;\n flex-shrink: 0;\n margin-left: -4px;\n}\n";
36545
+ var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n color-scheme: light;\n}\n\n.cp-tooltip__card {\n background: rgba(255, 255, 255, 0.97);\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__header {\n padding: 10px 14px;\n font-weight: 600;\n font-size: 14px;\n color: #2c3e50;\n background: rgba(0, 0, 0, 0.02);\n border-bottom: 1px solid rgba(0, 0, 0, 0.08);\n letter-spacing: 0.2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 I/O Devices section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__io-section {\n position: relative;\n}\n\n.cp-tooltip__io-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px;\n color: #666666;\n cursor: pointer;\n transition: background 0.12s ease, color 0.12s ease;\n}\n\n.cp-tooltip__io-trigger:hover {\n background: rgba(0, 0, 0, 0.04);\n color: #333333;\n}\n\n.cp-tooltip__io-trigger-label {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n font-weight: 500;\n}\n\n.cp-tooltip__io-arrow {\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__io-arrow {\n transform: rotate(90deg);\n}\n\n/* \u2500\u2500 Device list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__device-list {\n max-height: 0;\n overflow: hidden;\n transition: max-height 0.25s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__device-list {\n max-height: 300px;\n}\n\n.cp-tooltip__device-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 14px 6px 20px;\n color: #555555;\n font-size: 12px;\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n transition: background 0.1s ease;\n}\n\n.cp-tooltip__device-item:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n\n.cp-tooltip__device-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #1976d2;\n flex-shrink: 0;\n}\n\n.cp-tooltip__device-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__no-devices {\n padding: 8px 14px;\n color: #888888;\n font-size: 12px;\n font-style: italic;\n}\n\n/* \u2500\u2500 Caret arrow pointing down \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__caret {\n width: 0;\n height: 0;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 7px solid rgba(255, 255, 255, 0.97);\n margin: 0 auto;\n position: relative;\n top: -1px;\n filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.1));\n}\n\n/* \u2500\u2500 Data point rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__dp-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 4px 12px 4px 30px;\n font-size: 11.5px;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n min-height: 24px;\n}\n\n.cp-tooltip__dp-name {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: #666666;\n}\n\n/* Read-only state badge */\n.cp-tooltip__dp-badge {\n font-size: 10.5px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 8px;\n flex-shrink: 0;\n background: #f0f2f5;\n color: #666666;\n min-width: 30px;\n text-align: center;\n letter-spacing: 0.2px;\n}\n\n.cp-tooltip__dp-badge.active {\n background: rgba(76, 175, 80, 0.15);\n color: #2e7d32;\n}\n\n/* Binary toggle button */\n.cp-tooltip__dp-toggle {\n font-size: 10.5px;\n font-weight: 600;\n padding: 2px 9px;\n border-radius: 8px;\n flex-shrink: 0;\n border: 1px solid #dddddd;\n background: #f8f9fa;\n color: #555555;\n cursor: pointer;\n min-width: 40px;\n text-align: center;\n transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n}\n\n.cp-tooltip__dp-toggle:hover {\n background: #eeeeee;\n border-color: #cccccc;\n}\n\n.cp-tooltip__dp-toggle.on {\n background: rgba(76, 175, 80, 0.15);\n border-color: rgba(76, 175, 80, 0.45);\n color: #2e7d32;\n}\n\n/* Number / float input */\n.cp-tooltip__dp-input {\n width: 62px;\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 5px;\n text-align: right;\n outline: none;\n flex-shrink: 0;\n}\n\n.cp-tooltip__dp-input:focus {\n border-color: #1976d2;\n}\n\n/* Enum select */\n.cp-tooltip__dp-select {\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 4px;\n outline: none;\n flex-shrink: 0;\n max-width: 96px;\n cursor: pointer;\n}\n\n.cp-tooltip__dp-select:focus {\n border-color: #1976d2;\n}\n\n/* Unit suffix */\n.cp-tooltip__dp-unit {\n font-size: 10px;\n color: #888888;\n flex-shrink: 0;\n margin-left: -4px;\n}\n";
36566
36546
  var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
36567
36547
  /**
36568
36548
  * @param {Object} sceneViewer - The sceneViewer instance
@@ -37494,6 +37474,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37494
37474
  entries.push({
37495
37475
  anim: anim,
37496
37476
  mesh: mesh,
37477
+ deviceModelRoot: deviceModelRoot,
37497
37478
  origPos: mesh.position.clone(),
37498
37479
  origRot: mesh.rotation.clone(),
37499
37480
  origWorldPos: worldPos,
@@ -37510,9 +37491,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37510
37491
  }
37511
37492
  if (entries.length) {
37512
37493
  this._entries.set(key, entries);
37513
- console.log("[IoBehaviorManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ") \u2014 stateVariables: ").concat(entries.map(function (e) {
37514
- return e.anim.stateVariable;
37515
- }).join(', ')));
37494
+ // Loaded ${entries.length} animation(s) for attachment "${attachmentId}"
37516
37495
  } else {
37517
37496
  console.warn("[IoBehaviorManager] No mesh entries resolved for attachment \"".concat(attachmentId, "\" \u2014 behaviorConfig had ").concat(anims.length, " entries but none matched a mesh"));
37518
37497
  }
@@ -37530,13 +37509,8 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37530
37509
  }, {
37531
37510
  key: "triggerState",
37532
37511
  value: function triggerState(attachmentId, dataPointId, value, parentUuid) {
37533
- var _this$_crossComponent;
37534
- console.log("[Behavior] triggerState called:", {
37535
- attachmentId: attachmentId,
37536
- dataPointId: dataPointId,
37537
- value: value,
37538
- parentUuid: parentUuid
37539
- });
37512
+ // triggerState: ${attachmentId}.${dataPointId} = ${value}
37513
+
37540
37514
  if (parentUuid) {
37541
37515
  var key = this._key(parentUuid, attachmentId);
37542
37516
  var entries = this._entries.get(key);
@@ -37591,12 +37565,12 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37591
37565
  // Evaluate component-level behaviors (intra-component io-device linking)
37592
37566
  if (parentUuid && this._componentBehaviors.has(parentUuid)) {
37593
37567
  var componentBehaviors = this._componentBehaviors.get(parentUuid);
37594
- console.log("[Behavior] Checking component-level behaviors for ".concat(parentUuid, " (count: ").concat(componentBehaviors.length, ")"));
37568
+ // Checking component-level behaviors (count: ${componentBehaviors.length})
37595
37569
  this.triggerCrossComponentBehaviors(componentBehaviors, parentUuid, attachmentId, dataPointId, value);
37596
37570
  }
37597
37571
 
37598
37572
  // Evaluate cross-component behaviors if any are registered
37599
- console.log("[Behavior] Checking cross-component behaviors (count: ".concat(((_this$_crossComponent = this._crossComponentBehaviors) === null || _this$_crossComponent === void 0 ? void 0 : _this$_crossComponent.length) || 0, ")"));
37573
+ // Checking cross-component behaviors (count: ${this._crossComponentBehaviors?.length || 0})
37600
37574
  if (this._crossComponentBehaviors && this._crossComponentBehaviors.length > 0) {
37601
37575
  this.triggerCrossComponentBehaviors(this._crossComponentBehaviors, parentUuid, attachmentId, dataPointId, value);
37602
37576
  }
@@ -37615,7 +37589,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37615
37589
  this._crossComponentBehaviors = (behaviors || []).map(function (b) {
37616
37590
  return _this2._normalizeBehavior(b);
37617
37591
  });
37618
- console.log("[Behavior] Loaded ".concat(this._crossComponentBehaviors.length, " cross-component behavior(s)"), this._crossComponentBehaviors);
37592
+ // Loaded ${this._crossComponentBehaviors.length} cross-component behavior(s)
37619
37593
  }
37620
37594
 
37621
37595
  /**
@@ -37634,7 +37608,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37634
37608
  return _this3._normalizeBehavior(b);
37635
37609
  });
37636
37610
  this._componentBehaviors.set(componentUuid, normalized);
37637
- console.log("[Behavior] Registered ".concat(normalized.length, " component-level behavior(s) for component ").concat(componentUuid), normalized);
37611
+ // Registered ${normalized.length} component-level behavior(s) for component ${componentUuid}
37638
37612
  }
37639
37613
 
37640
37614
  /**
@@ -37745,7 +37719,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37745
37719
  key: "configure",
37746
37720
  value: function configure(stateAdapter) {
37747
37721
  this._stateAdapter = stateAdapter || null;
37748
- console.log('[Behavior] State adapter configured:', !!this._stateAdapter);
37722
+ // State adapter configured
37749
37723
  }
37750
37724
 
37751
37725
  /**
@@ -37761,10 +37735,10 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37761
37735
  key: "triggerCrossComponentBehaviors",
37762
37736
  value: function triggerCrossComponentBehaviors(behaviors, triggerParentUuid, triggerAttachmentId, triggerStateId, value) {
37763
37737
  if (!behaviors || !Array.isArray(behaviors)) {
37764
- console.log('[Behavior] No behaviors to evaluate');
37765
37738
  return;
37766
37739
  }
37767
- console.log("[Behavior] Evaluating ".concat(behaviors.length, " behavior(s) for trigger: ").concat(triggerParentUuid, ".").concat(triggerAttachmentId, ".").concat(triggerStateId, " = ").concat(value));
37740
+
37741
+ // Evaluating ${behaviors.length} behavior(s)
37768
37742
  var _iterator5 = _createForOfIteratorHelper(behaviors),
37769
37743
  _step5;
37770
37744
  try {
@@ -37799,7 +37773,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37799
37773
 
37800
37774
  // Verify that the input matches the triggering source
37801
37775
  if (inputComponent === triggerParentUuid && input.attachment === triggerAttachmentId && input.state === triggerStateId) {
37802
- console.log("[Behavior] \u2713 Behavior \"".concat(behavior.id, "\" matched!"));
37776
+ // Behavior "${behavior.id}" matched
37803
37777
 
37804
37778
  // Collect all outputs (single or multiple)
37805
37779
  var outputs = _outputs || (output ? [output] : []);
@@ -37817,14 +37791,13 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37817
37791
 
37818
37792
  // Direct state mapping without conditions
37819
37793
  if (this._stateAdapter) {
37820
- console.log("[Behavior] Dispatching state-to-state: ".concat(out.attachment, ".").concat(out.state, " = ").concat(value));
37794
+ // Dispatching state-to-state: ${out.attachment}.${out.state} = ${value}
37821
37795
  this._stateAdapter.setState(out.attachment, out.state, value);
37822
- console.log("[Behavior] \u2713 State-to-state triggered: ".concat(input.attachment, ".").concat(input.state, " (").concat(value, ") \u2192 ").concat(out.attachment, ".").concat(out.state));
37823
37796
 
37824
37797
  // Trigger animations on the output component
37825
37798
  // triggerState(attachmentId, dataPointId, value, parentUuid)
37826
37799
  if (outputComponent) {
37827
- console.log("[Behavior] Triggering animations on output component: ".concat(outputComponent, ".").concat(out.attachment, ".").concat(out.state));
37800
+ // Triggering animations on output component
37828
37801
  this.triggerState(out.attachment, out.state, value, outputComponent);
37829
37802
  } else {
37830
37803
  console.warn("[Behavior] Could not find component for attachment \"".concat(out.attachment, "\""));
@@ -37835,7 +37808,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
37835
37808
  }
37836
37809
  // LEGACY: Mesh-based pattern with conditions
37837
37810
  else if (conditions && out.child) {
37838
- console.log('[Behavior] Using legacy mesh-based pattern with conditions');
37811
+ // Using legacy mesh-based pattern with conditions
37839
37812
  // Evaluate conditions
37840
37813
  var _iterator7 = _createForOfIteratorHelper(conditions),
37841
37814
  _step7;
@@ -38252,13 +38225,9 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
38252
38225
  value: function _applyAnimation(entry, value) {
38253
38226
  var anim = entry.anim,
38254
38227
  mesh = entry.mesh,
38255
- origPos = entry.origPos,
38256
- origRot = entry.origRot,
38257
- origWorldPos = entry.origWorldPos,
38258
- origWorldQuat = entry.origWorldQuat,
38259
- origWorldCenter = entry.origWorldCenter,
38260
- deviceWorldQuat = entry.deviceWorldQuat,
38261
- viewerMaxDim = entry.viewerMaxDim;
38228
+ origPos = entry.origPos;
38229
+ entry.origRot;
38230
+ var viewerMaxDim = entry.viewerMaxDim;
38262
38231
  var mapping = this._resolveMapping(anim, value);
38263
38232
  if (!mapping) return;
38264
38233
  var types = anim.transformTypes || [];
@@ -38270,7 +38239,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
38270
38239
  if (type === 'translation') {
38271
38240
  this._applyTranslation(mesh, origPos, mapping.transform);
38272
38241
  } else if (type === 'rotation') {
38273
- this._applyRotation(mesh, origPos, origRot, anim, mapping.rotationTransform, origWorldPos, origWorldQuat, origWorldCenter, deviceWorldQuat, viewerMaxDim);
38242
+ this._applyRotation(entry, anim, mapping.rotationTransform, viewerMaxDim);
38274
38243
  } else if (type === 'color') {
38275
38244
  this._applyColor(mesh, mapping.colorTransform);
38276
38245
  }
@@ -38414,25 +38383,71 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
38414
38383
  mesh.position.set(origPos.x - ((_transform$x = transform.x) !== null && _transform$x !== void 0 ? _transform$x : 0), origPos.y - ((_transform$y = transform.y) !== null && _transform$y !== void 0 ? _transform$y : 0), origPos.z + ((_transform$z = transform.z) !== null && _transform$z !== void 0 ? _transform$z : 0));
38415
38384
  }
38416
38385
 
38386
+ /**
38387
+ * Recompute world-space rest-pose transforms for a behavior entry using the
38388
+ * current parent/device world matrix. origPos/origRot are local rest pose and
38389
+ * stay valid after parent moves; world anchors must be derived at apply time.
38390
+ *
38391
+ * @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
38392
+ * @returns {{ origWorldPos: THREE.Vector3, origWorldQuat: THREE.Quaternion, origWorldCenter: THREE.Vector3, deviceWorldQuat: THREE.Quaternion }|null}
38393
+ */
38394
+ }, {
38395
+ key: "_getRestWorldTransforms",
38396
+ value: function _getRestWorldTransforms(entry) {
38397
+ var mesh = entry.mesh,
38398
+ origPos = entry.origPos,
38399
+ origRot = entry.origRot,
38400
+ deviceModelRoot = entry.deviceModelRoot;
38401
+ if (!mesh || !origPos || !origRot) return null;
38402
+ var savedPos = mesh.position.clone();
38403
+ var savedQuat = mesh.quaternion.clone();
38404
+ mesh.position.copy(origPos);
38405
+ mesh.rotation.copy(origRot);
38406
+ mesh.updateMatrixWorld(true);
38407
+ var origWorldPos = new THREE__namespace.Vector3();
38408
+ mesh.getWorldPosition(origWorldPos);
38409
+ var origWorldQuat = new THREE__namespace.Quaternion();
38410
+ mesh.getWorldQuaternion(origWorldQuat);
38411
+ var box = new THREE__namespace.Box3().setFromObject(mesh);
38412
+ var origWorldCenter = new THREE__namespace.Vector3();
38413
+ if (!box.isEmpty()) box.getCenter(origWorldCenter);else origWorldCenter.copy(origWorldPos);
38414
+ var deviceWorldQuat = new THREE__namespace.Quaternion();
38415
+ if (deviceModelRoot) {
38416
+ deviceModelRoot.getWorldQuaternion(deviceWorldQuat);
38417
+ }
38418
+ mesh.position.copy(savedPos);
38419
+ mesh.quaternion.copy(savedQuat);
38420
+ return {
38421
+ origWorldPos: origWorldPos,
38422
+ origWorldQuat: origWorldQuat,
38423
+ origWorldCenter: origWorldCenter,
38424
+ deviceWorldQuat: deviceWorldQuat
38425
+ };
38426
+ }
38427
+
38417
38428
  /**
38418
38429
  * Apply a rotation around an arbitrary pivot point using world-space quaternion
38419
38430
  * math matching the ReconstructionViewer's setMeshPreviewRotationAxis approach.
38420
38431
  * This ensures the runtime axis/pivot matches what the user configured in the
38421
38432
  * animation dialog, regardless of the device's parent transform in the scene.
38422
38433
  *
38423
- * @param {THREE.Object3D} mesh
38424
- * @param {THREE.Vector3} origPos - local position at load time (unused, kept for signature compat)
38425
- * @param {THREE.Euler} origRot - local rotation at load time (unused)
38434
+ * @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
38426
38435
  * @param {Object} anim
38427
38436
  * @param {number} angleDeg - Degrees
38428
- * @param {THREE.Vector3} origWorldPos - world position at load time
38429
- * @param {THREE.Quaternion} origWorldQuat - world quaternion at load time
38430
- * @param {THREE.Vector3} origWorldCenter - world bounding-box center at load time
38437
+ * @param {number} viewerMaxDim
38431
38438
  */
38432
38439
  }, {
38433
38440
  key: "_applyRotation",
38434
- value: function _applyRotation(mesh, origPos, origRot, anim, angleDeg, origWorldPos, origWorldQuat, origWorldCenter, deviceWorldQuat, viewerMaxDim) {
38441
+ value: function _applyRotation(entry, anim, angleDeg, viewerMaxDim) {
38435
38442
  var _anim$rotAxis, _anim$rotAxisOffset;
38443
+ var mesh = entry.mesh,
38444
+ origPos = entry.origPos,
38445
+ origRot = entry.origRot;
38446
+ var restWorld = this._getRestWorldTransforms(entry);
38447
+ var origWorldPos = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldPos;
38448
+ var origWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldQuat;
38449
+ var origWorldCenter = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldCenter;
38450
+ var deviceWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.deviceWorldQuat;
38436
38451
  var angle = THREE__namespace.MathUtils.degToRad(typeof angleDeg === 'number' ? angleDeg : 0);
38437
38452
  var axis = ((_anim$rotAxis = anim.rotAxis) !== null && _anim$rotAxis !== void 0 ? _anim$rotAxis : 'x').toLowerCase();
38438
38453
  var off = (_anim$rotAxisOffset = anim.rotAxisOffset) !== null && _anim$rotAxisOffset !== void 0 ? _anim$rotAxisOffset : {
@@ -38936,12 +38951,10 @@ var CentralPlantInternals = /*#__PURE__*/function () {
38936
38951
  if (this.centralPlant.sceneViewer.$refs.container && this.centralPlant.sceneViewer.camera && this.centralPlant.sceneViewer.scene) {
38937
38952
  this.centralPlant.managers.tooltipsManager = new SceneTooltipsManager(this.centralPlant.sceneViewer.$refs.container, this.centralPlant.sceneViewer.camera, this.centralPlant.sceneViewer.scene);
38938
38953
  this.centralPlant.sceneViewer.tooltipsManager = this.centralPlant.managers.tooltipsManager;
38939
- console.log('🔍 Tooltip manager initialized:', this.centralPlant.managers.tooltipsManager);
38940
38954
 
38941
38955
  // Initialize the component tooltip manager (screen-space tooltip on selection)
38942
38956
  this.centralPlant.managers.componentTooltipManager = new ComponentTooltipManager(this.centralPlant.sceneViewer);
38943
38957
  this.centralPlant.sceneViewer.componentTooltipManager = this.centralPlant.managers.componentTooltipManager;
38944
- console.log('🔍 Component tooltip manager initialized');
38945
38958
  }
38946
38959
  }
38947
38960
 
@@ -39877,7 +39890,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
39877
39890
 
39878
39891
  // Register component-level behaviors (intra-component io-device linking)
39879
39892
  if (componentData.behaviors && componentData.behaviors.length > 0) {
39880
- console.log("[DragDrop] Registering ".concat(componentData.behaviors.length, " component-level behavior(s) for ").concat(componentId));
39893
+ // Registering ${componentData.behaviors.length} component-level behavior(s)
39881
39894
  ioBehavMgr.registerComponentBehaviors(componentId, componentData.behaviors);
39882
39895
  }
39883
39896
  }
@@ -40181,7 +40194,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
40181
40194
  * Initialize the CentralPlant manager
40182
40195
  *
40183
40196
  * @constructor
40184
- * @version 0.3.35
40197
+ * @version 0.3.37
40185
40198
  * @updated 2025-10-22
40186
40199
  *
40187
40200
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -40370,12 +40383,13 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
40370
40383
  behaviors: ((_this$importedSceneDa3 = this.importedSceneData.behaviors) === null || _this$importedSceneDa3 === void 0 ? void 0 : _this$importedSceneDa3.length) || 0,
40371
40384
  timestamp: new Date().toISOString()
40372
40385
  });
40373
- console.log('[Behavior] Scene behaviors detail:', this.importedSceneData.behaviors);
40386
+
40387
+ // Scene behaviors loaded
40374
40388
 
40375
40389
  // Register behaviors with IoBehaviorManager
40376
40390
  ioBehavMgr = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.managers) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.ioBehaviorManager;
40377
40391
  if (ioBehavMgr) {
40378
- console.log('[Behavior] Calling setCrossComponentBehaviors with:', this.importedSceneData.behaviors || []);
40392
+ // Setting cross-component behaviors
40379
40393
  ioBehavMgr.setCrossComponentBehaviors(this.importedSceneData.behaviors || []);
40380
40394
  } else {
40381
40395
  console.warn('[Behavior] ioBehaviorManager not available!');
@@ -40874,7 +40888,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
40874
40888
 
40875
40889
  // Enable drag functionality for the specific element
40876
40890
  this.sceneViewer.managers.componentDragManager.enableElementDrag(element, componentId);
40877
- console.log("\u2705 enableDragDrop(): Enabled drag and drop for ".concat(componentId));
40878
40891
  return true;
40879
40892
  } catch (error) {
40880
40893
  console.error('❌ enableDragDrop(): Error enabling drag and drop:', error);
@@ -40910,7 +40923,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
40910
40923
  }
40911
40924
  try {
40912
40925
  this.sceneViewer.managers.componentDragManager.disableElementDrag(element);
40913
- console.log('✅ disableDragDrop(): Disabled drag and drop for element');
40914
40926
  return true;
40915
40927
  } catch (error) {
40916
40928
  console.error('❌ disableDragDrop(): Error disabling drag and drop:', error);
@@ -40944,7 +40956,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
40944
40956
  if (this.sceneViewer.managers.componentDragManager) {
40945
40957
  this.sceneViewer.managers.componentDragManager.setEnabled(enabled);
40946
40958
  }
40947
- console.log("\u2705 setDragDropEnabled(): Drag and drop ".concat(enabled ? 'enabled' : 'disabled'));
40948
40959
  return true;
40949
40960
  } catch (error) {
40950
40961
  console.error('❌ setDragDropEnabled(): Error setting drag and drop state:', error);
@@ -46189,7 +46200,6 @@ function _findInAllCachePartitions() {
46189
46200
  _context16.n = 7;
46190
46201
  break;
46191
46202
  }
46192
- console.log("\u2705 [findInAllCachePartitions] Found in ".concat(cacheName, " (exact match): ").concat(cacheKey.substring(0, 80), "..."));
46193
46203
  return _context16.a(2, response);
46194
46204
  case 7:
46195
46205
  if (!(encodedCacheKey !== cacheKey)) {
@@ -46204,7 +46214,6 @@ function _findInAllCachePartitions() {
46204
46214
  _context16.n = 9;
46205
46215
  break;
46206
46216
  }
46207
- console.log("\u2705 [findInAllCachePartitions] Found in ".concat(cacheName, " (encoded match): ").concat(encodedCacheKey.substring(0, 80), "..."));
46208
46217
  return _context16.a(2, response);
46209
46218
  case 9:
46210
46219
  _context16.n = 4;
@@ -46239,8 +46248,6 @@ function _getCachedS3Object() {
46239
46248
  cachedResponse,
46240
46249
  cachedTime,
46241
46250
  age,
46242
- _allKeys,
46243
- matchingKeys,
46244
46251
  _args19 = arguments;
46245
46252
  return _regenerator().w(function (_context19) {
46246
46253
  while (1) switch (_context19.n) {
@@ -46248,50 +46255,26 @@ function _getCachedS3Object() {
46248
46255
  storageOptions = _args19.length > 1 && _args19[1] !== undefined ? _args19[1] : {};
46249
46256
  expiryMs = _args19.length > 2 && _args19[2] !== undefined ? _args19[2] : null;
46250
46257
  cacheKey = "https://s3.cache/".concat(s3Key);
46251
- expiry = expiryMs || cacheManager.getExpiryForPath(s3Key);
46252
- console.log("\uD83D\uDD0D [S3Cache] Checking for cached S3 object:", {
46253
- s3Key: s3Key,
46254
- cacheKey: cacheKey
46255
- });
46256
-
46257
- // First, check ALL app cache partitions for a hit (handles auth race condition)
46258
+ expiry = expiryMs || cacheManager.getExpiryForPath(s3Key); // First, check ALL app cache partitions for a hit (handles auth race condition)
46258
46259
  _context19.n = 1;
46259
46260
  return findInAllCachePartitions(cacheKey);
46260
46261
  case 1:
46261
46262
  cachedResponse = _context19.v;
46262
46263
  if (!cachedResponse) {
46263
- _context19.n = 4;
46264
+ _context19.n = 3;
46264
46265
  break;
46265
46266
  }
46266
46267
  cachedTime = cachedResponse.headers.get('x-cached-time');
46267
46268
  age = Date.now() - parseInt(cachedTime || '0');
46268
- console.log("\u2705 [S3Cache] Found in cache partition, age: ".concat(Math.round(age / 1000), "s, expiry: ").concat(Math.round(expiry / 1000), "s"));
46269
46269
  if (!(age < expiry)) {
46270
46270
  _context19.n = 3;
46271
46271
  break;
46272
46272
  }
46273
- console.log("\u2705 [S3Cache] Returning cached blob for: ".concat(s3Key));
46274
46273
  _context19.n = 2;
46275
46274
  return cachedResponse.blob();
46276
46275
  case 2:
46277
46276
  return _context19.a(2, _context19.v);
46278
46277
  case 3:
46279
- console.log("\u23F0 [S3Cache] Cache entry expired, will re-fetch");
46280
- _context19.n = 6;
46281
- break;
46282
- case 4:
46283
- console.log("\u274C [S3Cache] Not found in any cache partition");
46284
- _context19.n = 5;
46285
- return getAllCacheKeys();
46286
- case 5:
46287
- _allKeys = _context19.v;
46288
- matchingKeys = _toConsumableArray(_allKeys).filter(function (k) {
46289
- return k.includes('24dd6a7a') || k.includes('.glb');
46290
- });
46291
- if (matchingKeys.length > 0) {
46292
- console.log("\uD83D\uDD0D [S3Cache] Available GLB cache keys:", matchingKeys.slice(0, 5));
46293
- }
46294
- case 6:
46295
46278
  return _context19.a(2, cacheManager.execute({
46296
46279
  cacheKey: cacheKey,
46297
46280
  sourceKey: s3Key,
@@ -46450,7 +46433,6 @@ function _preloadS3Objects() {
46450
46433
  };
46451
46434
  }()));
46452
46435
  case 1:
46453
- console.log("\u2705 Preload complete: ".concat(results.success, " success, ").concat(results.failed, " failed"));
46454
46436
  return _context22.a(2, results);
46455
46437
  }
46456
46438
  }, _callee22);
@@ -46628,7 +46610,6 @@ function _preloadLocalFiles() {
46628
46610
  return _regenerator().w(function (_context29) {
46629
46611
  while (1) switch (_context29.n) {
46630
46612
  case 0:
46631
- console.log("preloadLocalFiles started");
46632
46613
  results = {
46633
46614
  success: 0,
46634
46615
  failed: 0,
@@ -46667,7 +46648,6 @@ function _preloadLocalFiles() {
46667
46648
  };
46668
46649
  }()));
46669
46650
  case 1:
46670
- console.log("preloadLocalFiles finished");
46671
46651
  if (results.failed > 0) {
46672
46652
  console.warn("\u26A0\uFE0F preloadLocalFiles Cache priming finished with errors: ".concat(results.failed, " failed"), results.errors);
46673
46653
  }
@@ -47329,7 +47309,6 @@ var S3MetadataCacheService = /*#__PURE__*/function () {
47329
47309
  // Update memory cache
47330
47310
  this._memoryCache = metadata;
47331
47311
  this._memoryCacheTime = Date.now();
47332
- console.log("\uD83D\uDCBE S3MetadataCacheService: Set ".concat(components.length, " components"));
47333
47312
  return _context9.a(2, true);
47334
47313
  case 4:
47335
47314
  _context9.p = 4;