@2112-lab/central-plant 0.3.25 → 0.3.26

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.
@@ -31513,13 +31513,14 @@ var ModelManager = /*#__PURE__*/function () {
31513
31513
  break;
31514
31514
  }
31515
31515
  _loop = /*#__PURE__*/_regenerator().m(function _loop() {
31516
- var _modelPreloader$compo;
31516
+ var _modelPreloader$compo, _deviceData$animation;
31517
31517
  var _Object$entries$_i, attachmentId, attachment, deviceData, deviceRoot;
31518
31518
  return _regenerator().w(function (_context) {
31519
31519
  while (1) switch (_context.n) {
31520
31520
  case 0:
31521
31521
  _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), attachmentId = _Object$entries$_i[0], attachment = _Object$entries$_i[1];
31522
31522
  deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
31523
+ console.log("[ModelManager] attachment \"".concat(attachmentId, "\" \u2192 deviceId \"").concat(attachment.deviceId, "\" \u2192 animationConfig:"), (_deviceData$animation = deviceData === null || deviceData === void 0 ? void 0 : deviceData.animationConfig) !== null && _deviceData$animation !== void 0 ? _deviceData$animation : 'NONE');
31523
31524
  if (deviceData !== null && deviceData !== void 0 && deviceData.animationConfig) {
31524
31525
  _context.n = 1;
31525
31526
  break;
@@ -37187,20 +37188,24 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
37187
37188
  object.traverse(function (child) {
37188
37189
  var _child$userData;
37189
37190
  if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'io-device') {
37190
- var _this2$sceneViewer;
37191
+ var _this2$sceneViewer$ma, _this2$sceneViewer;
37191
37192
  var attachmentId = child.userData.attachmentId || '';
37192
37193
 
37193
- // Prefer data point definitions from the animate window (richer, user-authored).
37194
- // Fall back to the static ioConfig.states[] snapshot on the mesh userData.
37195
- var animDps = (_this2$sceneViewer = _this2.sceneViewer) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.managers) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.ioAnimationManager) === null || _this2$sceneViewer === void 0 ? void 0 : _this2$sceneViewer.getAnimationDataPoints(parentUuid, attachmentId);
37196
- var dataPoints = (animDps === null || animDps === void 0 ? void 0 : animDps.length) > 0 ? animDps : child.userData.dataPoints || [];
37194
+ // Use only data points from the animate window (animationConfig).
37195
+ // The static ioConfig.states[] snapshot on userData is intentionally ignored.
37196
+ var dataPoints = (_this2$sceneViewer$ma = (_this2$sceneViewer = _this2.sceneViewer) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.managers) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.ioAnimationManager) === null || _this2$sceneViewer === void 0 ? void 0 : _this2$sceneViewer.getAnimationDataPoints(parentUuid, attachmentId)) !== null && _this2$sceneViewer$ma !== void 0 ? _this2$sceneViewer$ma : [];
37197
+
37198
+ // When data points come from animationConfig they already carry direction:'input'.
37199
+ // Pass null so _buildDataPointRow uses the per-dp direction instead of the
37200
+ // device-level ioDirection (which may be 'output' and would hide controls).
37201
+ var deviceDirection = dataPoints.length > 0 ? null : child.userData.ioDirection || 'output';
37197
37202
  devices.push({
37198
37203
  label: child.userData.attachmentLabel || child.name || child.userData.deviceId || 'Unknown Device',
37199
37204
  deviceId: child.userData.deviceId || '',
37200
37205
  attachmentId: attachmentId,
37201
37206
  scopedAttachmentId: _this2._getScopedAttachmentKey(attachmentId, parentUuid),
37202
37207
  dataPoints: dataPoints,
37203
- direction: child.userData.ioDirection || 'output'
37208
+ direction: deviceDirection
37204
37209
  });
37205
37210
  }
37206
37211
  });
@@ -37674,7 +37679,11 @@ var IoAnimationManager = /*#__PURE__*/function (_BaseDisposable) {
37674
37679
  }
37675
37680
  if (entries.length) {
37676
37681
  this._entries.set(key, entries);
37677
- console.log("[IoAnimationManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ")"));
37682
+ console.log("[IoAnimationManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ") \u2014 stateVariables: ").concat(entries.map(function (e) {
37683
+ return e.anim.stateVariable;
37684
+ }).join(', ')));
37685
+ } else {
37686
+ console.warn("[IoAnimationManager] No mesh entries resolved for attachment \"".concat(attachmentId, "\" \u2014 animationConfig had ").concat(anims.length, " entries but none matched a mesh"));
37678
37687
  }
