@2112-lab/central-plant 0.3.27 → 0.3.28

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.
@@ -761,13 +761,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
761
761
  phaseStart = performance.now();
762
762
  this._finalizeScene(data, crosscubeTextureSet, isImported);
763
763
  timers.phase5_finalize = performance.now() - phaseStart;
764
-
765
- // Phase 6: Load behaviors (after GLB models are present so output objects can be resolved)
766
- phaseStart = performance.now();
767
- this._processBehaviors(data);
768
- timers.phase6_behaviors = performance.now() - phaseStart;
769
764
  totalTime = performance.now() - totalStart;
770
- console.log("\u23F1\uFE0F Scene Loading Performance:\n Phase 1 (Prepare) : ".concat(timers.phase1_prepare.toFixed(0), "ms\n Phase 2 (Create Objects): ").concat(timers.phase2_createObjects.toFixed(0), "ms\n Phase 3 (GLB Models) : ").concat(timers.phase3_glbModels.toFixed(0), "ms\n Phase 4 (Pathfinding) : ").concat(timers.phase4_pathfinding.toFixed(0), "ms\n Phase 5 (Finalize) : ").concat(timers.phase5_finalize.toFixed(0), "ms\n Phase 6 (Behaviors) : ").concat(timers.phase6_behaviors.toFixed(0), "ms\n \u2500\u2500\u2500\u2500\u2500\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 Total : ").concat(totalTime.toFixed(0), "ms"));
765
+ console.log("\u23F1\uFE0F Scene Loading Performance:\n Phase 1 (Prepare) : ".concat(timers.phase1_prepare.toFixed(0), "ms\n Phase 2 (Create Objects): ").concat(timers.phase2_createObjects.toFixed(0), "ms\n Phase 3 (GLB Models) : ").concat(timers.phase3_glbModels.toFixed(0), "ms\n Phase 4 (Pathfinding) : ").concat(timers.phase4_pathfinding.toFixed(0), "ms\n Phase 5 (Finalize) : ").concat(timers.phase5_finalize.toFixed(0), "ms\n \u2500\u2500\u2500\u2500\u2500\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 Total : ").concat(totalTime.toFixed(0), "ms"));
771
766
  console.log('✅ Scene loaded successfully');
772
767
 
773
768
  // Notify UI components (e.g. SceneHierarchy) that the scene is fully loaded
@@ -1125,278 +1120,6 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1125
1120
  }
1126
1121
  }
1127
1122
 
