@2112-lab/central-plant 0.3.38 → 0.3.41

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.
Files changed (29) hide show
  1. package/dist/bundle/index.js +1096 -562
  2. package/dist/cjs/src/core/centralPlant.js +115 -68
  3. package/dist/cjs/src/core/centralPlantInternals.js +20 -36
  4. package/dist/cjs/src/index.js +23 -0
  5. package/dist/cjs/src/managers/behaviors/IoBehaviorManager.js +175 -234
  6. package/dist/cjs/src/managers/components/componentDataManager.js +63 -11
  7. package/dist/cjs/src/managers/scene/componentTooltipManager.js +95 -65
  8. package/dist/cjs/src/managers/scene/modelManager.js +93 -145
  9. package/dist/cjs/src/managers/scene/sceneOperationsManager.js +8 -3
  10. package/dist/cjs/src/utils/animationTransformUtils.js +82 -0
  11. package/dist/cjs/src/utils/behaviorDispatch.js +62 -0
  12. package/dist/cjs/src/utils/behaviorRegistration.js +76 -0
  13. package/dist/cjs/src/utils/behaviorSceneUtils.js +155 -0
  14. package/dist/cjs/src/utils/behaviorSchema.js +209 -0
  15. package/dist/esm/src/core/centralPlant.js +115 -68
  16. package/dist/esm/src/core/centralPlantInternals.js +21 -37
  17. package/dist/esm/src/index.js +5 -0
  18. package/dist/esm/src/managers/behaviors/IoBehaviorManager.js +176 -235
  19. package/dist/esm/src/managers/components/componentDataManager.js +63 -11
  20. package/dist/esm/src/managers/scene/componentTooltipManager.js +95 -65
  21. package/dist/esm/src/managers/scene/modelManager.js +94 -146
  22. package/dist/esm/src/managers/scene/sceneOperationsManager.js +8 -3
  23. package/dist/esm/src/utils/animationTransformUtils.js +56 -0
  24. package/dist/esm/src/utils/behaviorDispatch.js +56 -0
  25. package/dist/esm/src/utils/behaviorRegistration.js +71 -0
  26. package/dist/esm/src/utils/behaviorSceneUtils.js +147 -0
  27. package/dist/esm/src/utils/behaviorSchema.js +201 -0
  28. package/dist/index.d.ts +186 -1
  29. package/package.json +1 -1
@@ -8,6 +8,8 @@ var baseDisposable = require('./baseDisposable.js');
8
8
  var DisposalUtilities = require('../utils/DisposalUtilities.js');
9
9
  var centralPlantInternals = require('./centralPlantInternals.js');
10
10
  require('../rendering/modelPreloader.js');
11
+ var behaviorSceneUtils = require('../utils/behaviorSceneUtils.js');
12
+ var behaviorDispatch = require('../utils/behaviorDispatch.js');
11
13
 
12
14
  // ─────────────────────────────────────────────────────────────────────────────
13
15
  // Flow-direction compatibility helper (module-level, no class dependency)
@@ -35,7 +37,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
35
37
  * Initialize the CentralPlant manager
36
38
  *
37
39
  * @constructor
38
- * @version 0.3.38
40
+ * @version 0.3.41
39
41
  * @updated 2025-10-22
40
42
  *
41
43
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -209,8 +211,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
209
211
  key: "setImportedSceneData",