37679
37688
  }
37680
37689
 
@@ -39217,15 +39226,40 @@ var CentralPlantInternals = /*#__PURE__*/function () {
39217
39226
 
39218
39227
  // Add attached IO device models for smart components
39219
39228
  if (componentData.isSmart && componentData.attachedDevices) {
39229
+ var _this$centralPlant$sc8;
39220
39230
  attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
39231
+
39232
+ // Register animation configs so IoAnimationManager can respond to state changes
39233
+ var ioAnimMgr = (_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.ioAnimationManager;
39234
+ if (ioAnimMgr) {
39235
+ var _loop = function _loop() {
39236
+ var _modelPreloader$compo;
39237
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
39238
+ attachmentId = _Object$entries$_i[0],
39239
+ attachment = _Object$entries$_i[1];
39240
+ var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
39241
+ if (!(deviceData !== null && deviceData !== void 0 && deviceData.animationConfig)) return 1; // continue
39242
+ var deviceRoot = null;
39243
+ componentModel.traverse(function (obj) {
39244
+ var _obj$userData2;
39245
+ if (!deviceRoot && ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.attachmentId) === attachmentId) deviceRoot = obj;
39246
+ });
39247
+ if (deviceRoot) {
39248
+ ioAnimMgr.loadAnimations(attachmentId, deviceData.animationConfig, deviceRoot, componentId);
39249
+ }
39250
+ };
39251
+ for (var _i = 0, _Object$entries = Object.entries(componentData.attachedDevices); _i < _Object$entries.length; _i++) {
39252
+ if (_loop()) continue;
39253
+ }
39254
+ }
39221
39255
  }
39222
39256
 
39223
39257
  // Register default behaviors for smart components so the BehaviorManager
39224
39258
  // responds to tooltip-driven state changes immediately after drop.
39225
39259
  // (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
39226
39260
  if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
39227
- var _this$centralPlant$sc8, _som$registerBehavior;
39228
- var som = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.sceneOperationsManager;
39261
+ var _this$centralPlant$sc9, _som$registerBehavior;
39262
+ var som = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.sceneOperationsManager;
39229
39263
  som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
39230
39264
  }
39231
39265
 
