@2112-lab/central-plant 0.3.41 → 0.3.43

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 +332 -123
  2. package/dist/cjs/src/core/centralPlant.js +41 -27
  3. package/dist/cjs/src/core/centralPlantInternals.js +3 -2
  4. package/dist/cjs/src/index.js +6 -0
  5. package/dist/cjs/src/managers/behaviors/IoBehaviorManager.js +1 -12
  6. package/dist/cjs/src/managers/controls/transformControls.js +2 -2
  7. package/dist/cjs/src/managers/controls/transformControlsManager.js +4 -7
  8. package/dist/cjs/src/managers/scene/modelManager.js +2 -2
  9. package/dist/cjs/src/utils/animationTransformUtils.js +10 -7
  10. package/dist/cjs/src/utils/behaviorDispatch.js +64 -0
  11. package/dist/cjs/src/utils/behaviorRegistration.js +12 -1
  12. package/dist/cjs/src/utils/behaviorSceneUtils.js +1 -1
  13. package/dist/cjs/src/utils/behaviorSchema.js +48 -0
  14. package/dist/cjs/src/utils/demoSceneUtils.js +91 -0
  15. package/dist/esm/src/core/centralPlant.js +41 -27
  16. package/dist/esm/src/core/centralPlantInternals.js +3 -2
  17. package/dist/esm/src/index.js +3 -2
  18. package/dist/esm/src/managers/behaviors/IoBehaviorManager.js +2 -13
  19. package/dist/esm/src/managers/controls/transformControls.js +2 -2
  20. package/dist/esm/src/managers/controls/transformControlsManager.js +4 -7
  21. package/dist/esm/src/managers/scene/modelManager.js +2 -2
  22. package/dist/esm/src/utils/animationTransformUtils.js +10 -7
  23. package/dist/esm/src/utils/behaviorDispatch.js +64 -1
  24. package/dist/esm/src/utils/behaviorRegistration.js +12 -1
  25. package/dist/esm/src/utils/behaviorSceneUtils.js +1 -1
  26. package/dist/esm/src/utils/behaviorSchema.js +49 -2
  27. package/dist/esm/src/utils/demoSceneUtils.js +85 -0
  28. package/dist/index.d.ts +16 -4
  29. package/package.json +1 -1
@@ -1164,6 +1164,122 @@ var DisposalUtilities = /*#__PURE__*/function () {
1164
1164
  }]);
1165
1165
  }();
1166
1166
 