1128
- /**
1129
- * Process behaviors from the scene data, expand any defaultBehaviors defined
1130
- * on component dictionary entries, resolve behaviorRef entries against device
1131
- * assets, inject per-instance component UUIDs, and hand the flat resolved
1132
- * array to BehaviorManager.
1133
- *
1134
- * Resolution cascade:
1135
- * 1. Explicit behaviors in data.behaviors — passed through as-is (behaviorRef
1136
- * entries are resolved against the component/device dictionaries).
1137
- * 2. defaultBehaviors[] on each placed smart component's dictionary entry —
1138
- * expanded per instance with the instance UUID injected. Compact
1139
- * behaviorRef-derived entries are tagged _isDefaultBehavior:true (the
1140
- * exporter can re-derive them); full L2 behavior objects are tagged false
1141
- * so they are exported verbatim and survive round-trips.
1142
- *
1143
- * @param {Object} data - Scene JSON data
1144
- */
1145
- }, {
1146
- key: "_processBehaviors",
1147
- value: function _processBehaviors(data) {
1148
- var _this$sceneViewer2,
1149
- _this$sceneViewer$cen2,
1150
- _this5 = this,
1151
- _data$scene3;
1152
- var behaviorManager = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.managers) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.behaviorManager;
1153
- if (!behaviorManager) {
1154
- console.warn('⚠️ _processBehaviors: BehaviorManager not available');
1155
- return;
1156
- }
1157
-
1158
- // Obtain the component dictionary (extended = includes S3/smart components)
1159
- var componentDictionary = ((_this$sceneViewer$cen2 = this.sceneViewer.centralPlant) === null || _this$sceneViewer$cen2 === void 0 || (_this$sceneViewer$cen2 = _this$sceneViewer$cen2.managers) === null || _this$sceneViewer$cen2 === void 0 || (_this$sceneViewer$cen2 = _this$sceneViewer$cen2.componentDataManager) === null || _this$sceneViewer$cen2 === void 0 ? void 0 : _this$sceneViewer$cen2.componentDictionary) || {};
1160
-
1161
- // ── Step A: Resolve any behaviorRef entries from data.behaviors ─────────
1162
- var explicitBehaviors = [];
1163
- if (Array.isArray(data === null || data === void 0 ? void 0 : data.behaviors)) {
1164
- data.behaviors.forEach(function (entry) {
1165
- if (entry.behaviorRef) {
1166
- var resolved = _this5._resolveBehaviorRef(entry, componentDictionary);
1167
- if (resolved) explicitBehaviors.push(resolved);
1168
- } else {
1169
- explicitBehaviors.push(entry);
1170
- }
1171
- });
1172
- }
1173
-
1174
- // Build a set of explicit behavior ids for deduplication
1175
- var explicitIds = new Set(explicitBehaviors.map(function (b) {
1176
- return b.id;
1177
- }));
1178
-
1179
- // Build a set of (component::attachment::state) tuples covered by explicit
1180
- // behaviors. If an expanded default behavior would produce the SAME input
1181
- // tuple, the explicit behavior is treated as the intentional override and
1182
- // the default expansion is skipped. This prevents a component's built-in
1183
- // switch→LED wiring from doubling-up when the user has deliberately authored
1184
- // cross-component behaviors that re-wire the same switch.
1185
- var explicitInputTuples = new Set(explicitBehaviors.filter(function (b) {
1186
- var _b$input, _b$input2, _b$input3;
1187
- return ((_b$input = b.input) === null || _b$input === void 0 ? void 0 : _b$input.component) && ((_b$input2 = b.input) === null || _b$input2 === void 0 ? void 0 : _b$input2.attachment) && ((_b$input3 = b.input) === null || _b$input3 === void 0 ? void 0 : _b$input3.state);
1188
- }).map(function (b) {
1189
- return "".concat(b.input.component, "::").concat(b.input.attachment, "::").concat(b.input.state);
1190
- }));
1191
-
1192
- // Build a set of instanceUuids already covered by behaviorRef entries in
1193
- // data.behaviors (written by the exporter for smart component defaults).
1194
- // Step B skips these instances to avoid loading the same behaviors twice —
1195
- // once via Step A (resolved from data.behaviors refs) and once via Step B
1196
- // (auto-expanded from the component dictionary).
1197
- var coveredInstances = new Set();
1198
- if (Array.isArray(data === null || data === void 0 ? void 0 : data.behaviors)) {
1199
- data.behaviors.forEach(function (entry) {
1200
- if (entry.behaviorRef && entry.component) {
1201
- coveredInstances.add(entry.component);
1202
- }
1203
- });
1204
- }
1205
-
1206
- // ── Step B: Walk placed components and expand their defaultBehaviors ─────
1207
- var instanceBehaviors = [];
1208
- if (Array.isArray(data === null || data === void 0 || (_data$scene3 = data.scene) === null || _data$scene3 === void 0 ? void 0 : _data$scene3.children)) {
1209
- data.scene.children.forEach(function (child) {
1210
- var _child$userData0, _compData$defaultBeha;
1211
- var libraryId = (_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.libraryId;
1212
- if (!libraryId) return;
1213
- var instanceUuid = child.uuid;
1214
- // Skip instances whose defaults were already resolved by Step A
1215
- // (they have explicit behaviorRef entries in data.behaviors).
1216
- if (coveredInstances.has(instanceUuid)) return;
1217
- var compData = componentDictionary[libraryId];
1218
- if (!(compData !== null && compData !== void 0 && (_compData$defaultBeha = compData.defaultBehaviors) !== null && _compData$defaultBeha !== void 0 && _compData$defaultBeha.length)) return;
1219
- compData.defaultBehaviors.forEach(function (template) {
1220
- var _expanded$input, _expanded$input2, _expanded$input3;
1221
- var expanded = _this5._expandDefaultBehavior(template, instanceUuid, componentDictionary);
1222
- if (!expanded) return;
1223
- // Skip if an explicit scene behavior already covers this id
1224
- if (explicitIds.has(expanded.id)) return;
1225
- // Skip if an explicit scene behavior already covers the same
1226
- // (component, attachment, state) input tuple. This prevents a
1227
- // component's built-in default wiring (e.g. switch → own LED) from
1228
- // double-firing when the user has authored a cross-component override
1229
- // that rewires the same switch to a different target.
1230
- if ((_expanded$input = expanded.input) !== null && _expanded$input !== void 0 && _expanded$input.component && (_expanded$input2 = expanded.input) !== null && _expanded$input2 !== void 0 && _expanded$input2.attachment && (_expanded$input3 = expanded.input) !== null && _expanded$input3 !== void 0 && _expanded$input3.state) {
1231
- var tuple = "".concat(expanded.input.component, "::").concat(expanded.input.attachment, "::").concat(expanded.input.state);
1232
- if (explicitInputTuples.has(tuple)) return;
1233
- }
1234
- // All component defaultBehaviors are re-derivable from the component
1235
- // asset at export time (via compact behaviorRef), so mark them all.
1236
- expanded._isDefaultBehavior = true;
1237
- instanceBehaviors.push(expanded);
1238
- });
1239
- });
1240
- }
1241
- var allBehaviors = [].concat(explicitBehaviors, instanceBehaviors);
1242
- if (allBehaviors.length === 0) return;
1243
- behaviorManager.loadBehaviors(allBehaviors);
1244
- console.log("\u2705 _processBehaviors: loaded ".concat(explicitBehaviors.length, " explicit + ").concat(instanceBehaviors.length, " default-expanded behavior(s)"));
1245
- }
1246
-
1247
- /**
1248
- * Register the defaultBehaviors of a single newly placed component instance
1249
- * into the BehaviorManager. Called from addComponent() (drag-drop), where
1250
- * _processBehaviors() (scene-load path) is not invoked.
1251
- *
1252
- * @param {Object} componentData - Entry from the component dictionary
1253
- * @param {string} instanceUuid - UUID of the placed component (componentModel.uuid)
1254
- */
1255
- }, {
1256
- key: "registerBehaviorsForComponentInstance",
1257
- value: function registerBehaviorsForComponentInstance(componentData, instanceUuid) {
1258
- var _this$sceneViewer3,
1259
- _componentData$defaul,
1260
- _this$sceneViewer$cen3,
1261
- _this6 = this;
1262
- var behaviorManager = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.managers) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.behaviorManager;
1263
- if (!behaviorManager) return;
1264
- if (!(componentData !== null && componentData !== void 0 && (_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length)) return;
1265
- var componentDictionary = ((_this$sceneViewer$cen3 = this.sceneViewer.centralPlant) === null || _this$sceneViewer$cen3 === void 0 || (_this$sceneViewer$cen3 = _this$sceneViewer$cen3.managers) === null || _this$sceneViewer$cen3 === void 0 || (_this$sceneViewer$cen3 = _this$sceneViewer$cen3.componentDataManager) === null || _this$sceneViewer$cen3 === void 0 ? void 0 : _this$sceneViewer$cen3.componentDictionary) || {};
1266
- var registered = 0;
1267
- componentData.defaultBehaviors.forEach(function (template) {
1268
- var expanded = _this6._expandDefaultBehavior(template, instanceUuid, componentDictionary);
1269
- if (!expanded) return;
1270
- expanded._isDefaultBehavior = true;
1271
- behaviorManager.addBehavior(expanded);
1272
- registered++;
1273
- });
1274
- if (registered > 0) {
1275
- console.log("\u2705 registerBehaviorsForComponentInstance: registered ".concat(registered, " behavior(s) for instance ").concat(instanceUuid));
1276
- }
1277
- }
1278
-
1279
- /**
1280
- * Resolve a scene-level or component-level behaviorRef entry into a full
1281
- * behavior definition by looking up the referenced template in the device
1282
- * asset's defaultBehaviors[] and substituting 'self' with the real
1283
- * attachmentId.
1284
- *
1285
- * Ref shape: { behaviorRef, deviceId, attachment, component? }
1286
- *
1287
- * @param {Object} ref
1288
- * @param {Object} componentDictionary
1289
- * @returns {Object|null} Resolved behavior or null if not found
1290
- */
1291
- }, {
1292
- key: "_resolveBehaviorRef",
1293
- value: function _resolveBehaviorRef(ref, componentDictionary) {
1294
- var _resolved$input, _resolved$output;
1295
- if (!ref.behaviorRef) {
1296
- console.warn('⚠️ _resolveBehaviorRef: missing behaviorRef', ref);
1297
- return null;
1298
- }
1299
-
1300
- // ── Component-level L2 ref: { behaviorRef, libraryId, component } ──────
1301
- // The full behavior template lives on the smart component's defaultBehaviors[].
1302
- // No 'self' substitution needed — attachment IDs are already real.
1303
- if (ref.libraryId) {
1304
- var compData = componentDictionary[ref.libraryId];
1305
- if (!compData) {
1306
- console.warn("\u26A0\uFE0F _resolveBehaviorRef: component \"".concat(ref.libraryId, "\" not in dictionary"));
1307
- return null;
1308
- }
1309
- var _template = (compData.defaultBehaviors || []).find(function (b) {
1310
- return b.id === ref.behaviorRef;
1311
- });
1312
- if (!_template) {
1313
- console.warn("\u26A0\uFE0F _resolveBehaviorRef: behavior \"".concat(ref.behaviorRef, "\" not found on component \"").concat(ref.libraryId, "\""));
1314
- return null;
1315
- }
1316
- var _resolved = JSON.parse(JSON.stringify(_template));
1317
- _resolved.id = "".concat(_resolved.id, "::").concat(ref.component);
1318
- if (ref.component) {
1319
- _resolved.input = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, _resolved.input), {}, {
1320
- component: ref.component
1321
- });
1322
- _resolved.output = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, _resolved.output), {}, {
1323
- component: ref.component
1324
- });
1325
- }
1326
- return _resolved;
1327
- }
1328
-
1329
- // ── Device-level L1 ref: { behaviorRef, deviceId, attachment, component } ─
1330
- if (!ref.deviceId || !ref.attachment) {
1331
- console.warn('⚠️ _resolveBehaviorRef: incomplete ref', ref);
1332
- return null;
1333
- }
1334
- var deviceData = componentDictionary[ref.deviceId];
1335
- if (!deviceData) {
1336
- console.warn("\u26A0\uFE0F _resolveBehaviorRef: device \"".concat(ref.deviceId, "\" not in dictionary"));
1337
- return null;
1338
- }
1339
- var template = (deviceData.defaultBehaviors || []).find(function (b) {
1340
- return b.id === ref.behaviorRef;
1341
- });
1342
- if (!template) {
1343
- console.warn("\u26A0\uFE0F _resolveBehaviorRef: behavior \"".concat(ref.behaviorRef, "\" not found on device \"").concat(ref.deviceId, "\""));
1344
- return null;
1345
- }
1346
- // Deep clone and substitute 'self' -> real attachmentId
1347
- var resolved = JSON.parse(JSON.stringify(template));
1348
- resolved.id = "".concat(resolved.id, "::").concat(ref.attachment);
1349
- if (((_resolved$input = resolved.input) === null || _resolved$input === void 0 ? void 0 : _resolved$input.attachment) === 'self') resolved.input.attachment = ref.attachment;
1350
- if (((_resolved$output = resolved.output) === null || _resolved$output === void 0 ? void 0 : _resolved$output.attachment) === 'self') resolved.output.attachment = ref.attachment;
1351
- // Inject component UUID guard if the ref carries one
1352
- if (ref.component) {
1353
- resolved.input = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, resolved.input), {}, {
1354
- component: ref.component
1355
- });
1356
- resolved.output = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, resolved.output), {}, {
1357
- component: ref.component
1358
- });
1359
- }
1360
- return resolved;
1361
- }
1362
-
1363
- /**
1364
- * Expand a single defaultBehaviors[] template entry for a specific component
1365
- * instance placed in the scene.
1366
- *
1367
- * If the entry is a behaviorRef, it is first resolved against the device
1368
- * library; otherwise it is treated as a full behavior definition.
1369
- * In both cases the instanceUuid is injected as input.component and
1370
- * output.component, and the behavior id is suffixed with ::instanceUuid.
1371
- *
1372
- * @param {Object} template - Entry from compData.defaultBehaviors[]
1373
- * @param {string} instanceUuid - UUID of the placed component instance
1374
- * @param {Object} componentDictionary
1375
- * @returns {Object|null}
1376
- */
1377
- }, {
1378
- key: "_expandDefaultBehavior",
1379
- value: function _expandDefaultBehavior(template, instanceUuid, componentDictionary) {
1380
- var base;
1381
- if (template.behaviorRef) {
1382
- // Resolve the device ref first (substitutes 'self' -> attachment)
1383
- base = this._resolveBehaviorRef(template, componentDictionary);
1384
- if (!base) return null;
1385
- } else {
1386
- base = JSON.parse(JSON.stringify(template));
1387
- }
1388
- // Suffix the id so each instance gets a unique behavior id
1389
- base.id = "".concat(base.id, "::").concat(instanceUuid);
1390
- // Inject the instance UUID as the component scope guard
1391
- base.input = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, base.input), {}, {
1392
- component: instanceUuid
1393
- });
1394
- base.output = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, base.output), {}, {
1395
- component: instanceUuid
1396
- });
1397
- return base;
1398
- }
1399
-
1400
1123
  /**
1401
1124
  * Save original world matrices for direction calculations
1402
1125
  */