@@ -39287,18 +39321,18 @@ var CentralPlantInternals = /*#__PURE__*/function () {
39287
39321
  }, {
39288
39322
  key: "deleteComponent",
39289
39323
  value: function deleteComponent(componentId) {
39290
- var _this$centralPlant$sc9;
39324
+ var _this$centralPlant$sc0;
39291
39325
  // Check if component manager is available
39292
- var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
39326
+ var componentManager = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.componentManager;
39293
39327
  if (!componentManager) {
39294
39328
  console.error('❌ deleteComponent(): Component manager not available');
39295
39329
  return false;
39296
39330
  }
39297
39331
  try {
39298
- var _this$centralPlant$sc0, _this$centralPlant$sc1, _sceneData$scene2, _sceneData$scene3;
39332
+ var _this$centralPlant$sc1, _this$centralPlant$sc10, _sceneData$scene2, _sceneData$scene3;
39299
39333
  console.log("\uD83D\uDDD1\uFE0F deleteComponent(): Deleting component ".concat(componentId));
39300
- var threeScene = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.scene;
39301
- var sceneData = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.currentSceneData;
39334
+ var threeScene = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.scene;
39335
+ var sceneData = (_this$centralPlant$sc10 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc10 === void 0 ? void 0 : _this$centralPlant$sc10.currentSceneData;
39302
39336
 
39303
39337
  // Step 1: Resolve the actual Three.js UUID from componentId.
39304
39338
  // The UI emits object.name (e.g. "Pump (PUMP-1)") as the selection ID, but
@@ -39342,8 +39376,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
39342
39376
  // the component (e.g., dynamically added but not yet synced to sceneData)
39343
39377
  if (connectorIds.size === 0 && threeScene) {
39344
39378
  threeScene.traverse(function (obj) {
39345
- var _obj$userData2, _obj$userData3;
39346
- 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') {
39379
+ var _obj$userData3, _obj$userData4;
39380
+ 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') {
39347
39381
  obj.children.forEach(function (child) {
39348
39382
  var _child$userData3;
39349
39383
  if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'connector') {
@@ -39393,12 +39427,12 @@ var CentralPlantInternals = /*#__PURE__*/function () {
39393
39427
  if (connectorIds.size > 0 && threeScene) {
39394
39428
  var objectsToRemove = [];
39395
39429
  threeScene.traverse(function (obj) {
39396
- var _obj$uuid, _obj$userData4, _obj$uuid2, _obj$userData5;
39397
- 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;
39398
- 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;
39430
+ var _obj$uuid, _obj$userData5, _obj$uuid2, _obj$userData6;
39431
+ 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;
39432
+ 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;
39399
39433
  if (isComputedSegment || isComputedGateway) {
39400
- var _obj$userData6, _obj$userData7;
39401
- 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)) {
39434
+ var _obj$userData7, _obj$userData8;
39435
+ 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)) {
39402
39436
  objectsToRemove.push(obj);
39403
39437
  }
39404
39438
  }
@@ -39513,7 +39547,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
39513
39547
  * Initialize the CentralPlant manager
39514
39548
  *
39515
39549
  * @constructor
39516
- * @version 0.3.25
39550
+ * @version 0.3.26
39517
39551
  * @updated 2025-10-22
39518
39552
  *
39519
39553
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -35,7 +35,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
35
35
  * Initialize the CentralPlant manager
36
36
  *
37
37
  * @constructor
38
- * @version 0.3.25
38
+ * @version 0.3.26
39
39
  * @updated 2025-10-22
40
40
  *
41
41
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -1148,15 +1148,40 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1148
1148
 
1149
1149
  // Add attached IO device models for smart components
1150
1150
  if (componentData.isSmart && componentData.attachedDevices) {
1151
+ var _this$centralPlant$sc8;
1151
1152
  ioDeviceUtils.attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
1153
+
1154
+ // Register animation configs so IoAnimationManager can respond to state changes
1155
+ var ioAnimMgr = (_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.ioAnimationManager;
1156
+ if (ioAnimMgr) {
1157
+ var _loop = function _loop() {
1158
+ var _modelPreloader$compo;
1159
+ var _Object$entries$_i = _rollupPluginBabelHelpers.slicedToArray(_Object$entries[_i], 2),
1160
+ attachmentId = _Object$entries$_i[0],
1161
+ attachment = _Object$entries$_i[1];
1162
+ var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
1163
+ if (!(deviceData !== null && deviceData !== void 0 && deviceData.animationConfig)) return 1; // continue
1164
+ var deviceRoot = null;
1165
+ componentModel.traverse(function (obj) {
1166
+ var _obj$userData2;
1167
+ if (!deviceRoot && ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.attachmentId) === attachmentId) deviceRoot = obj;
1168
+ });
1169
+ if (deviceRoot) {
1170
+ ioAnimMgr.loadAnimations(attachmentId, deviceData.animationConfig, deviceRoot, componentId);
1171
+ }
1172
+ };
1173
+ for (var _i = 0, _Object$entries = Object.entries(componentData.attachedDevices); _i < _Object$entries.length; _i++) {
1174
+ if (_loop()) continue;
1175
+ }
1176
+ }
1152
1177
  }
1153
1178
 
1154
1179
  // Register default behaviors for smart components so the BehaviorManager
1155
1180
  // responds to tooltip-driven state changes immediately after drop.
1156
1181
  // (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
1157
1182
  if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
1158
- var _this$centralPlant$sc8, _som$registerBehavior;
1159
- var som = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.sceneOperationsManager;
1183
+ var _this$centralPlant$sc9, _som$registerBehavior;
1184
+ var som = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.sceneOperationsManager;
1160
1185
  som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
1161
1186
  }
1162
1187
 
@@ -1218,18 +1243,18 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1218
1243
  }, {
1219
1244
  key: "deleteComponent",
1220
1245
  value: function deleteComponent(componentId) {
1221
- var _this$centralPlant$sc9;
1246
+ var _this$centralPlant$sc0;
1222
1247
  // Check if component manager is available
1223
- var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
1248
+ var componentManager = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.componentManager;
1224
1249
  if (!componentManager) {
1225
1250
  console.error('❌ deleteComponent(): Component manager not available');
1226
1251
  return false;
1227
1252
  }
1228
1253
  try {
1229
- var _this$centralPlant$sc0, _this$centralPlant$sc1, _sceneData$scene2, _sceneData$scene3;
1254
+ var _this$centralPlant$sc1, _this$centralPlant$sc10, _sceneData$scene2, _sceneData$scene3;
1230
1255
  console.log("\uD83D\uDDD1\uFE0F deleteComponent(): Deleting component ".concat(componentId));
1231
- var threeScene = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.scene;
1232
- var sceneData = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.currentSceneData;
1256
+ var threeScene = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.scene;
1257
+ var sceneData = (_this$centralPlant$sc10 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc10 === void 0 ? void 0 : _this$centralPlant$sc10.currentSceneData;
1233
1258
 
1234
1259
  // Step 1: Resolve the actual Three.js UUID from componentId.
1235
1260
  // The UI emits object.name (e.g. "Pump (PUMP-1)") as the selection ID, but
@@ -1273,8 +1298,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1273
1298
  // the component (e.g., dynamically added but not yet synced to sceneData)
1274
1299
  if (connectorIds.size === 0 && threeScene) {
1275
1300
  threeScene.traverse(function (obj) {
1276
- var _obj$userData2, _obj$userData3;
1277
- 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') {
1301
+ var _obj$userData3, _obj$userData4;
1302
+ 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') {
1278
1303
  obj.children.forEach(function (child) {
1279
1304
  var _child$userData3;
1280
1305
  if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'connector') {
@@ -1324,12 +1349,12 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1324
1349
  if (connectorIds.size > 0 && threeScene) {
1325
1350
  var objectsToRemove = [];
1326
1351
  threeScene.traverse(function (obj) {
1327
- var _obj$uuid, _obj$userData4, _obj$uuid2, _obj$userData5;
1328
- 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;
1329
- 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;
1352
+ var _obj$uuid, _obj$userData5, _obj$uuid2, _obj$userData6;
1353
+ 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;
1354
+ 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;
1330
1355
  if (isComputedSegment || isComputedGateway) {
1331
- var _obj$userData6, _obj$userData7;
1332
- 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)) {
1356
+ var _obj$userData7, _obj$userData8;
1357
+ 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)) {
1333
1358
  objectsToRemove.push(obj);
1334
1359
  }
1335
1360
  }
@@ -94,7 +94,11 @@ var IoAnimationManager = /*#__PURE__*/function (_BaseDisposable) {
94
94
  }
95
95
  if (entries.length) {
96
96
  this._entries.set(key, entries);
97
- console.log("[IoAnimationManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ")"));
97
+ console.log("[IoAnimationManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ") \u2014 stateVariables: ").concat(entries.map(function (e) {
98
+ return e.anim.stateVariable;
99
+ }).join(', ')));
100
+ } else {
101
+ console.warn("[IoAnimationManager] No mesh entries resolved for attachment \"".concat(attachmentId, "\" \u2014 animationConfig had ").concat(anims.length, " entries but none matched a mesh"));
98
102
  }
99
103
  }
100
104
 
@@ -287,20 +287,24 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
287
287
  object.traverse(function (child) {
288
288
  var _child$userData;
289
289
  if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'io-device') {
290
- var _this2$sceneViewer;
290
+ var _this2$sceneViewer$ma, _this2$sceneViewer;
291
291
  var attachmentId = child.userData.attachmentId || '';
292
292
 
293
- // Prefer data point definitions from the animate window (richer, user-authored).
294
- // Fall back to the static ioConfig.states[] snapshot on the mesh userData.
295
- var animDps = (_this2$sceneViewer = _this2.sceneViewer) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.managers) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.ioAnimationManager) === null || _this2$sceneViewer === void 0 ? void 0 : _this2$sceneViewer.getAnimationDataPoints(parentUuid, attachmentId);
296
- var dataPoints = (animDps === null || animDps === void 0 ? void 0 : animDps.length) > 0 ? animDps : child.userData.dataPoints || [];
293
+ // Use only data points from the animate window (animationConfig).
294
+ // The static ioConfig.states[] snapshot on userData is intentionally ignored.
295
+ var dataPoints = (_this2$sceneViewer$ma = (_this2$sceneViewer = _this2.sceneViewer) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.managers) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.ioAnimationManager) === null || _this2$sceneViewer === void 0 ? void 0 : _this2$sceneViewer.getAnimationDataPoints(parentUuid, attachmentId)) !== null && _this2$sceneViewer$ma !== void 0 ? _this2$sceneViewer$ma : [];
296
+
297
+ // When data points come from animationConfig they already carry direction:'input'.
298
+ // Pass null so _buildDataPointRow uses the per-dp direction instead of the
299
+ // device-level ioDirection (which may be 'output' and would hide controls).
300
+ var deviceDirection = dataPoints.length > 0 ? null : child.userData.ioDirection || 'output';
297
301
  devices.push({
298
302
  label: child.userData.attachmentLabel || child.name || child.userData.deviceId || 'Unknown Device',
299
303
  deviceId: child.userData.deviceId || '',
300
304
  attachmentId: attachmentId,
301
305
  scopedAttachmentId: _this2._getScopedAttachmentKey(attachmentId, parentUuid),
302
306
  dataPoints: dataPoints,
303
- direction: child.userData.ioDirection || 'output'
307
+ direction: deviceDirection
304
308
  });
305
309
  }
306
310
  });
@@ -127,13 +127,14 @@ var ModelManager = /*#__PURE__*/function () {
127
127
  break;
128
128
  }
129
129
  _loop = /*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _loop() {
130
- var _modelPreloader$compo;
130
+ var _modelPreloader$compo, _deviceData$animation;
131
131
  var _Object$entries$_i, attachmentId, attachment, deviceData, deviceRoot;
132
132
  return _rollupPluginBabelHelpers.regenerator().w(function (_context) {
133
133
  while (1) switch (_context.n) {
134
134
  case 0:
135
135
  _Object$entries$_i = _rollupPluginBabelHelpers.slicedToArray(_Object$entries[_i], 2), attachmentId = _Object$entries$_i[0], attachment = _Object$entries$_i[1];
136
136
  deviceData = (_modelPreloader$compo = modelPreloader["default"].componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
137
+ console.log("[ModelManager] attachment \"".concat(attachmentId, "\" \u2192 deviceId \"").concat(attachment.deviceId, "\" \u2192 animationConfig:"), (_deviceData$animation = deviceData === null || deviceData === void 0 ? void 0 : deviceData.animationConfig) !== null && _deviceData$animation !== void 0 ? _deviceData$animation : 'NONE');
137
138
  if (deviceData !== null && deviceData !== void 0 && deviceData.animationConfig) {
138
139
  _context.n = 1;
139
140
  break;
@@ -31,7 +31,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
31
31
  * Initialize the CentralPlant manager
32
32
  *
33
33
  * @constructor
34
- * @version 0.3.25
34
+ * @version 0.3.26
35
35
  * @updated 2025-10-22
36
36
  *
37
37
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -1,4 +1,4 @@
1
- import { createClass as _createClass, objectSpread2 as _objectSpread2, createForOfIteratorHelper as _createForOfIteratorHelper, typeof as _typeof, toConsumableArray as _toConsumableArray, classCallCheck as _classCallCheck, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../_virtual/_rollupPluginBabelHelpers.js';
1
+ import { createClass as _createClass, objectSpread2 as _objectSpread2, createForOfIteratorHelper as _createForOfIteratorHelper, typeof as _typeof, slicedToArray as _slicedToArray, toConsumableArray as _toConsumableArray, classCallCheck as _classCallCheck, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../_virtual/_rollupPluginBabelHelpers.js';
2
2
  import * as THREE from 'three';
3
3
  import { CentralPlantValidator } from './centralPlantValidator.js';
4
4
  import { createTransformControls } from '../managers/controls/transformControlsManager.js';
@@ -1124,15 +1124,40 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1124
1124
 
1125
1125
  // Add attached IO device models for smart components
1126
1126
  if (componentData.isSmart && componentData.attachedDevices) {
1127
+ var _this$centralPlant$sc8;
1127
1128
  attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId);
1129
+
1130
+ // Register animation configs so IoAnimationManager can respond to state changes
1131
+ var ioAnimMgr = (_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.ioAnimationManager;
1132
+ if (ioAnimMgr) {
1133
+ var _loop = function _loop() {
1134
+ var _modelPreloader$compo;
1135
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
1136
+ attachmentId = _Object$entries$_i[0],
1137
+ attachment = _Object$entries$_i[1];
1138
+ var deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
1139
+ if (!(deviceData !== null && deviceData !== void 0 && deviceData.animationConfig)) return 1; // continue
1140
+ var deviceRoot = null;
1141
+ componentModel.traverse(function (obj) {
1142
+ var _obj$userData2;
1143
+ if (!deviceRoot && ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.attachmentId) === attachmentId) deviceRoot = obj;
1144
+ });
1145
+ if (deviceRoot) {
1146
+ ioAnimMgr.loadAnimations(attachmentId, deviceData.animationConfig, deviceRoot, componentId);
1147
+ }
1148
+ };
1149
+ for (var _i = 0, _Object$entries = Object.entries(componentData.attachedDevices); _i < _Object$entries.length; _i++) {
1150
+ if (_loop()) continue;
1151
+ }
1152
+ }
1128
1153
  }
1129
1154
 
1130
1155
  // Register default behaviors for smart components so the BehaviorManager
1131
1156
  // responds to tooltip-driven state changes immediately after drop.
1132
1157
  // (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
1133
1158
  if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
1134
- var _this$centralPlant$sc8, _som$registerBehavior;
1135
- var som = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.sceneOperationsManager;
1159
+ var _this$centralPlant$sc9, _som$registerBehavior;
1160
+ var som = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.sceneOperationsManager;
1136
1161
  som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
1137
1162
  }
1138
1163
 
@@ -1194,18 +1219,18 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1194
1219
  }, {
1195
1220
  key: "deleteComponent",
1196
1221
  value: function deleteComponent(componentId) {
1197
- var _this$centralPlant$sc9;
1222
+ var _this$centralPlant$sc0;
1198
1223
  // Check if component manager is available
1199
- var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
1224
+ var componentManager = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.componentManager;
1200
1225
  if (!componentManager) {
1201
1226
  console.error('❌ deleteComponent(): Component manager not available');
1202
1227
  return false;
1203
1228
  }
1204
1229
  try {
1205
- var _this$centralPlant$sc0, _this$centralPlant$sc1, _sceneData$scene2, _sceneData$scene3;
1230
+ var _this$centralPlant$sc1, _this$centralPlant$sc10, _sceneData$scene2, _sceneData$scene3;
1206
1231
  console.log("\uD83D\uDDD1\uFE0F deleteComponent(): Deleting component ".concat(componentId));
1207
- var threeScene = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.scene;
1208
- var sceneData = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.currentSceneData;
1232
+ var threeScene = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.scene;
1233
+ var sceneData = (_this$centralPlant$sc10 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc10 === void 0 ? void 0 : _this$centralPlant$sc10.currentSceneData;
1209
1234
 
1210
1235
  // Step 1: Resolve the actual Three.js UUID from componentId.
1211
1236
  // The UI emits object.name (e.g. "Pump (PUMP-1)") as the selection ID, but
@@ -1249,8 +1274,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1249
1274
  // the component (e.g., dynamically added but not yet synced to sceneData)
1250
1275
  if (connectorIds.size === 0 && threeScene) {
1251
1276
  threeScene.traverse(function (obj) {
1252
- var _obj$userData2, _obj$userData3;
1253
- 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') {
1277
+ var _obj$userData3, _obj$userData4;
1278
+ 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') {
1254
1279
  obj.children.forEach(function (child) {
1255
1280
  var _child$userData3;
1256
1281
  if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'connector') {
@@ -1300,12 +1325,12 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1300
1325
  if (connectorIds.size > 0 && threeScene) {
1301
1326
  var objectsToRemove = [];
1302
1327
  threeScene.traverse(function (obj) {
1303
- var _obj$uuid, _obj$userData4, _obj$uuid2, _obj$userData5;
1304
- 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;
1305
- 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;
1328
+ var _obj$uuid, _obj$userData5, _obj$uuid2, _obj$userData6;
1329
+ 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;
1330
+ 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;
1306
1331
  if (isComputedSegment || isComputedGateway) {
1307
- var _obj$userData6, _obj$userData7;
1308
- 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)) {
1332
+ var _obj$userData7, _obj$userData8;
1333
+ 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)) {
1309
1334
  objectsToRemove.push(obj);
1310
1335
  }
1311
1336
  }
@@ -70,7 +70,11 @@ var IoAnimationManager = /*#__PURE__*/function (_BaseDisposable) {
70
70
  }
71
71
  if (entries.length) {
72
72
  this._entries.set(key, entries);
73
- console.log("[IoAnimationManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ")"));
73
+ console.log("[IoAnimationManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ") \u2014 stateVariables: ").concat(entries.map(function (e) {
74
+ return e.anim.stateVariable;
75
+ }).join(', ')));
76
+ } else {
77
+ console.warn("[IoAnimationManager] No mesh entries resolved for attachment \"".concat(attachmentId, "\" \u2014 animationConfig had ").concat(anims.length, " entries but none matched a mesh"));
74
78
  }
75
79
  }
76
80
 
@@ -263,20 +263,24 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
263
263
  object.traverse(function (child) {
264
264
  var _child$userData;
265
265
  if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'io-device') {
266
- var _this2$sceneViewer;
266
+ var _this2$sceneViewer$ma, _this2$sceneViewer;
267
267
  var attachmentId = child.userData.attachmentId || '';
268
268
 
269
- // Prefer data point definitions from the animate window (richer, user-authored).
270
- // Fall back to the static ioConfig.states[] snapshot on the mesh userData.
271
- var animDps = (_this2$sceneViewer = _this2.sceneViewer) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.managers) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.ioAnimationManager) === null || _this2$sceneViewer === void 0 ? void 0 : _this2$sceneViewer.getAnimationDataPoints(parentUuid, attachmentId);
272
- var dataPoints = (animDps === null || animDps === void 0 ? void 0 : animDps.length) > 0 ? animDps : child.userData.dataPoints || [];
269
+ // Use only data points from the animate window (animationConfig).
270
+ // The static ioConfig.states[] snapshot on userData is intentionally ignored.
271
+ var dataPoints = (_this2$sceneViewer$ma = (_this2$sceneViewer = _this2.sceneViewer) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.managers) === null || _this2$sceneViewer === void 0 || (_this2$sceneViewer = _this2$sceneViewer.ioAnimationManager) === null || _this2$sceneViewer === void 0 ? void 0 : _this2$sceneViewer.getAnimationDataPoints(parentUuid, attachmentId)) !== null && _this2$sceneViewer$ma !== void 0 ? _this2$sceneViewer$ma : [];
272
+
273
+ // When data points come from animationConfig they already carry direction:'input'.
274
+ // Pass null so _buildDataPointRow uses the per-dp direction instead of the
275
+ // device-level ioDirection (which may be 'output' and would hide controls).
276
+ var deviceDirection = dataPoints.length > 0 ? null : child.userData.ioDirection || 'output';
273
277
  devices.push({
274
278
  label: child.userData.attachmentLabel || child.name || child.userData.deviceId || 'Unknown Device',
275
279
  deviceId: child.userData.deviceId || '',
276
280
  attachmentId: attachmentId,
277
281
  scopedAttachmentId: _this2._getScopedAttachmentKey(attachmentId, parentUuid),
278
282
  dataPoints: dataPoints,
279
- direction: child.userData.ioDirection || 'output'
283
+ direction: deviceDirection
280
284
  });
281
285
  }