210
212
  value: (function () {
211
213
  var _setImportedSceneData = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee2(sceneData) {
212
- var _this$importedSceneDa, _this$importedSceneDa2, _this$importedSceneDa3, _this$sceneViewer;
213
- var ioBehavMgr;
214
+ var _this$importedSceneDa, _this$importedSceneDa2, _this$importedSceneDa3;
214
215
  return _rollupPluginBabelHelpers.regenerator().w(function (_context2) {
215
216
  while (1) switch (_context2.n) {
216
217
  case 0:
@@ -227,14 +228,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
227
228
 
228
229
  // Scene behaviors loaded
229
230
 
230
- // Register behaviors with IoBehaviorManager
231
- 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;
232
- if (ioBehavMgr) {
233
- // Setting cross-component behaviors
234
- ioBehavMgr.setCrossComponentBehaviors(this.importedSceneData.behaviors || []);
235
- } else {
236
- console.warn('[Behavior] ioBehaviorManager not available!');
237
- }
231
+ // Cross-component behaviors are registered by sceneOperationsManager.loadSceneData()
238
232
 
239
233
  // Reset component counter based on imported components to avoid ID conflicts
240
234
  this.internals.resetComponentCounter();
@@ -415,8 +409,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
415
409
  }, {
416
410
  key: "selectObject",
417
411
  value: function selectObject(objectOrId) {
418
- var _this$sceneViewer2, _object;
419
- if (!((_this$sceneViewer2 = this.sceneViewer) !== null && _this$sceneViewer2 !== void 0 && _this$sceneViewer2.transformManager)) {
412
+ var _this$sceneViewer, _object;
413
+ if (!((_this$sceneViewer = this.sceneViewer) !== null && _this$sceneViewer !== void 0 && _this$sceneViewer.transformManager)) {
420
414
  console.warn('⚠️ Transform manager not initialized');
421
415
  return false;
422
416
  }
@@ -462,8 +456,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
462
456
  }, {
463
457
  key: "toggleObject",
464
458
  value: function toggleObject(objectOrId) {
465
- var _this$sceneViewer3, _object2;
466
- if (!((_this$sceneViewer3 = this.sceneViewer) !== null && _this$sceneViewer3 !== void 0 && _this$sceneViewer3.transformManager)) {
459
+ var _this$sceneViewer2, _object2;
460
+ if (!((_this$sceneViewer2 = this.sceneViewer) !== null && _this$sceneViewer2 !== void 0 && _this$sceneViewer2.transformManager)) {
467
461
  console.warn('⚠️ Transform manager not initialized');
468
462
  return false;
469
463
  }
@@ -499,8 +493,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
499
493
  }, {
500
494
  key: "deselectObject",
501
495
  value: function deselectObject() {
502
- var _this$sceneViewer4;
503
- if (!((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.transformManager)) {
496
+ var _this$sceneViewer3;
497
+ if (!((_this$sceneViewer3 = this.sceneViewer) !== null && _this$sceneViewer3 !== void 0 && _this$sceneViewer3.transformManager)) {
504
498
  console.warn('⚠️ Transform manager not initialized');
505
499
  return false;
506
500
  }
@@ -1080,68 +1074,70 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1080
1074
  }
1081
1075
 
1082
1076
  /**
1083
- * Set the state of an I/O device instance in the Three.js scene.
1084
- *
1085
- * This is the primary public API for driving IO device state changes from
1086
- * external code (real-time data feeds, AI agents, automated tests, etc.).
1087
- * It performs three coordinated actions in order:
1088
- * 1. Persists the new value through the state adapter (Vuex in sandbox,
1089
- * or any custom adapter injected via componentTooltipManager.configure())
1090
- * so that the host application's store stays consistent.
1091
- * 2. Evaluates all behaviors whose input matches this (attachmentId, stateId)
1092
- * pair and applies the resulting property changes to Three.js meshes.
1093
- * 3. Emits an 'io-device-state-changed' event on the sceneViewer so that
1094
- * host applications without a Vuex store (e.g. cp3d-viewer) can react.
1095
- *
1096
- * @param {string} attachmentId - The attachment ID of the IO device (matches
1097
- * the `attachmentId` stored in the Three.js object's userData)
1098
- * @param {string} stateId - The data-point / state ID on the device (e.g. 'power', 'level')
1099
- * @param {*} value - The new state value (boolean, number, string, etc.)
1100
- * @param {string} [parentUuid] - UUID of the parent component instance.
1101
- * Required when multiple instances of the same smart component share the
1102
- * same attachmentId — prevents cross-instance state bleed.
1103
- * @returns {boolean} True if the behavior system was reached; false if unavailable.
1104
- * @example
1105
- * // Toggle a push-button on a specific pump instance
1106
- * centralPlant.setIoDeviceState('pump-push-button-01', 'power', true, pumpUuid)
1107
- *
1108
- * // Drive an analog level sensor (no parentUuid needed when only one instance)
1109
- * centralPlant.setIoDeviceState('chiller-level-sensor-01', 'level', 0.75)
1077
+ * Internal single path for I/O state changes: persist, animate, link, emit.
1078
+ * @private
1110
1079
  */
1111
1080
  }, {
1112
- key: "setIoDeviceState",
1113
- value: function setIoDeviceState(attachmentId, stateId, value, parentUuid) {
1114
- var _this$sceneViewer5, _this$sceneViewer6, _this$sceneViewer7;
1115
- // 1. Persist via state adapter if one has been configured
1116
- var stateAdapter = (_this$sceneViewer5 = this.sceneViewer) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.managers) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.componentTooltipManager) === null || _this$sceneViewer5 === void 0 ? void 0 : _this$sceneViewer5._stateAdapter;
1081
+ key: "_dispatchIoState",
1082
+ value: function _dispatchIoState(attachmentId, stateId, value, parentUuid) {
1083
+ var _this$managers, _this$sceneViewer4, _this$sceneViewer5, _this$managers2, _this$sceneViewer6, _this$sceneViewer7, _this$sceneViewer8;
1084
+ var tooltipMgr = ((_this$managers = this.managers) === null || _this$managers === void 0 ? void 0 : _this$managers.componentTooltipManager) || ((_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 ? void 0 : _this$sceneViewer4.componentTooltipManager) || ((_this$sceneViewer5 = this.sceneViewer) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.managers) === null || _this$sceneViewer5 === void 0 ? void 0 : _this$sceneViewer5.componentTooltipManager);
1085
+ var stateAdapter = tooltipMgr === null || tooltipMgr === void 0 ? void 0 : tooltipMgr._stateAdapter;
1117
1086
  if (stateAdapter !== null && stateAdapter !== void 0 && stateAdapter.setState) {
1118
- var scopedKey = parentUuid ? "".concat(parentUuid, "::").concat(attachmentId) : attachmentId;
1087
+ var scopedKey = behaviorDispatch.getScopedAttachmentKey(attachmentId, parentUuid);
1119
1088
  try {
1120
1089
  stateAdapter.setState(scopedKey, stateId, value);
1121
1090
  } catch (err) {
1122
- console.warn('⚠️ setIoDeviceState(): stateAdapter.setState() threw:', err);
1091
+ console.warn('⚠️ _dispatchIoState(): stateAdapter.setState() threw:', err);
1123
1092
  }
1124
1093
  }
1125
-
1126
- // 2. Apply io-behavior changes
1127
- var ioBehavMgr = (_this$sceneViewer6 = this.sceneViewer) === null || _this$sceneViewer6 === void 0 || (_this$sceneViewer6 = _this$sceneViewer6.managers) === null || _this$sceneViewer6 === void 0 ? void 0 : _this$sceneViewer6.ioBehaviorManager;
1094
+ var ioBehavMgr = ((_this$managers2 = this.managers) === null || _this$managers2 === void 0 ? void 0 : _this$managers2.ioBehaviorManager) || ((_this$sceneViewer6 = this.sceneViewer) === null || _this$sceneViewer6 === void 0 || (_this$sceneViewer6 = _this$sceneViewer6.managers) === null || _this$sceneViewer6 === void 0 ? void 0 : _this$sceneViewer6.ioBehaviorManager) || ((_this$sceneViewer7 = this.sceneViewer) === null || _this$sceneViewer7 === void 0 ? void 0 : _this$sceneViewer7.ioBehaviorManager);
1128
1095
  if (ioBehavMgr) {
1129
- var _this$importedSceneDa4;
1130
1096
  ioBehavMgr.triggerState(attachmentId, stateId, value, parentUuid);
1131
-
1132
- // Evaluate cross-component behaviors if they exist in the imported scene
1133
- if ((_this$importedSceneDa4 = this.importedSceneData) !== null && _this$importedSceneDa4 !== void 0 && _this$importedSceneDa4.behaviors) {
1134
- ioBehavMgr.triggerCrossComponentBehaviors(this.importedSceneData.behaviors, parentUuid, attachmentId, stateId, value);
1135
- }
1136
1097
  }
1137
-
1138
- // 3. Emit event for host apps that don't use the state adapter (e.g. cp3d-viewer)
1139
- (_this$sceneViewer7 = this.sceneViewer) === null || _this$sceneViewer7 === void 0 || _this$sceneViewer7.emit('io-device-state-changed', {
1098
+ (_this$sceneViewer8 = this.sceneViewer) === null || _this$sceneViewer8 === void 0 || _this$sceneViewer8.emit('io-device-state-changed', {
1140
1099
  attachmentId: attachmentId,
1141
1100
  stateId: stateId,
1142
1101
  value: value,
1143
1102
  parentUuid: parentUuid || null
1144
1103
  });
1104
+ }
1105
+
1106
+ /**
1107
+ * Configure the state adapter on both tooltip and behavior managers.
1108
+ * @param {{ getState: Function, setState: Function }} stateAdapter
1109
+ */
1110
+ }, {
1111
+ key: "configureStateAdapter",
1112
+ value: function configureStateAdapter(stateAdapter) {
1113
+ var _this$managers3, _this$sceneViewer9, _this$managers4, _this$sceneViewer1, _this$sceneViewer10;
1114
+ var tooltipMgr = ((_this$managers3 = this.managers) === null || _this$managers3 === void 0 ? void 0 : _this$managers3.componentTooltipManager) || ((_this$sceneViewer9 = this.sceneViewer) === null || _this$sceneViewer9 === void 0 ? void 0 : _this$sceneViewer9.componentTooltipManager);
1115
+ if (tooltipMgr !== null && tooltipMgr !== void 0 && tooltipMgr.configure) {
1116
+ var _this$sceneViewer0;
1117
+ tooltipMgr.configure(stateAdapter);
1118
+ if ((_this$sceneViewer0 = this.sceneViewer) !== null && _this$sceneViewer0 !== void 0 && _this$sceneViewer0.managers) {
1119
+ this.sceneViewer.managers.componentTooltipManager = tooltipMgr;
1120
+ }
1121
+ }
1122
+ var ioBehavMgr = ((_this$managers4 = this.managers) === null || _this$managers4 === void 0 ? void 0 : _this$managers4.ioBehaviorManager) || ((_this$sceneViewer1 = this.sceneViewer) === null || _this$sceneViewer1 === void 0 || (_this$sceneViewer1 = _this$sceneViewer1.managers) === null || _this$sceneViewer1 === void 0 ? void 0 : _this$sceneViewer1.ioBehaviorManager) || ((_this$sceneViewer10 = this.sceneViewer) === null || _this$sceneViewer10 === void 0 ? void 0 : _this$sceneViewer10.ioBehaviorManager);
1123
+ if (ioBehavMgr !== null && ioBehavMgr !== void 0 && ioBehavMgr.configure) {
1124
+ ioBehavMgr.configure(stateAdapter);
1125
+ }
1126
+ }
1127
+
1128
+ /**
1129
+ * Set the state of an I/O device instance in the Three.js scene.
1130
+ *
1131
+ * @param {string} attachmentId - IO device attachment ID
1132
+ * @param {string} stateId - Data-point / state ID (e.g. 'power', 'level')
1133
+ * @param {*} value - New state value
1134
+ * @param {string} [parentUuid] - Parent component instance UUID
1135
+ * @returns {boolean}
1136
+ */
1137
+ }, {
1138
+ key: "setIoDeviceState",
1139
+ value: function setIoDeviceState(attachmentId, stateId, value, parentUuid) {
1140
+ this._dispatchIoState(attachmentId, stateId, value, parentUuid);
1145
1141
  return true;
1146
1142
  }
1147
1143
 
@@ -1158,8 +1154,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1158
1154
  }, {
1159
1155
  key: "getSceneAttachments",
1160
1156
  value: function getSceneAttachments() {
1161
- var _this$sceneViewer8;
1162
- var scene = (_this$sceneViewer8 = this.sceneViewer) === null || _this$sceneViewer8 === void 0 ? void 0 : _this$sceneViewer8.scene;
1157
+ var _this$sceneViewer11;
1158
+ var scene = (_this$sceneViewer11 = this.sceneViewer) === null || _this$sceneViewer11 === void 0 ? void 0 : _this$sceneViewer11.scene;
1163
1159
  if (!scene) return [];
1164
1160
  var results = [];
1165
1161
  scene.traverse(function (obj) {
@@ -1867,6 +1863,58 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1867
1863
  }
1868
1864
  return extendComponentDictionary;
1869
1865
  }()
1866
+ /**
1867
+ * Merge mesh animation configs into the component dictionary.
1868
+ * @param {Object<string, { behaviorConfig?: Array, meshNameMap?: Object }>} configsByAssetId
1869
+ * @returns {number} Count of dictionary entries updated
1870
+ */
1871
+ )
1872
+ }, {
1873
+ key: "mergeBehaviorConfigsIntoDictionary",
1874
+ value: function mergeBehaviorConfigsIntoDictionary(configsByAssetId) {
1875
+ if (!this.managers.componentDataManager) {
1876
+ console.warn('⚠️ mergeBehaviorConfigsIntoDictionary(): Component data manager not available');
1877
+ return 0;
1878
+ }
1879
+ return this.managers.componentDataManager.mergeBehaviorConfigsIntoDictionary(configsByAssetId);
1880
+ }
1881
+
1882
+ /**
1883
+ * Scan live scene for I/O device endpoints (for behavior authoring UIs).
1884
+ */
1885
+ }, {
1886
+ key: "scanSceneIoEndpoints",
1887
+ value: function scanSceneIoEndpoints() {
1888
+ return behaviorSceneUtils.scanSceneIoEndpoints(this);
1889
+ }
1890
+
1891
+ /**
1892
+ * Apply cross-component behaviors to scene data and the runtime manager.
1893
+ */
1894
+ }, {
1895
+ key: "setSceneBehaviors",
1896
+ value: function setSceneBehaviors(behaviors) {
1897
+ behaviorSceneUtils.applyCrossComponentBehaviors(this, behaviors);
1898
+ }
1899
+
1900
+ /**
1901
+ * Read cross-component behaviors from the current scene data mirrors.
1902
+ */
1903
+ }, {
1904
+ key: "getSceneBehaviors",
1905
+ value: function getSceneBehaviors() {
1906
+ return behaviorSceneUtils.loadCrossComponentBehaviors(this);
1907
+ }
1908
+
1909
+ /**
1910
+ * Re-register all intra- and cross-component behaviors on placed instances.
1911
+ */
1912
+ }, {
1913
+ key: "reregisterSceneBehaviors",
1914
+ value: function reregisterSceneBehaviors() {
1915
+ behaviorSceneUtils.reregisterSceneBehaviors(this);
1916
+ }
1917
+
1870
1918
  /**
1871
1919
  * Remove S3 components from component dictionary
1872
1920
  * @returns {Promise<boolean>} True if components were removed successfully, false otherwise
@@ -1879,7 +1927,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1879
1927
  * console.log('S3 components removed');
1880
1928
  * }
1881
1929
  */
1882
- )
1883
1930
  }, {
1884
1931
  key: "removeS3Components",
1885
1932
  value: (function () {
@@ -2786,9 +2833,9 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2786
2833
  }, {
2787
2834
  key: "clearScene",
2788
2835
  value: function clearScene() {
2789
- var _this$sceneViewer9;
2836
+ var _this$sceneViewer12;
2790
2837
  this.importedSceneData = null;
2791
- var ioBehavMgr = (_this$sceneViewer9 = this.sceneViewer) === null || _this$sceneViewer9 === void 0 || (_this$sceneViewer9 = _this$sceneViewer9.managers) === null || _this$sceneViewer9 === void 0 ? void 0 : _this$sceneViewer9.ioBehaviorManager;
2838
+ var ioBehavMgr = (_this$sceneViewer12 = this.sceneViewer) === null || _this$sceneViewer12 === void 0 || (_this$sceneViewer12 = _this$sceneViewer12.managers) === null || _this$sceneViewer12 === void 0 ? void 0 : _this$sceneViewer12.ioBehaviorManager;
2792
2839
  if (ioBehavMgr) {
2793
2840
  ioBehavMgr.setCrossComponentBehaviors([]);
2794
2841
  }
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
6
6
  var THREE = require('three');
7
+ var behaviorRegistration = require('../utils/behaviorRegistration.js');
7
8
  var centralPlantValidator = require('./centralPlantValidator.js');
8
9
  var transformControlsManager = require('../managers/controls/transformControlsManager.js');
9
10
  var threeJSResourceManager = require('../managers/system/threeJSResourceManager.js');
@@ -240,6 +241,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
240
241
  // Initialize the component tooltip manager (screen-space tooltip on selection)
241
242
  this.centralPlant.managers.componentTooltipManager = new componentTooltipManager.ComponentTooltipManager(this.centralPlant.sceneViewer);
242
243
  this.centralPlant.sceneViewer.componentTooltipManager = this.centralPlant.managers.componentTooltipManager;
244
+ this.centralPlant.sceneViewer.managers.componentTooltipManager = this.centralPlant.managers.componentTooltipManager;
243
245
  }
244
246
  }
245
247
 
@@ -1148,37 +1150,14 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1148
1150
  // Add attached IO device models for smart components
1149
1151
  if (componentData.isSmart && componentData.attachedDevices) {
1150
1152
  var _this$centralPlant$sc8;
1151
- ioDeviceUtils.attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
1152
-
1153
- // Register behavior configs so IoBehaviorManager can respond to state changes
1154
1153
  var ioBehavMgr = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 || (_this$centralPlant$sc8 = _this$centralPlant$sc8.managers) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.ioBehaviorManager;
1155
- if (ioBehavMgr) {
1156
- var _loop = function _loop() {
1157
- var _modelPreloader$compo;
1158
- var _Object$entries$_i = _rollupPluginBabelHelpers.slicedToArray(_Object$entries[_i], 2),
1159
- attachmentId = _Object$entries$_i[0],
1160
- attachment = _Object$entries$_i[1];
1161
- var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
1162
- if (!(deviceData !== null && deviceData !== void 0 && deviceData.behaviorConfig)) return 1; // continue
1163
- var deviceRoot = null;
1164
- componentModel.traverse(function (obj) {
1165
- var _obj$userData2;
1166
- if (!deviceRoot && ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.attachmentId) === attachmentId) deviceRoot = obj;
1167
- });
1168
- if (deviceRoot) {
1169
- ioBehavMgr.loadBehaviors(attachmentId, deviceData.behaviorConfig, deviceRoot, componentId);
1170
- }
1171
- };
1172
- for (var _i = 0, _Object$entries = Object.entries(componentData.attachedDevices); _i < _Object$entries.length; _i++) {
1173
- if (_loop()) continue;
1154
+ ioDeviceUtils.attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId).then(function () {
1155
+ if (ioBehavMgr) {
1156
+ behaviorRegistration.registerBehaviorsForComponent(ioBehavMgr, componentId, componentData, componentModel, modelPreloader.componentDictionary);
1174
1157
  }
1175
-
1176
- // Register component-level behaviors (intra-component io-device linking)
1177
- if (componentData.behaviors && componentData.behaviors.length > 0) {
1178
- // Registering ${componentData.behaviors.length} component-level behavior(s)
1179
- ioBehavMgr.registerComponentBehaviors(componentId, componentData.behaviors);
1180
- }
1181
- }
1158
+ }).catch(function (err) {
1159
+ console.error("\u274C Error attaching IO devices for ".concat(libraryId, ":"), err);
1160
+ });
1182
1161
  }
1183
1162
 
1184
1163
  // Notify the component manager about the new component
@@ -1308,8 +1287,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1308
1287
  // the component (e.g., dynamically added but not yet synced to sceneData)
1309
1288
  if (connectorIds.size === 0 && threeScene) {
1310
1289
  threeScene.traverse(function (obj) {
1311
- var _obj$userData3, _obj$userData4;
1312
- if ((obj.uuid === resolvedUuid || ((_obj$userData3 = obj.userData) === null || _obj$userData3 === void 0 ? void 0 : _obj$userData3.originalUuid) === resolvedUuid) && ((_obj$userData4 = obj.userData) === null || _obj$userData4 === void 0 ? void 0 : _obj$userData4.objectType) === 'component') {
1290
+ var _obj$userData2, _obj$userData3;
1291
+ if ((obj.uuid === resolvedUuid || ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.originalUuid) === resolvedUuid) && ((_obj$userData3 = obj.userData) === null || _obj$userData3 === void 0 ? void 0 : _obj$userData3.objectType) === 'component') {
1313
1292
  obj.children.forEach(function (child) {
1314
1293
  var _child$userData3;
1315
1294
  if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'connector') {
@@ -1353,18 +1332,23 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1353
1332
  // Step 5: Remove the component from the Three.js scene
1354
1333
  var success = componentManager.removeComponentFromScene(componentId);
1355
1334
  if (success) {
1335
+ var _this$centralPlant$sc10;
1336
+ var ioBehavMgr = (_this$centralPlant$sc10 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc10 === void 0 || (_this$centralPlant$sc10 = _this$centralPlant$sc10.managers) === null || _this$centralPlant$sc10 === void 0 ? void 0 : _this$centralPlant$sc10.ioBehaviorManager;
1337
+ if (ioBehavMgr !== null && ioBehavMgr !== void 0 && ioBehavMgr.unloadForComponent) {
1338
+ ioBehavMgr.unloadForComponent(resolvedUuid);
1339
+ }
1356
1340
  // Step 6: Directly remove SEGMENT-* and Gateway objects from Three.js whose
1357
1341
  // pathFrom/pathTo references one of this component's connectors.
1358
1342
  // This is surgical cleanup that works regardless of shouldUpdatePaths.
1359
1343
  if (connectorIds.size > 0 && threeScene) {
1360
1344
  var objectsToRemove = [];
1361
1345
  threeScene.traverse(function (obj) {
1362
- var _obj$uuid, _obj$userData5, _obj$uuid2, _obj$userData6;
1363
- var isComputedSegment = ((_obj$uuid = obj.uuid) === null || _obj$uuid === void 0 ? void 0 : _obj$uuid.startsWith('SEGMENT-')) && ((_obj$userData5 = obj.userData) === null || _obj$userData5 === void 0 ? void 0 : _obj$userData5.isDeclared) !== true;
1364
- var isComputedGateway = ((_obj$uuid2 = obj.uuid) === null || _obj$uuid2 === void 0 ? void 0 : _obj$uuid2.includes('Gateway')) && ((_obj$userData6 = obj.userData) === null || _obj$userData6 === void 0 ? void 0 : _obj$userData6.isDeclared) !== true;
1346
+ var _obj$uuid, _obj$userData4, _obj$uuid2, _obj$userData5;
1347
+ var isComputedSegment = ((_obj$uuid = obj.uuid) === null || _obj$uuid === void 0 ? void 0 : _obj$uuid.startsWith('SEGMENT-')) && ((_obj$userData4 = obj.userData) === null || _obj$userData4 === void 0 ? void 0 : _obj$userData4.isDeclared) !== true;
1348
+ var isComputedGateway = ((_obj$uuid2 = obj.uuid) === null || _obj$uuid2 === void 0 ? void 0 : _obj$uuid2.includes('Gateway')) && ((_obj$userData5 = obj.userData) === null || _obj$userData5 === void 0 ? void 0 : _obj$userData5.isDeclared) !== true;
1365
1349
  if (isComputedSegment || isComputedGateway) {
1366
- var _obj$userData7, _obj$userData8;
1367
- if (connectorIds.has((_obj$userData7 = obj.userData) === null || _obj$userData7 === void 0 ? void 0 : _obj$userData7.pathFrom) || connectorIds.has((_obj$userData8 = obj.userData) === null || _obj$userData8 === void 0 ? void 0 : _obj$userData8.pathTo)) {
1350
+ var _obj$userData6, _obj$userData7;
1351
+ if (connectorIds.has((_obj$userData6 = obj.userData) === null || _obj$userData6 === void 0 ? void 0 : _obj$userData6.pathFrom) || connectorIds.has((_obj$userData7 = obj.userData) === null || _obj$userData7 === void 0 ? void 0 : _obj$userData7.pathTo)) {
1368
1352
  objectsToRemove.push(obj);
1369
1353
  }
1370
1354
  }
@@ -14,6 +14,11 @@ var sceneTooltipsManager = require('./managers/scene/sceneTooltipsManager.js');
14
14
  var componentTooltipManager = require('./managers/scene/componentTooltipManager.js');
15
15
  var sceneHierarchyManager = require('./managers/scene/sceneHierarchyManager.js');
16
16
  var IoBehaviorManager = require('./managers/behaviors/IoBehaviorManager.js');
17
+ var behaviorSchema = require('./utils/behaviorSchema.js');
18
+ var behaviorRegistration = require('./utils/behaviorRegistration.js');
19
+ var behaviorDispatch = require('./utils/behaviorDispatch.js');
20
+ var behaviorSceneUtils = require('./utils/behaviorSceneUtils.js');
21
+ var animationTransformUtils = require('./utils/animationTransformUtils.js');
17
22
  var componentManager = require('./managers/components/componentManager.js');
18
23
  var animationManager = require('./managers/scene/animationManager.js');
19
24
  var pathfindingManager = require('./managers/pathfinding/pathfindingManager.js');
@@ -68,6 +73,24 @@ exports.SceneTooltipsManager = sceneTooltipsManager.SceneTooltipsManager;
68
73
  exports.ComponentTooltipManager = componentTooltipManager.ComponentTooltipManager;
69
74
  exports.SceneHierarchyManager = sceneHierarchyManager.SceneHierarchyManager;
70
75
  exports.IoBehaviorManager = IoBehaviorManager.IoBehaviorManager;
76
+ exports.buildCrossBehavior = behaviorSchema.buildCrossBehavior;
77
+ exports.buildIntraBehavior = behaviorSchema.buildIntraBehavior;
78
+ exports.normalizeBehavior = behaviorSchema.normalizeBehavior;
79
+ exports.parseCrossBehavior = behaviorSchema.parseCrossBehavior;
80
+ exports.parseIntraBehavior = behaviorSchema.parseIntraBehavior;
81
+ exports.registerBehaviorsForComponent = behaviorRegistration.registerBehaviorsForComponent;
82
+ exports.reloadBehaviorsForDeviceAsset = behaviorRegistration.reloadBehaviorsForDeviceAsset;
83
+ exports.getIoBehaviorManager = behaviorDispatch.getIoBehaviorManager;
84
+ exports.getScopedAttachmentKey = behaviorDispatch.getScopedAttachmentKey;
85
+ exports.resolveDataPoints = behaviorDispatch.resolveDataPoints;
86
+ exports.applyCrossComponentBehaviors = behaviorSceneUtils.applyCrossComponentBehaviors;
87
+ exports.loadCrossComponentBehaviors = behaviorSceneUtils.loadCrossComponentBehaviors;
88
+ exports.refreshSceneIntraBehaviors = behaviorSceneUtils.refreshSceneIntraBehaviors;
89
+ exports.reregisterSceneBehaviors = behaviorSceneUtils.reregisterSceneBehaviors;
90
+ exports.scanSceneIoEndpoints = behaviorSceneUtils.scanSceneIoEndpoints;
91
+ exports.applyModelRootTranslation = animationTransformUtils.applyModelRootTranslation;
92
+ exports.applyModelRootTranslationFromWorldBase = animationTransformUtils.applyModelRootTranslationFromWorldBase;
93
+ exports.modelOffsetToWorldDelta = animationTransformUtils.modelOffsetToWorldDelta;
71
94
  exports.ComponentManager = componentManager.ComponentManager;
72
95
  exports.AnimationManager = animationManager.AnimationManager;
73
96
  exports.PathfindingManager = pathfindingManager.PathfindingManager;