@@ -1465,7 +1188,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1465
1188
  key: "loadSceneFromData",
1466
1189
  value: (function () {
1467
1190
  var _loadSceneFromData = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee9(data) {
1468
- var _data$scene4, _data$scene5, _data$scene6, _data$scene7;
1191
+ var _data$scene3, _data$scene4, _data$scene5, _data$scene6;
1469
1192
  return _rollupPluginBabelHelpers.regenerator().w(function (_context9) {
1470
1193
  while (1) switch (_context9.n) {
1471
1194
  case 0:
@@ -1475,10 +1198,10 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1475
1198
  dataType: _rollupPluginBabelHelpers["typeof"](data),
1476
1199
  hasScene: !!(data !== null && data !== void 0 && data.scene),
1477
1200
  sceneType: _rollupPluginBabelHelpers["typeof"](data === null || data === void 0 ? void 0 : data.scene),
1478
- hasChildren: !!(data !== null && data !== void 0 && (_data$scene4 = data.scene) !== null && _data$scene4 !== void 0 && _data$scene4.children),
1479
- childrenType: data !== null && data !== void 0 && (_data$scene5 = data.scene) !== null && _data$scene5 !== void 0 && _data$scene5.children ? _rollupPluginBabelHelpers["typeof"](data.scene.children) : 'undefined',
1480
- isArray: Array.isArray(data === null || data === void 0 || (_data$scene6 = data.scene) === null || _data$scene6 === void 0 ? void 0 : _data$scene6.children),
1481
- childrenLength: data === null || data === void 0 || (_data$scene7 = data.scene) === null || _data$scene7 === void 0 || (_data$scene7 = _data$scene7.children) === null || _data$scene7 === void 0 ? void 0 : _data$scene7.length,
1201
+ hasChildren: !!(data !== null && data !== void 0 && (_data$scene3 = data.scene) !== null && _data$scene3 !== void 0 && _data$scene3.children),
1202
+ childrenType: data !== null && data !== void 0 && (_data$scene4 = data.scene) !== null && _data$scene4 !== void 0 && _data$scene4.children ? _rollupPluginBabelHelpers["typeof"](data.scene.children) : 'undefined',
1203
+ isArray: Array.isArray(data === null || data === void 0 || (_data$scene5 = data.scene) === null || _data$scene5 === void 0 ? void 0 : _data$scene5.children),
1204
+ childrenLength: data === null || data === void 0 || (_data$scene6 = data.scene) === null || _data$scene6 === void 0 || (_data$scene6 = _data$scene6.children) === null || _data$scene6 === void 0 ? void 0 : _data$scene6.length,
1482
1205
  dataKeys: data ? Object.keys(data) : [],
1483
1206
  sceneKeys: data !== null && data !== void 0 && data.scene ? Object.keys(data.scene) : []
1484
1207
  });
@@ -1609,8 +1332,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1609
1332
  // Process children (connectors, etc.) if they exist
1610
1333
  if (componentModel.children && componentModel.children.length > 0) {
1611
1334
  componentModel.children.forEach(function (child) {
1612
- var _child$userData1, _child$userData10;
1613
- var childType = ((_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.objectType) || ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType);
1335
+ var _child$userData0, _child$userData1;
1336
+ var childType = ((_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.objectType) || ((_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.objectType);
1614
1337
  if (childType === 'connector') {
1615
1338
  var _child$geometry;
1616
1339
  var childBoundingBox = new THREE__namespace.Box3().setFromObject(child);
@@ -1695,8 +1418,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1695
1418
  if (segment.children && segment.children.length > 0) {
1696
1419
  var childrenToRemove = _rollupPluginBabelHelpers.toConsumableArray(segment.children);
1697
1420
  childrenToRemove.forEach(function (child) {
1698
- var _child$userData11;
1699
- if ((_child$userData11 = child.userData) !== null && _child$userData11 !== void 0 && _child$userData11.isPipeElbow) {
1421
+ var _child$userData10;
1422
+ if ((_child$userData10 = child.userData) !== null && _child$userData10 !== void 0 && _child$userData10.isPipeElbow) {
1700
1423
  console.log("\uD83D\uDDD1\uFE0F Removing elbow child from segment before manualization: ".concat(child.uuid));
1701
1424
  segment.remove(child);
1702
1425
  if (child.geometry) child.geometry.dispose();
@@ -1847,7 +1570,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1847
1570
  value: function _convertConnectedGatewaysToManual(connectors, currentSceneData) {
1848
1571
  var _connectors$,
1849
1572
  _segment$userData2,
1850
- _this7 = this;
1573
+ _this5 = this;
1851
1574
  console.log('🔍 Checking for connected gateways to convert to manual...');
1852
1575
  var sceneViewer = this.sceneViewer;
1853
1576
  var convertedGateways = [];
@@ -1884,7 +1607,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1884
1607
  console.log("\uD83D\uDD27 Found computed gateway at endpoint: ".concat(endpointObject.uuid, " - converting to manual"));
1885
1608
 
1886
1609
  // Convert gateway to manual (declared) using manualizeGateway for consistency
1887
- _this7.manualizeGateway(endpointObject, currentSceneData);
1610
+ _this5.manualizeGateway(endpointObject, currentSceneData);
1888
1611
  convertedGateways.push(endpointObject);
1889
1612
  } else if (((_endpointObject$userD5 = endpointObject.userData) === null || _endpointObject$userD5 === void 0 ? void 0 : _endpointObject$userD5.objectType) === 'gateway' && ((_endpointObject$userD6 = endpointObject.userData) === null || _endpointObject$userD6 === void 0 ? void 0 : _endpointObject$userD6.isDeclared) === true) {
1890
1613
  console.log("\u2139\uFE0F Gateway ".concat(endpointObject.uuid, " is already declared (manual), skipping conversion"));
@@ -31,7 +31,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
31
31
  * Initialize the CentralPlant manager
32
32
  *
33
33
  * @constructor
34
- * @version 0.3.27
34
+ * @version 0.3.28
35
35
  * @updated 2025-10-22
36
36
  *
37
37
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -1065,107 +1065,6 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1065
1065
  };
1066
1066
  }
1067
1067
 
1068
- // ─────────────────────────────────────────────────────────────────────────
1069
- // BEHAVIORS API
1070
- // ─────────────────────────────────────────────────────────────────────────
1071
-
1072
- /**
1073
- * Get all behavior definitions currently stored in the BehaviorManager.
1074
- * @returns {Array<Object>} Array of behavior definition objects, or empty array.
1075
- * @example
1076
- * const behaviors = centralPlant.getBehaviors()
1077
- * behaviors.forEach(b => console.log(b.id, b.input, b.output))
1078
- */
1079
- }, {
1080
- key: "getBehaviors",
1081
- value: function getBehaviors() {
1082
- var _this$sceneViewer4;
1083
- var bm = (_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 || (_this$sceneViewer4 = _this$sceneViewer4.managers) === null || _this$sceneViewer4 === void 0 ? void 0 : _this$sceneViewer4.behaviorManager;
1084
- if (!bm) {
1085
- console.warn('⚠️ getBehaviors(): BehaviorManager not available');
1086
- return [];
1087
- }
1088
- return bm.getBehaviors();
1089
- }
1090
-
1091
- /**
1092
- * Add a behavior definition at runtime.
1093
- * @param {Object} behaviorDef - Full behavior definition object (must have unique `id`)
1094
- * @returns {boolean} True if added successfully, false otherwise
1095
- * @example
1096
- * centralPlant.addBehavior({
1097
- * id: 'my-behavior',
1098
- * input: { attachment: 'device-01', dataPoint: 'boolean-status-01' },
1099
- * output: { attachment: 'light-01', child: 'indicator-mesh-01' },
1100
- * conditions: [{ when: 'dataPoint.value === true', actions: [{ set: 'material.emissiveIntensity', value: 1.0 }] }]
1101
- * })
1102
- */
1103
- }, {
1104
- key: "addBehavior",
1105
- value: function addBehavior(behaviorDef) {
1106
- var _this$sceneViewer5, _this$sceneViewer6;
1107
- var bm = (_this$sceneViewer5 = this.sceneViewer) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.managers) === null || _this$sceneViewer5 === void 0 ? void 0 : _this$sceneViewer5.behaviorManager;
1108
- if (!bm) {
1109
- console.warn('⚠️ addBehavior(): BehaviorManager not available');
1110
- return false;
1111
- }
1112
- // Also persist into currentSceneData so export includes it
1113
- if ((_this$sceneViewer6 = this.sceneViewer) !== null && _this$sceneViewer6 !== void 0 && _this$sceneViewer6.currentSceneData) {
1114
- if (!Array.isArray(this.sceneViewer.currentSceneData.behaviors)) {
1115
- this.sceneViewer.currentSceneData.behaviors = [];
1116
- }
1117
- this.sceneViewer.currentSceneData.behaviors.push(behaviorDef);
1118
- }
1119
- return bm.addBehavior(behaviorDef);
1120
- }
1121
-
1122
- /**
1123
- * Remove a behavior definition by id.
1124
- * @param {string} behaviorId
1125
- * @returns {boolean} True if removed, false if not found
1126
- * @example
1127
- * centralPlant.removeBehavior('my-behavior')
1128
- */
1129
- }, {
1130
- key: "removeBehavior",
1131
- value: function removeBehavior(behaviorId) {
1132
- var _this$sceneViewer7, _this$sceneViewer8;
1133
- var bm = (_this$sceneViewer7 = this.sceneViewer) === null || _this$sceneViewer7 === void 0 || (_this$sceneViewer7 = _this$sceneViewer7.managers) === null || _this$sceneViewer7 === void 0 ? void 0 : _this$sceneViewer7.behaviorManager;
1134
- if (!bm) {
1135
- console.warn('⚠️ removeBehavior(): BehaviorManager not available');
1136
- return false;
1137
- }
1138
- // Also remove from currentSceneData
1139
- if ((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && (_this$sceneViewer8 = _this$sceneViewer8.currentSceneData) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.behaviors) {
1140
- var idx = this.sceneViewer.currentSceneData.behaviors.findIndex(function (b) {
1141
- return b.id === behaviorId;
1142
- });
1143
- if (idx !== -1) this.sceneViewer.currentSceneData.behaviors.splice(idx, 1);
1144
- }
1145
- return bm.removeBehavior(behaviorId);
1146
- }
1147
-
1148
- /**
1149
- * Simulate an IO device state value arriving and trigger any matching behaviors.
1150
- * Useful for live testing in the UI or for integration with real data feeds.
1151
- * @param {string} attachmentId - The attachment id of the input io-device
1152
- * @param {string} stateId - The state id on that device
1153
- * @param {*} value - The new state value
1154
- * @example
1155
- * centralPlant.triggerState('pump-push-button-01', 'power', true)
1156
- */
1157
- }, {
1158
- key: "triggerState",
1159
- value: function triggerState(attachmentId, stateId, value, parentUuid) {
1160
- var _this$sceneViewer9;
1161
- var bm = (_this$sceneViewer9 = this.sceneViewer) === null || _this$sceneViewer9 === void 0 || (_this$sceneViewer9 = _this$sceneViewer9.managers) === null || _this$sceneViewer9 === void 0 ? void 0 : _this$sceneViewer9.behaviorManager;
1162
- if (!bm) {
1163
- console.warn('⚠️ triggerState(): BehaviorManager not available');
1164
- return;
1165
- }
1166
- bm.triggerState(attachmentId, stateId, value, parentUuid);
1167
- }
1168
-
1169
1068
  /**
1170
1069
  * Set the state of an I/O device instance in the Three.js scene.
1171
1070
  *
@@ -1198,15 +1097,9 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1198
1097
  }, {
1199
1098
  key: "setIoDeviceState",
1200
1099
  value: function setIoDeviceState(attachmentId, stateId, value, parentUuid) {
1201
- var _this$sceneViewer0, _this$sceneViewer1, _this$sceneViewer10;
1202
- var bm = (_this$sceneViewer0 = this.sceneViewer) === null || _this$sceneViewer0 === void 0 || (_this$sceneViewer0 = _this$sceneViewer0.managers) === null || _this$sceneViewer0 === void 0 ? void 0 : _this$sceneViewer0.behaviorManager;
1203
- if (!bm) {
1204
- console.warn('⚠️ setIoDeviceState(): BehaviorManager not available');
1205
- return false;
1206
- }
1207
-
1100
+ var _this$sceneViewer4, _this$sceneViewer5, _this$sceneViewer6;
1208
1101
  // 1. Persist via state adapter if one has been configured
1209
- var stateAdapter = (_this$sceneViewer1 = this.sceneViewer) === null || _this$sceneViewer1 === void 0 || (_this$sceneViewer1 = _this$sceneViewer1.managers) === null || _this$sceneViewer1 === void 0 || (_this$sceneViewer1 = _this$sceneViewer1.componentTooltipManager) === null || _this$sceneViewer1 === void 0 ? void 0 : _this$sceneViewer1._stateAdapter;
1102
+ var stateAdapter = (_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 || (_this$sceneViewer4 = _this$sceneViewer4.managers) === null || _this$sceneViewer4 === void 0 || (_this$sceneViewer4 = _this$sceneViewer4.componentTooltipManager) === null || _this$sceneViewer4 === void 0 ? void 0 : _this$sceneViewer4._stateAdapter;
1210
1103
  if (stateAdapter !== null && stateAdapter !== void 0 && stateAdapter.setState) {
1211
1104
  var scopedKey = parentUuid ? "".concat(parentUuid, "::").concat(attachmentId) : attachmentId;
1212
1105
  try {
@@ -1216,11 +1109,11 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1216
1109
  }
1217
1110
  }
1218
1111
 
1219
- // 2. Apply Three.js behavior changes
1220
- bm.triggerState(attachmentId, stateId, value, parentUuid);
1112
+ // 2. Apply io-animation changes
1113
+ (_this$sceneViewer5 = this.sceneViewer) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.managers) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.ioAnimationManager) === null || _this$sceneViewer5 === void 0 || _this$sceneViewer5.triggerState(attachmentId, stateId, value, parentUuid);
1221
1114
 
1222
1115
  // 3. Emit event for host apps that don't use the state adapter (e.g. cp3d-viewer)
1223
- (_this$sceneViewer10 = this.sceneViewer) === null || _this$sceneViewer10 === void 0 || _this$sceneViewer10.emit('io-device-state-changed', {
1116
+ (_this$sceneViewer6 = this.sceneViewer) === null || _this$sceneViewer6 === void 0 || _this$sceneViewer6.emit('io-device-state-changed', {
1224
1117
  attachmentId: attachmentId,
1225
1118
  stateId: stateId,
1226
1119
  value: value,
@@ -1242,8 +1135,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
1242
1135
  }, {
1243
1136
  key: "getSceneAttachments",
1244
1137
  value: function getSceneAttachments() {
1245
- var _this$sceneViewer11;
1246
- var scene = (_this$sceneViewer11 = this.sceneViewer) === null || _this$sceneViewer11 === void 0 ? void 0 : _this$sceneViewer11.scene;
1138
+ var _this$sceneViewer7;
1139
+ var scene = (_this$sceneViewer7 = this.sceneViewer) === null || _this$sceneViewer7 === void 0 ? void 0 : _this$sceneViewer7.scene;
1247
1140
  if (!scene) return [];
1248
1141
  var results = [];
1249
1142
  scene.traverse(function (obj) {
@@ -15,7 +15,6 @@ import { EnvironmentManager } from '../managers/environment/environmentManager.j
15
15
  import { KeyboardControlsManager } from '../managers/controls/keyboardControlsManager.js';
16
16
  import { PathfindingManager } from '../managers/pathfinding/pathfindingManager.js';
17
17
  import { PathFlowManager } from '../managers/pathfinding/PathFlowManager.js';
18
- import { BehaviorManager } from '../managers/behaviors/BehaviorManager.js';
19
18
  import { SceneOperationsManager } from '../managers/scene/sceneOperationsManager.js';
20
19
  import { AnimationManager } from '../managers/scene/animationManager.js';
21
20
  import { CameraControlsManager } from '../managers/controls/cameraControlsManager.js';
@@ -145,7 +144,6 @@ var CentralPlantInternals = /*#__PURE__*/function () {
145
144
  this.centralPlant.managers.keyboardControlsManager = new KeyboardControlsManager(this.centralPlant.sceneViewer);
146
145
  this.centralPlant.managers.pathfindingManager = new PathfindingManager(this.centralPlant.sceneViewer);
147
146
  this.centralPlant.managers.pathFlowManager = new PathFlowManager(this.centralPlant.sceneViewer);
148
- this.centralPlant.managers.behaviorManager = new BehaviorManager(this.centralPlant.sceneViewer);
149
147
  this.centralPlant.managers.sceneOperationsManager = new SceneOperationsManager(this.centralPlant.sceneViewer);
150
148
  this.centralPlant.managers.animationManager = new AnimationManager(this.centralPlant.sceneViewer);
151
149
  this.centralPlant.managers.cameraControlsManager = new CameraControlsManager(this.centralPlant.sceneViewer);
@@ -923,7 +921,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
923
921
  return false;
924
922
  }
925
923
  try {
926
- var _componentData$childr, _componentData$childr2, _this$centralPlant$sc7, _componentData$childr3, _componentData$defaul;
924
+ var _componentData$childr, _componentData$childr2, _this$centralPlant$sc7, _componentData$childr3;
927
925
  // Generate a unique component ID if not provided
928
926
  var componentId = options.customId || this.generateUniqueComponentId(libraryId);
929
927
 
@@ -1155,15 +1153,6 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1155
1153
  }
1156
1154
  }
1157
1155
 
1158
- // Register default behaviors for smart components so the BehaviorManager
1159
- // responds to tooltip-driven state changes immediately after drop.
1160
- // (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
1161
- if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
1162
- var _this$centralPlant$sc9, _som$registerBehavior;
1163
- var som = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.sceneOperationsManager;
1164
- som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
1165
- }
1166
-
1167
1156
  // Notify the component manager about the new component
1168
1157
  if (componentManager.registerComponent) {
1169
1158
  componentManager.registerComponent(componentModel);
@@ -1236,18 +1225,18 @@ var CentralPlantInternals = /*#__PURE__*/function () {
1236
1225
  }, {
1237
1226
  key: "deleteComponent",
1238
1227
  value: function deleteComponent(componentId) {
1239
- var _this$centralPlant$sc0;
1228
+ var _this$centralPlant$sc9;
1240
1229
  // Check if component manager is available
1241
- var componentManager = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.componentManager;
1230
+ var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
1242
1231
  if (!componentManager) {
1243
1232
  console.error('❌ deleteComponent(): Component manager not available');
1244
1233
  return false;
1245
1234
  }
1246
1235
  try {
1247
- var _this$centralPlant$sc1, _this$centralPlant$sc10, _sceneData$scene2, _sceneData$scene3;
1236
+ var _this$centralPlant$sc0, _this$centralPlant$sc1, _sceneData$scene2, _sceneData$scene3;
1248
1237
  console.log("\uD83D\uDDD1\uFE0F deleteComponent(): Deleting component ".concat(componentId));
1249
- var threeScene = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.scene;
1250
- var sceneData = (_this$centralPlant$sc10 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc10 === void 0 ? void 0 : _this$centralPlant$sc10.currentSceneData;
1238
+ var threeScene = (_this$centralPlant$sc0 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc0 === void 0 ? void 0 : _this$centralPlant$sc0.scene;
1239
+ var sceneData = (_this$centralPlant$sc1 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc1 === void 0 ? void 0 : _this$centralPlant$sc1.currentSceneData;
1251
1240
 
1252
1241
  // Step 1: Resolve the actual Three.js UUID from componentId.
1253
1242
  // The UI emits object.name (e.g. "Pump (PUMP-1)") as the selection ID, but
@@ -98,7 +98,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
98
98
  this.centralPlant.attachToComponent();
99
99
 
100
100
  // Sync our managers tracking object after attachment
101
- managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'pathFlowManager', 'behaviorManager', 'ioAnimationManager', 'ioOutlineManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
101
+ managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'pathFlowManager', 'ioAnimationManager', 'ioOutlineManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
102
102
  managerKeys.forEach(function (key) {
103
103
  if (_this2[key]) {
104
104
  _this2.managers[key] = _this2[key];
@@ -9,7 +9,6 @@ export { SceneExportManager } from './managers/scene/sceneExportManager.js';
9
9
  export { SceneTooltipsManager } from './managers/scene/sceneTooltipsManager.js';
10
10
  export { ComponentTooltipManager } from './managers/scene/componentTooltipManager.js';
11
11
  export { SceneHierarchyManager } from './managers/scene/sceneHierarchyManager.js';
12
- export { BehaviorManager } from './managers/behaviors/BehaviorManager.js';
13
12
  export { IoAnimationManager } from './managers/behaviors/IoAnimationManager.js';
14
13
  export { ComponentManager } from './managers/components/componentManager.js';
15
14
  export { AnimationManager } from './managers/scene/animationManager.js';