282
286
  });
@@ -103,13 +103,14 @@ var ModelManager = /*#__PURE__*/function () {
103
103
  break;
104
104
  }
105
105
  _loop = /*#__PURE__*/_regenerator().m(function _loop() {
106
- var _modelPreloader$compo;
106
+ var _modelPreloader$compo, _deviceData$animation;
107
107
  var _Object$entries$_i, attachmentId, attachment, deviceData, deviceRoot;
108
108
  return _regenerator().w(function (_context) {
109
109
  while (1) switch (_context.n) {
110
110
  case 0:
111
111
  _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), attachmentId = _Object$entries$_i[0], attachment = _Object$entries$_i[1];
112
112
  deviceData = (_modelPreloader$compo = modelPreloader.componentDictionary) === null || _modelPreloader$compo === void 0 ? void 0 : _modelPreloader$compo[attachment.deviceId];
113
+ console.log("[ModelManager] attachment \"".concat(attachmentId, "\" \u2192 deviceId \"").concat(attachment.deviceId, "\" \u2192 animationConfig:"), (_deviceData$animation = deviceData === null || deviceData === void 0 ? void 0 : deviceData.animationConfig) !== null && _deviceData$animation !== void 0 ? _deviceData$animation : 'NONE');
113
114
  if (deviceData !== null && deviceData !== void 0 && deviceData.animationConfig) {
114
115
  _context.n = 1;
115
116
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2112-lab/central-plant",
3
- "version": "0.3.25",
3
+ "version": "0.3.26",
4
4
  "description": "Utility modules for the Central Plant Application",
5
5
  "main": "dist/bundle/index.js",
6
6
  "module": "dist/esm/src/index.js",