1167
+ /**
1168
+ * Shared I/O device state dispatch helpers used by centralPlant and componentTooltipManager.
1169
+ */
1170
+
1171
+ /**
1172
+ * @param {string} attachmentId
1173
+ * @param {string|null|undefined} parentUuid
1174
+ * @returns {string}
1175
+ */
1176
+ function getScopedAttachmentKey(attachmentId, parentUuid) {
1177
+ if (!parentUuid) return attachmentId;
1178
+ return "".concat(parentUuid, "::").concat(attachmentId);
1179
+ }
1180
+
1181
+ /**
1182
+ * @param {Object} sceneViewer
1183
+ * @returns {import('../managers/behaviors/IoBehaviorManager.js').IoBehaviorManager|null}
1184
+ */
1185
+ function getIoBehaviorManager(sceneViewer) {
1186
+ var _sceneViewer$managers, _sceneViewer$centralP;
1187
+ if (!sceneViewer) return null;
1188
+ return ((_sceneViewer$managers = sceneViewer.managers) === null || _sceneViewer$managers === void 0 ? void 0 : _sceneViewer$managers.ioBehaviorManager) || sceneViewer.ioBehaviorManager || ((_sceneViewer$centralP = sceneViewer.centralPlant) === null || _sceneViewer$centralP === void 0 || (_sceneViewer$centralP = _sceneViewer$centralP.managers) === null || _sceneViewer$centralP === void 0 ? void 0 : _sceneViewer$centralP.ioBehaviorManager) || null;
1189
+ }
1190
+
1191
+ /**
1192
+ * Resolve tooltip/drag data points for an I/O device attachment.
1193
+ * Prefers behaviorConfig-driven animation data points; merges legacy ioConfig snapshot.
1194
+ *
1195
+ * @param {string} parentUuid
1196
+ * @param {string} attachmentId
1197
+ * @param {Object} userData - io-device userData (may include dataPoints snapshot)
1198
+ * @param {import('../managers/behaviors/IoBehaviorManager.js').IoBehaviorManager|null} ioBehaviorManager
1199
+ * @param {THREE.Object3D|null} [hitMesh]
1200
+ * @returns {Object[]}
1201
+ */
1202
+ function resolveDataPoints(parentUuid, attachmentId, userData, ioBehaviorManager) {
1203
+ var hitMesh = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
1204
+ var fromAnimations = (ioBehaviorManager === null || ioBehaviorManager === void 0 ? void 0 : ioBehaviorManager.getAnimationDataPoints(parentUuid, attachmentId, hitMesh)) || [];
1205
+ if (fromAnimations.length) return fromAnimations;
1206
+ var legacy = (userData === null || userData === void 0 ? void 0 : userData.dataPoints) || [];
1207
+ return legacy.map(function (dp) {
1208
+ var _dp$defaultValue;
1209
+ return {
1210
+ id: dp.id || dp.name,
1211
+ name: dp.name || dp.id,
1212
+ stateType: dp.stateType || 'binary',
1213
+ stateConfig: dp.stateConfig || {},
1214
+ defaultValue: (_dp$defaultValue = dp.defaultValue) !== null && _dp$defaultValue !== void 0 ? _dp$defaultValue : null,
1215
+ direction: dp.direction || (userData === null || userData === void 0 ? void 0 : userData.ioDirection) || 'output'
1216
+ };
1217
+ }).filter(function (dp) {
1218
+ return dp.id;
1219
+ });
1220
+ }
1221
+
1222
+ /**
1223
+ * Apply persisted default values for I/O device animation states in the live scene.
1224
+ * Updates the state adapter (e.g. Vuex) and drives mesh animations via IoBehaviorManager.
1225
+ *
1226
+ * @param {Object} centralPlant
1227
+ * @param {{ parentUuid?: string, attachmentId?: string }} [options]
1228
+ */
1229
+ function applyDefaultIoDeviceStates(centralPlant) {
1230
+ var _centralPlant$sceneVi;
1231
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1232
+ var parentUuid = options.parentUuid,
1233
+ attachmentId = options.attachmentId;
1234
+ var ioBehavMgr = getIoBehaviorManager(centralPlant === null || centralPlant === void 0 ? void 0 : centralPlant.sceneViewer);
1235
+ var scene = centralPlant === null || centralPlant === void 0 || (_centralPlant$sceneVi = centralPlant.sceneViewer) === null || _centralPlant$sceneVi === void 0 ? void 0 : _centralPlant$sceneVi.scene;
1236
+ if (!ioBehavMgr || !scene || typeof (centralPlant === null || centralPlant === void 0 ? void 0 : centralPlant.setIoDeviceState) !== 'function') return;
1237
+ var seen = new Set();
1238
+ scene.traverse(function (obj) {
1239
+ var _obj$userData, _obj$parent;
1240
+ if (((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType) !== 'io-device') return;
1241
+ var objParentUuid = obj.userData.parentComponentId || ((_obj$parent = obj.parent) === null || _obj$parent === void 0 ? void 0 : _obj$parent.uuid);
1242
+ var objAttachmentId = obj.userData.attachmentId;
1243
+ if (!objParentUuid || !objAttachmentId) return;
1244
+ if (parentUuid && objParentUuid !== parentUuid) return;
1245
+ if (attachmentId && objAttachmentId !== attachmentId) return;
1246
+ var scopedKey = getScopedAttachmentKey(objAttachmentId, objParentUuid);
1247
+ if (seen.has(scopedKey)) return;
1248
+ seen.add(scopedKey);
1249
+ var dps = ioBehavMgr.getAnimationDataPoints(objParentUuid, objAttachmentId) || [];
1250
+ if (dps.length) {
1251
+ var _iterator = _createForOfIteratorHelper(dps),
1252
+ _step;
1253
+ try {
1254
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1255
+ var dp = _step.value;
1256
+ if (!(dp !== null && dp !== void 0 && dp.id) || dp.defaultValue === undefined || dp.defaultValue === null) continue;
1257
+ centralPlant.setIoDeviceState(objAttachmentId, dp.id, dp.defaultValue, objParentUuid);
1258
+ }
1259
+ } catch (err) {
1260
+ _iterator.e(err);
1261
+ } finally {
1262
+ _iterator.f();
1263
+ }
1264
+ return;
1265
+ }
1266
+ var _iterator2 = _createForOfIteratorHelper(obj.userData.dataPoints || []),
1267
+ _step2;
1268
+ try {
1269
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
1270
+ var _dp = _step2.value;
1271
+ var dpId = _dp.id || _dp.name;
1272
+ if (!dpId || _dp.defaultValue === undefined || _dp.defaultValue === null) continue;
1273
+ centralPlant.setIoDeviceState(objAttachmentId, dpId, _dp.defaultValue, objParentUuid);
1274
+ }
1275
+ } catch (err) {
1276
+ _iterator2.e(err);
1277
+ } finally {
1278
+ _iterator2.f();
1279
+ }
1280
+ });
1281
+ }
1282
+
1167
1283
  /**
1168
1284
  * Register mesh animations and intra-component state links when a smart
1169
1285
  * component is placed or imported into the scene.
@@ -1173,8 +1289,9 @@ var DisposalUtilities = /*#__PURE__*/function () {
1173
1289
  * @param {Object} componentData - Smart component dictionary entry
1174
1290
  * @param {Object} componentModel - Root THREE.Object3D of the placed component
1175
1291
  * @param {Object} componentDictionary - modelPreloader.componentDictionary
1292
+ * @param {Object} [centralPlant] - When provided, default animation states are applied after registration
1176
1293
  */
1177
- function registerBehaviorsForComponent(ioBehavMgr, componentUuid, componentData, componentModel, componentDictionary) {
1294
+ function registerBehaviorsForComponent(ioBehavMgr, componentUuid, componentData, componentModel, componentDictionary, centralPlant) {
1178
1295
  var _componentData$behavi;
1179
1296
  if (!ioBehavMgr || !componentData || !componentModel) {
1180
1297
  return;
@@ -1204,6 +1321,11 @@ function registerBehaviorsForComponent(ioBehavMgr, componentUuid, componentData,
1204
1321
  } else if (componentData.isSmart) {
1205
1322
  ioBehavMgr.registerComponentBehaviors(componentUuid, []);
1206
1323
  }
1324
+ if (centralPlant) {
1325
+ applyDefaultIoDeviceStates(centralPlant, {
1326
+ parentUuid: componentUuid
1327
+ });
1328
+ }
1207
1329
  }
1208
1330
 
1209
1331
  /**
@@ -1229,6 +1351,10 @@ function reloadBehaviorsForDeviceAsset(ioBehavMgr, deviceAssetId, componentDicti
1229
1351
  if (!parentUuid || !attachmentId) return;
1230
1352
  ioBehavMgr.unloadForAttachment(parentUuid, attachmentId);
1231
1353
  ioBehavMgr.loadBehaviors(attachmentId, deviceData.behaviorConfig, obj, parentUuid);
1354
+ applyDefaultIoDeviceStates(centralPlant, {
1355
+ parentUuid: parentUuid,
1356
+ attachmentId: attachmentId
1357
+ });
1232
1358
  });
1233
1359
  }
1234
1360
 
@@ -2844,8 +2970,8 @@ var transformControls = /*#__PURE__*/function (_THREE$Object3D) {
2844
2970
  }, {
2845
2971
  key: "setMode",
2846
2972
  value: function setMode(mode) {
2847
- if (mode === 'scale') {
2848
- console.warn('transformControls: Scale mode has been removed. Using translate mode instead.');
2973
+ if (mode !== 'translate') {
2974
+ console.warn("transformControls: ".concat(mode, " mode is disabled. Locking to translate."));
2849
2975
  mode = 'translate';
2850
2976
  }
2851
2977
  this.mode = mode;
@@ -4209,10 +4335,6 @@ var TransformControlsManager = /*#__PURE__*/function () {
4209
4335
  // Translate mode
4210
4336
  _this3.setMode('translate');
4211
4337
  break;
4212
- case 'KeyR':
4213
- // Rotate mode
4214
- _this3.setMode('rotate');
4215
- break;
4216
4338
  }
4217
4339
  };
4218
4340
  window.addEventListener('keydown', this.eventHandlers.keydown);
@@ -5232,9 +5354,10 @@ var TransformControlsManager = /*#__PURE__*/function () {
5232
5354
  }, {
5233
5355
  key: "setMode",
5234
5356
  value: function setMode(mode) {
5235
- if (!['translate', 'rotate', 'scale'].includes(mode)) {
5236
- console.warn("\u26A0\uFE0F Invalid transform mode: ".concat(mode));
5237
- return;
5357
+ // Only allow translate mode - lock rotation and scale controls
5358
+ if (mode !== 'translate') {
5359
+ console.warn("\u26A0\uFE0F Transform mode ".concat(mode, " is disabled. Locking to translate."));
5360
+ mode = 'translate';
5238
5361
  }
5239
5362
  var previousMode = this.currentMode;
5240
5363
  this.currentMode = mode;
@@ -27775,7 +27898,7 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
27775
27898
  }]);
27776
27899
  }(BaseDisposable);
27777
27900
 
27778
- var _excluded$1 = ["direction"];
27901
+ var _excluded$2 = ["direction"];
27779
27902
  var ConnectorManager = /*#__PURE__*/function (_BaseDisposable) {
27780
27903
  function ConnectorManager(sceneViewer) {
27781
27904
  var _this;
@@ -27920,7 +28043,7 @@ var ConnectorManager = /*#__PURE__*/function (_BaseDisposable) {
27920
28043
  // Filter out 'direction' attribute - manual segment connectors don't need it
27921
28044
  var _ref = connector.userData || {};
27922
28045
  _ref.direction;
27923
- var cleanedUserData = _objectWithoutProperties(_ref, _excluded$1);
28046
+ var cleanedUserData = _objectWithoutProperties(_ref, _excluded$2);
27924
28047
  var sceneDataConnector = {
27925
28048
  uuid: connector.uuid,
27926
28049
  userData: _objectSpread2(_objectSpread2({}, cleanedUserData), {}, {
@@ -31438,7 +31561,7 @@ var ModelManager = /*#__PURE__*/function () {
31438
31561
  key: "loadLibraryModel",
31439
31562
  value: function () {
31440
31563
  var _loadLibraryModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(targetMesh, jsonEntry, componentData) {
31441
- var component, _jsonEntry$userData, _jsonEntry$userData2, _jsonEntry$userData3, originalProps, connectorChildren, gltfScene, libraryModel, _this$sceneViewer, ioBehavMgr, warmFn, _jsonEntry$userData4, _t;
31564
+ var component, _jsonEntry$userData, _jsonEntry$userData2, _jsonEntry$userData3, originalProps, connectorChildren, gltfScene, libraryModel, _this$sceneViewer, ioBehavMgr, _this$sceneViewer2, warmFn, _jsonEntry$userData4, _t;
31442
31565
  return _regenerator().w(function (_context) {
31443
31566
  while (1) switch (_context.n) {
31444
31567
  case 0:
@@ -31483,7 +31606,7 @@ var ModelManager = /*#__PURE__*/function () {
31483
31606
  case 4:
31484
31607
  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;
31485
31608
  if (ioBehavMgr) {
31486
- registerBehaviorsForComponent(ioBehavMgr, originalProps.uuid, componentData, libraryModel, modelPreloader.componentDictionary);
31609
+ registerBehaviorsForComponent(ioBehavMgr, originalProps.uuid, componentData, libraryModel, modelPreloader.componentDictionary, (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.centralPlant);
31487
31610
  }
31488
31611
  case 5:
31489
31612
  // Replace mesh in scene
@@ -32687,7 +32810,7 @@ var SceneClearingUtility = /*#__PURE__*/function () {
32687
32810
  }]);
32688
32811
  }();
32689
32812
 
32690
- var _excluded = ["direction"],
32813
+ var _excluded$1 = ["direction"],
32691
32814
  _excluded2 = ["direction"];
32692
32815
  var SceneOperationsManager = /*#__PURE__*/function () {
32693
32816
  function SceneOperationsManager(sceneViewer) {
@@ -33276,7 +33399,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
33276
33399
  // Initialize userData (filter out 'direction' - manual segment connectors don't need it)
33277
33400
  var _ref = connectorData.userData || {};
33278
33401
  _ref.direction;
33279
- var _cleanedUserData = _objectWithoutProperties(_ref, _excluded);
33402
+ var _cleanedUserData = _objectWithoutProperties(_ref, _excluded$1);
33280
33403
  _connectorMesh.userData = _objectSpread2(_objectSpread2({}, _cleanedUserData), {}, {
33281
33404
  originalUuid: connectorData.uuid,
33282
33405
  objectType: 'segment-connector',
@@ -36612,61 +36735,6 @@ var SceneTooltipsManager = /*#__PURE__*/function (_BaseDisposable) {
36612
36735
  }]);
36613
36736
  }(BaseDisposable);
36614
36737
 
36615
- /**
36616
- * Shared I/O device state dispatch helpers used by centralPlant and componentTooltipManager.
36617
- */
36618
-
36619
- /**
36620
- * @param {string} attachmentId
36621
- * @param {string|null|undefined} parentUuid
36622
- * @returns {string}
36623
- */
36624
- function getScopedAttachmentKey(attachmentId, parentUuid) {
36625
- if (!parentUuid) return attachmentId;
36626
- return "".concat(parentUuid, "::").concat(attachmentId);
36627
- }
36628
-
36629
- /**
36630
- * @param {Object} sceneViewer
36631
- * @returns {import('../managers/behaviors/IoBehaviorManager.js').IoBehaviorManager|null}
36632
- */
36633
- function getIoBehaviorManager(sceneViewer) {
36634
- var _sceneViewer$managers, _sceneViewer$centralP;
36635
- if (!sceneViewer) return null;
36636
- return ((_sceneViewer$managers = sceneViewer.managers) === null || _sceneViewer$managers === void 0 ? void 0 : _sceneViewer$managers.ioBehaviorManager) || sceneViewer.ioBehaviorManager || ((_sceneViewer$centralP = sceneViewer.centralPlant) === null || _sceneViewer$centralP === void 0 || (_sceneViewer$centralP = _sceneViewer$centralP.managers) === null || _sceneViewer$centralP === void 0 ? void 0 : _sceneViewer$centralP.ioBehaviorManager) || null;
36637
- }
36638
-
36639
- /**
36640
- * Resolve tooltip/drag data points for an I/O device attachment.
36641
- * Prefers behaviorConfig-driven animation data points; merges legacy ioConfig snapshot.
36642
- *
36643
- * @param {string} parentUuid
36644
- * @param {string} attachmentId
36645
- * @param {Object} userData - io-device userData (may include dataPoints snapshot)
36646
- * @param {import('../managers/behaviors/IoBehaviorManager.js').IoBehaviorManager|null} ioBehaviorManager
36647
- * @param {THREE.Object3D|null} [hitMesh]
36648
- * @returns {Object[]}
36649
- */
36650
- function resolveDataPoints(parentUuid, attachmentId, userData, ioBehaviorManager) {
36651
- var hitMesh = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
36652
- var fromAnimations = (ioBehaviorManager === null || ioBehaviorManager === void 0 ? void 0 : ioBehaviorManager.getAnimationDataPoints(parentUuid, attachmentId, hitMesh)) || [];
36653
- if (fromAnimations.length) return fromAnimations;
36654
- var legacy = (userData === null || userData === void 0 ? void 0 : userData.dataPoints) || [];
36655
- return legacy.map(function (dp) {
36656
- var _dp$defaultValue;
36657
- return {
36658
- id: dp.id || dp.name,
36659
- name: dp.name || dp.id,
36660
- stateType: dp.stateType || 'binary',
36661
- stateConfig: dp.stateConfig || {},
36662
- defaultValue: (_dp$defaultValue = dp.defaultValue) !== null && _dp$defaultValue !== void 0 ? _dp$defaultValue : null,
36663
- direction: dp.direction || (userData === null || userData === void 0 ? void 0 : userData.ioDirection) || 'output'
36664
- };
36665
- }).filter(function (dp) {
36666
- return dp.id;
36667
- });
36668
- }
36669
-
36670
36738
  // ---------------------------------------------------------------------------
36671
36739
  // Inline styles (injected once into the document head)
36672
36740
  // ---------------------------------------------------------------------------
@@ -37734,6 +37802,53 @@ function parseCrossBehavior(behavior) {
37734
37802
  };
37735
37803
  }
37736
37804
 
37805
+ /**
37806
+ * Resolve the runtime default value for an animation behavior entry.
37807
+ * Uses explicit `defaultValue` when present; otherwise infers from stateType and mappings.
37808
+ *
37809
+ * @param {Object} anim - Behavior entry from behaviorConfig
37810
+ * @returns {boolean|string|number}
37811
+ */
37812
+ function resolveAnimationDefaultValue(anim) {
37813
+ var _anim$stateConfig2, _anim$stateConfig3;
37814
+ if (!anim) return null;
37815
+ var rawType = (anim.stateType || '').toLowerCase();
37816
+ var isBinary = rawType === 'binary' || rawType === 'boolean';
37817
+ var isEnum = rawType === 'enum';
37818
+ if (anim.defaultValue !== undefined && anim.defaultValue !== null) {
37819
+ if (isBinary) return !!anim.defaultValue;
37820
+ if (isEnum) return String(anim.defaultValue);
37821
+ var n = Number(anim.defaultValue);
37822
+ return Number.isNaN(n) ? 0 : n;
37823
+ }
37824
+ if (isBinary) return false;
37825
+ if (isEnum) {
37826
+ var _anim$stateConfig, _resolved$;
37827
+ var _mappingValues = (anim.mappings || []).map(function (m) {
37828
+ return m.stateValue;
37829
+ }).filter(function (v) {
37830
+ return v !== '' && v != null;
37831
+ });
37832
+ var options = (((_anim$stateConfig = anim.stateConfig) === null || _anim$stateConfig === void 0 ? void 0 : _anim$stateConfig.options) || []).filter(function (o) {
37833
+ return o !== '';
37834
+ });
37835
+ var resolved = options.length ? options : _toConsumableArray(new Set(_mappingValues.map(String)));
37836
+ return (_resolved$ = resolved[0]) !== null && _resolved$ !== void 0 ? _resolved$ : '';
37837
+ }
37838
+ var mappingValues = (anim.mappings || []).map(function (m) {
37839
+ return m.stateValue;
37840
+ });
37841
+ var nums = mappingValues.map(Number).filter(function (n) {
37842
+ return !Number.isNaN(n);
37843
+ });
37844
+ if (nums.length) return Math.min.apply(Math, _toConsumableArray(nums));
37845
+ if (((_anim$stateConfig2 = anim.stateConfig) === null || _anim$stateConfig2 === void 0 ? void 0 : _anim$stateConfig2.min) !== undefined && ((_anim$stateConfig3 = anim.stateConfig) === null || _anim$stateConfig3 === void 0 ? void 0 : _anim$stateConfig3.min) !== null) {
37846
+ var min = Number(anim.stateConfig.min);
37847
+ return Number.isNaN(min) ? 0 : min;
37848
+ }
37849
+ return 0;
37850
+ }
37851
+
37737
37852
  /**
37738
37853
  * Translation helpers for I/O device animations.
37739
37854
  * Offsets are expressed in the device/model root's local space so every child
@@ -37743,13 +37858,14 @@ function parseCrossBehavior(behavior) {
37743
37858
  /**
37744
37859
  * @param {THREE.Object3D} modelRoot
37745
37860
  * @param {{ x?: number, y?: number, z?: number }|THREE.Vector3} offset
37861
+ * @param {THREE.Quaternion} [customQuat] - Optional override for model orientation
37746
37862
  * @returns {THREE.Vector3}
37747
37863
  */
37748
- function modelOffsetToWorldDelta(modelRoot, offset) {
37864
+ function modelOffsetToWorldDelta(modelRoot, offset, customQuat) {
37749
37865
  var _offset$x, _offset$y, _offset$z;
37750
37866
  var v = offset instanceof THREE__namespace.Vector3 ? offset.clone() : new THREE__namespace.Vector3((_offset$x = offset === null || offset === void 0 ? void 0 : offset.x) !== null && _offset$x !== void 0 ? _offset$x : 0, (_offset$y = offset === null || offset === void 0 ? void 0 : offset.y) !== null && _offset$y !== void 0 ? _offset$y : 0, (_offset$z = offset === null || offset === void 0 ? void 0 : offset.z) !== null && _offset$z !== void 0 ? _offset$z : 0);
37751
- var q = new THREE__namespace.Quaternion();
37752
- modelRoot.getWorldQuaternion(q);
37867
+ var q = customQuat ? customQuat.clone() : new THREE__namespace.Quaternion();
37868
+ if (!customQuat) modelRoot.getWorldQuaternion(q);
37753
37869
  return v.applyQuaternion(q);
37754
37870
  }
37755
37871
 
@@ -37760,14 +37876,15 @@ function modelOffsetToWorldDelta(modelRoot, offset) {
37760
37876
  * @param {THREE.Object3D} modelRoot
37761
37877
  * @param {THREE.Vector3} origLocalPos
37762
37878
  * @param {{ x?: number, y?: number, z?: number }} modelOffset
37879
+ * @param {THREE.Quaternion} [customQuat]
37763
37880
  */
37764
- function applyModelRootTranslation(mesh, modelRoot, origLocalPos, modelOffset) {
37881
+ function applyModelRootTranslation(mesh, modelRoot, origLocalPos, modelOffset, customQuat) {
37765
37882
  if (!mesh || !modelRoot || !origLocalPos) return;
37766
37883
  mesh.position.copy(origLocalPos);
37767
37884
  mesh.updateMatrixWorld(true);
37768
37885
  var origWorldPos = new THREE__namespace.Vector3();
37769
37886
  mesh.getWorldPosition(origWorldPos);
37770
- var newWorldPos = origWorldPos.add(modelOffsetToWorldDelta(modelRoot, modelOffset));
37887
+ var newWorldPos = origWorldPos.add(modelOffsetToWorldDelta(modelRoot, modelOffset, customQuat));
37771
37888
  if (mesh.parent) mesh.parent.worldToLocal(newWorldPos);
37772
37889
  mesh.position.copy(newWorldPos);
37773
37890
  }
@@ -37779,10 +37896,11 @@ function applyModelRootTranslation(mesh, modelRoot, origLocalPos, modelOffset) {
37779
37896
  * @param {THREE.Object3D} modelRoot
37780
37897
  * @param {THREE.Vector3} baseWorldPos
37781
37898
  * @param {{ x?: number, y?: number, z?: number }} modelOffset
37899
+ * @param {THREE.Quaternion} [customQuat]
37782
37900
  */
37783
- function applyModelRootTranslationFromWorldBase(mesh, modelRoot, baseWorldPos, modelOffset) {
37901
+ function applyModelRootTranslationFromWorldBase(mesh, modelRoot, baseWorldPos, modelOffset, customQuat) {
37784
37902
  if (!mesh || !modelRoot || !baseWorldPos) return;
37785
- var newWorldPos = baseWorldPos.clone().add(modelOffsetToWorldDelta(modelRoot, modelOffset));
37903
+ var newWorldPos = baseWorldPos.clone().add(modelOffsetToWorldDelta(modelRoot, modelOffset, customQuat));
37786
37904
  if (mesh.parent) mesh.parent.worldToLocal(newWorldPos);
37787
37905
  mesh.position.copy(newWorldPos);
37788
37906
  }
@@ -38377,18 +38495,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
38377
38495
  stateConfig.max = Math.max.apply(Math, _toConsumableArray(nums));
38378
38496
  }
38379
38497
  }
38380
-
38381
- // Sensible default values
38382
- var defaultValue = void 0;
38383
- if (stateType === 'binary') {
38384
- defaultValue = 0;
38385
- } else if (stateType === 'enum') {
38386
- var _stateConfig$options$, _stateConfig$options;
38387
- defaultValue = (_stateConfig$options$ = (_stateConfig$options = stateConfig.options) === null || _stateConfig$options === void 0 ? void 0 : _stateConfig$options[0]) !== null && _stateConfig$options$ !== void 0 ? _stateConfig$options$ : '';
38388
- } else {
38389
- var _stateConfig$min;
38390
- defaultValue = (_stateConfig$min = stateConfig.min) !== null && _stateConfig$min !== void 0 ? _stateConfig$min : 0;
38391
- }
38498
+ var defaultValue = resolveAnimationDefaultValue(_anim);
38392
38499
  dps.push({
38393
38500
  id: stateVar,
38394
38501
  name: _anim.name || stateVar,
@@ -39976,7 +40083,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
39976
40083
  }, {
39977
40084
  key: "addComponent",
39978
40085
  value: function addComponent(libraryId) {
39979
- var _this$centralPlant$sc6;
40086
+ var _this$centralPlant$sc6,
40087
+ _this2 = this;
39980
40088
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
39981
40089
  // Use centralized validation for component addition parameters
39982
40090
  var existingIds = this.getComponentIds();
@@ -40213,7 +40321,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
40213
40321
  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;
40214
40322
  attachIODevicesToComponent(componentModel, componentData, modelPreloader, componentId).then(function () {
40215
40323
  if (ioBehavMgr) {
40216
- registerBehaviorsForComponent(ioBehavMgr, componentId, componentData, componentModel, modelPreloader.componentDictionary);
40324
+ registerBehaviorsForComponent(ioBehavMgr, componentId, componentData, componentModel, modelPreloader.componentDictionary, _this2.centralPlant);
40217
40325
  }
40218
40326
  }).catch(function (err) {
40219
40327
  console.error("\u274C Error attaching IO devices for ".concat(libraryId, ":"), err);
@@ -40500,7 +40608,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
40500
40608
  /**
40501
40609
  * Scene-level behavior helpers: scan endpoints, register behaviors, cross-component links.
40502
40610
  */
40503
- function getComponentDictionary(centralPlant) {
40611
+ function getComponentDictionary$1(centralPlant) {
40504
40612
  var _centralPlant$getUtil, _centralPlant$manager;
40505
40613
  return (centralPlant === null || centralPlant === void 0 || (_centralPlant$getUtil = centralPlant.getUtility) === null || _centralPlant$getUtil === void 0 || (_centralPlant$getUtil = _centralPlant$getUtil.call(centralPlant, 'modelPreloader')) === null || _centralPlant$getUtil === void 0 ? void 0 : _centralPlant$getUtil.componentDictionary) || (centralPlant === null || centralPlant === void 0 || (_centralPlant$manager = centralPlant.managers) === null || _centralPlant$manager === void 0 || (_centralPlant$manager = _centralPlant$manager.componentDataManager) === null || _centralPlant$manager === void 0 ? void 0 : _centralPlant$manager.componentDictionary) || null;
40506
40614
  }
@@ -40531,7 +40639,7 @@ function scanSceneIoEndpoints(centralPlant) {
40531
40639
  var _centralPlant$sceneVi;
40532
40640
  var scene = centralPlant === null || centralPlant === void 0 || (_centralPlant$sceneVi = centralPlant.sceneViewer) === null || _centralPlant$sceneVi === void 0 ? void 0 : _centralPlant$sceneVi.scene;
40533
40641
  if (!scene) return [];
40534
- var dict = getComponentDictionary(centralPlant);
40642
+ var dict = getComponentDictionary$1(centralPlant);
40535
40643
  var endpoints = [];
40536
40644
  scene.traverse(function (obj) {
40537
40645
  var _obj$userData, _parent$userData, _parent$userData2;
@@ -40624,7 +40732,7 @@ function reregisterSceneBehaviors(centralPlant) {
40624
40732
  var _centralPlant$sceneVi4;
40625
40733
  var ioBehavMgr = getIoBehaviorManager(centralPlant === null || centralPlant === void 0 ? void 0 : centralPlant.sceneViewer);
40626
40734
  var scene = centralPlant === null || centralPlant === void 0 || (_centralPlant$sceneVi4 = centralPlant.sceneViewer) === null || _centralPlant$sceneVi4 === void 0 ? void 0 : _centralPlant$sceneVi4.scene;
40627
- var dict = getComponentDictionary(centralPlant);
40735
+ var dict = getComponentDictionary$1(centralPlant);
40628
40736
  if (!ioBehavMgr || !scene) return;
40629
40737
  var crossBehaviors = loadCrossComponentBehaviors(centralPlant);
40630
40738
  ioBehavMgr.setCrossComponentBehaviors(crossBehaviors);
@@ -40636,7 +40744,7 @@ function reregisterSceneBehaviors(centralPlant) {
40636
40744
  if (!libraryId) return;
40637
40745
  var componentData = dict[libraryId];
40638
40746
  if (!componentData) return;
40639
- registerBehaviorsForComponent(ioBehavMgr, obj.uuid, componentData, obj, dict);
40747
+ registerBehaviorsForComponent(ioBehavMgr, obj.uuid, componentData, obj, dict, centralPlant);
40640
40748
  });
40641
40749
  }
40642
40750
 
@@ -40666,7 +40774,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
40666
40774
  * Initialize the CentralPlant manager
40667
40775
  *
40668
40776
  * @constructor
40669
- * @version 0.3.41
40777
+ * @version 0.3.43
40670
40778
  * @updated 2025-10-22
40671
40779
  *
40672
40780
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -43158,7 +43266,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
43158
43266
  key: "importScene",
43159
43267
  value: (function () {
43160
43268
  var _importScene = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10(jsonData) {
43161
- var validation, missingIds, resolved, _t4, _t5;
43269
+ var validation, embeddedCount, missingIds, resolved, _t4, _t5;
43162
43270
  return _regenerator().w(function (_context10) {
43163
43271
  while (1) switch (_context10.n) {
43164
43272
  case 0:
@@ -43179,64 +43287,78 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
43179
43287
  console.error('❌ Invalid scene data format:', validation.message);
43180
43288
  return _context10.a(2, false);
43181
43289
  case 2:
43290
+ if (!(jsonData.componentDefinitions && _typeof(jsonData.componentDefinitions) === 'object')) {
43291
+ _context10.n = 4;
43292
+ break;
43293
+ }
43294
+ embeddedCount = Object.keys(jsonData.componentDefinitions).length;
43295
+ if (!(embeddedCount > 0)) {
43296
+ _context10.n = 4;
43297
+ break;
43298
+ }
43299
+ _context10.n = 3;
43300
+ return this.extendComponentDictionary(jsonData.componentDefinitions);
43301
+ case 3:
43302
+ console.log("\uD83D\uDCE6 importScene(): Applied ".concat(embeddedCount, " embedded component definition(s)"));
43303
+ case 4:
43182
43304
  if (!this._componentDefinitionResolver) {
43183
- _context10.n = 8;
43305
+ _context10.n = 10;
43184
43306
  break;
43185
43307
  }
43186
43308
  missingIds = this.getMissingLibraryIds(jsonData);
43187
43309
  if (!(missingIds.length > 0)) {
43188
- _context10.n = 8;
43310
+ _context10.n = 10;
43189
43311
  break;
43190
43312
  }
43191
- _context10.p = 3;
43313
+ _context10.p = 5;
43192
43314
  console.log("\uD83D\uDD0D importScene(): Resolving ".concat(missingIds.length, " missing component definition(s)..."));
43193
- _context10.n = 4;
43315
+ _context10.n = 6;
43194
43316
  return this._componentDefinitionResolver(missingIds);
43195
- case 4:
43317
+ case 6:
43196
43318
  resolved = _context10.v;
43197
43319
  if (!(resolved && _typeof(resolved) === 'object' && Object.keys(resolved).length > 0)) {
43198
- _context10.n = 6;
43320
+ _context10.n = 8;
43199
43321
  break;
43200
43322
  }
43201
- _context10.n = 5;
43323
+ _context10.n = 7;
43202
43324
  return this.extendComponentDictionary(resolved);
43203
- case 5:
43325
+ case 7:
43204
43326
  console.log("\u2705 importScene(): Resolved ".concat(Object.keys(resolved).length, " component definition(s)"));
43205
- case 6:
43206
- _context10.n = 8;
43327
+ case 8:
43328
+ _context10.n = 10;
43207
43329
  break;
43208
- case 7:
43209
- _context10.p = 7;
43330
+ case 9:
43331
+ _context10.p = 9;
43210
43332
  _t4 = _context10.v;
43211
43333
  console.warn('⚠️ importScene(): Component definition resolver failed, continuing with existing dictionary:', _t4);
43212
- case 8:
43213
- _context10.n = 9;
43334
+ case 10:
43335
+ _context10.n = 11;
43214
43336
  return this.setImportedSceneData(jsonData);
43215
- case 9:
43337
+ case 11:
43216
43338
  if (!(this.sceneViewer && this.sceneViewer.sceneOperationsManager)) {
43217
- _context10.n = 11;
43339
+ _context10.n = 13;
43218
43340
  break;
43219
43341
  }
43220
- _context10.n = 10;
43342
+ _context10.n = 12;
43221
43343
  return this.sceneViewer.sceneOperationsManager.loadSceneFromData(jsonData);
43222
- case 10:
43344
+ case 12:
43223
43345
  console.log('✅ Scene imported successfully');
43224
43346
  return _context10.a(2, true);
43225
- case 11:
43347
+ case 13:
43226
43348
  console.error('❌ SceneViewer not available for scene loading');
43227
43349
  return _context10.a(2, false);
43228
- case 12:
43229
- _context10.n = 14;
43350
+ case 14:
43351
+ _context10.n = 16;
43230
43352
  break;
43231
- case 13:
43232
- _context10.p = 13;
43353
+ case 15:
43354
+ _context10.p = 15;
43233
43355
  _t5 = _context10.v;
43234
43356
  console.error('❌ Error importing scene:', _t5);
43235
43357
  return _context10.a(2, false);
43236
- case 14:
43358
+ case 16:
43237
43359
  return _context10.a(2);
43238
43360
  }
43239
- }, _callee10, this, [[3, 7], [1, 13]]);
43361
+ }, _callee10, this, [[5, 9], [1, 15]]);
43240
43362
  }));
43241
43363
  function importScene(_x6) {
43242
43364
  return _importScene.apply(this, arguments);
@@ -44874,6 +44996,88 @@ var SceneHierarchyManager = /*#__PURE__*/function (_BaseDisposable) {
44874
44996
  }]);
44875
44997
  }(BaseDisposable);
44876
44998
 
44999
+ var _excluded = ["componentDefinitions"];
45000
+ /**
45001
+ * Helpers for portable demo scene JSON (embedded component definitions).
45002
+ */
45003
+
45004
+ function cloneDefinition(def) {
45005
+ if (!def || _typeof(def) !== 'object') return null;
45006
+ try {
45007
+ return JSON.parse(JSON.stringify(def));
45008
+ } catch (_unused) {
45009
+ return _objectSpread2({}, def);
45010
+ }
45011
+ }
45012
+
45013
+ /**
45014
+ * Collect unique library IDs referenced by scene nodes.
45015
+ * @param {Object} sceneData
45016
+ * @returns {string[]}
45017
+ */
45018
+ function collectSceneLibraryIds(sceneData) {
45019
+ var _sceneData$scene;
45020
+ var ids = new Set();
45021
+ var _walk = function walk(nodes) {
45022
+ if (!Array.isArray(nodes)) return;
45023
+ nodes.forEach(function (node) {
45024
+ var _node$userData;
45025
+ var libraryId = node === null || node === void 0 || (_node$userData = node.userData) === null || _node$userData === void 0 ? void 0 : _node$userData.libraryId;
45026
+ if (libraryId) ids.add(libraryId);
45027
+ if (node.children) _walk(node.children);
45028
+ });
45029
+ };
45030
+ _walk(sceneData === null || sceneData === void 0 || (_sceneData$scene = sceneData.scene) === null || _sceneData$scene === void 0 ? void 0 : _sceneData$scene.children);
45031
+ return Array.from(ids);
45032
+ }
45033
+
45034
+ /**
45035
+ * Embed component/device definitions required by a scene into the JSON payload.
45036
+ * @param {Object} sceneData
45037
+ * @param {Record<string, Object>} componentDictionary
45038
+ * @returns {Object}
45039
+ */
45040
+ function embedComponentDefinitions(sceneData) {
45041
+ var componentDictionary = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
45042
+ if (!sceneData || _typeof(sceneData) !== 'object') return sceneData;
45043
+ var libraryIds = collectSceneLibraryIds(sceneData);
45044
+ var componentDefinitions = {};
45045
+ var deviceIds = new Set();
45046
+ libraryIds.forEach(function (libraryId) {
45047
+ var def = componentDictionary[libraryId];
45048
+ if (!def) return;
45049
+ componentDefinitions[libraryId] = cloneDefinition(def);
45050
+ var attachedDevices = def.attachedDevices;
45051
+ if (!attachedDevices || _typeof(attachedDevices) !== 'object') return;
45052
+ Object.values(attachedDevices).forEach(function (att) {
45053
+ if (att !== null && att !== void 0 && att.deviceId) deviceIds.add(att.deviceId);
45054
+ });
45055
+ });
45056
+ deviceIds.forEach(function (deviceId) {
45057
+ if (componentDefinitions[deviceId]) return;
45058
+ var deviceDef = componentDictionary[deviceId];
45059
+ if (deviceDef) componentDefinitions[deviceId] = cloneDefinition(deviceDef);
45060
+ });
45061
+ if (!Object.keys(componentDefinitions).length) {
45062
+ sceneData.componentDefinitions;
45063
+ var rest = _objectWithoutProperties(sceneData, _excluded);
45064
+ return rest;
45065
+ }
45066
+ return _objectSpread2(_objectSpread2({}, sceneData), {}, {
45067
+ componentDefinitions: componentDefinitions
45068
+ });
45069
+ }
45070
+
45071
+ /**
45072
+ * Resolve the live component dictionary from a CentralPlant instance.
45073
+ * @param {Object} centralPlant
45074
+ * @returns {Record<string, Object>}
45075
+ */
45076
+ function getComponentDictionary(centralPlant) {
45077
+ var _centralPlant$getUtil, _centralPlant$manager;
45078
+ return (centralPlant === null || centralPlant === void 0 || (_centralPlant$getUtil = centralPlant.getUtility) === null || _centralPlant$getUtil === void 0 || (_centralPlant$getUtil = _centralPlant$getUtil.call(centralPlant, 'modelPreloader')) === null || _centralPlant$getUtil === void 0 ? void 0 : _centralPlant$getUtil.componentDictionary) || (centralPlant === null || centralPlant === void 0 || (_centralPlant$manager = centralPlant.managers) === null || _centralPlant$manager === void 0 || (_centralPlant$manager = _centralPlant$manager.componentDataManager) === null || _centralPlant$manager === void 0 ? void 0 : _centralPlant$manager.componentDictionary) || {};
45079
+ }
45080
+
44877
45081
  /**
44878
45082
  * Generic Cache Management using Browser Cache API
44879
45083
  * Framework-agnostic implementation of caching logic
@@ -49344,6 +49548,7 @@ exports.SceneTooltipsManager = SceneTooltipsManager;
49344
49548
  exports.SnapshotManager = SnapshotManager;
49345
49549
  exports.ThreeJSResourceManager = ThreeJSResourceManager;
49346
49550
  exports.applyCrossComponentBehaviors = applyCrossComponentBehaviors;
49551
+ exports.applyDefaultIoDeviceStates = applyDefaultIoDeviceStates;
49347
49552
  exports.applyModelRootTranslation = applyModelRootTranslation;
49348
49553
  exports.applyModelRootTranslationFromWorldBase = applyModelRootTranslationFromWorldBase;
49349
49554
  exports.buildCrossBehavior = buildCrossBehavior;
@@ -49353,8 +49558,10 @@ exports.cacheManager = cacheManager;
49353
49558
  exports.cleanExpiredCache = cleanExpiredCache;
49354
49559
  exports.cleanInvalidCacheEntries = cleanInvalidCacheEntries;
49355
49560
  exports.clearS3Cache = clearS3Cache;
49561
+ exports.collectSceneLibraryIds = collectSceneLibraryIds;
49356
49562
  exports.createPathfindingRequest = createPathfindingRequest;
49357
49563
  exports.createTransformControls = createTransformControls;
49564
+ exports.embedComponentDefinitions = embedComponentDefinitions;
49358
49565
  exports.findObjectByHardcodedUuid = findObjectByHardcodedUuid;
49359
49566
  exports.formatCacheExpiry = formatCacheExpiry;
49360
49567
  exports.generateUniqueComponentId = generateUniqueComponentId;
@@ -49369,6 +49576,7 @@ exports.getCachedLocalJson = getCachedLocalJson;
49369
49576
  exports.getCachedS3Json = getCachedS3Json;
49370
49577
  exports.getCachedS3Object = getCachedS3Object;
49371
49578
  exports.getCachedS3ObjectURL = getCachedS3ObjectURL;
49579
+ exports.getComponentDictionary = getComponentDictionary;
49372
49580
  exports.getCurrentCacheName = getCurrentCacheName;
49373
49581
  exports.getGlobalCacheStats = getGlobalCacheStats;
49374
49582
  exports.getGlobalOnlyCacheStats = getGlobalOnlyCacheStats;
@@ -49407,6 +49615,7 @@ exports.removeCachedJsonData = removeCachedJsonData;
49407
49615
  exports.reregisterSceneBehaviors = reregisterSceneBehaviors;
49408
49616
  exports.resetCacheIdentity = resetCacheIdentity;
49409
49617
  exports.resetGlobalCacheStats = resetGlobalCacheStats;
49618
+ exports.resolveAnimationDefaultValue = resolveAnimationDefaultValue;
49410
49619
  exports.resolveDataPoints = resolveDataPoints;
49411
49620
  exports.s3MetadataCache = s3MetadataCache;
49412
49621
  exports.scanSceneIoEndpoints = scanSceneIoEndpoints;