@2112-lab/central-plant 0.3.37 → 0.3.39

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 (31) hide show
  1. package/dist/bundle/index.js +1080 -563
  2. package/dist/cjs/src/core/centralPlant.js +115 -68
  3. package/dist/cjs/src/core/centralPlantInternals.js +20 -36
  4. package/dist/cjs/src/index.js +19 -0
  5. package/dist/cjs/src/managers/behaviors/IoBehaviorManager.js +175 -234
  6. package/dist/cjs/src/managers/components/componentDataManager.js +63 -11
  7. package/dist/cjs/src/managers/scene/componentTooltipManager.js +95 -65
  8. package/dist/cjs/src/managers/scene/modelManager.js +93 -145
  9. package/dist/cjs/src/managers/scene/sceneExportManager.js +2 -1
  10. package/dist/cjs/src/managers/scene/sceneOperationsManager.js +8 -3
  11. package/dist/cjs/src/utils/animationTransformUtils.js +66 -0
  12. package/dist/cjs/src/utils/behaviorDispatch.js +62 -0
  13. package/dist/cjs/src/utils/behaviorRegistration.js +76 -0
  14. package/dist/cjs/src/utils/behaviorSceneUtils.js +155 -0
  15. package/dist/cjs/src/utils/behaviorSchema.js +209 -0
  16. package/dist/esm/src/core/centralPlant.js +115 -68
  17. package/dist/esm/src/core/centralPlantInternals.js +21 -37
  18. package/dist/esm/src/index.js +4 -0
  19. package/dist/esm/src/managers/behaviors/IoBehaviorManager.js +176 -235
  20. package/dist/esm/src/managers/components/componentDataManager.js +63 -11
  21. package/dist/esm/src/managers/scene/componentTooltipManager.js +95 -65
  22. package/dist/esm/src/managers/scene/modelManager.js +94 -146
  23. package/dist/esm/src/managers/scene/sceneExportManager.js +2 -1
  24. package/dist/esm/src/managers/scene/sceneOperationsManager.js +8 -3
  25. package/dist/esm/src/utils/animationTransformUtils.js +41 -0
  26. package/dist/esm/src/utils/behaviorDispatch.js +56 -0
  27. package/dist/esm/src/utils/behaviorRegistration.js +71 -0
  28. package/dist/esm/src/utils/behaviorSceneUtils.js +147 -0
  29. package/dist/esm/src/utils/behaviorSchema.js +201 -0
  30. package/dist/index.d.ts +169 -1
  31. package/package.json +1 -1
@@ -351,6 +351,14 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
351
351
  if (!_this3.componentDictionary[key]) {
352
352
  newComponents[key] = component;
353
353
  } else {
354
+ var _component$behaviors;
355
+ var existing = _this3.componentDictionary[key];
356
+ if (component.behaviorConfig) existing.behaviorConfig = component.behaviorConfig;
357
+ if (component.meshNameMap) existing.meshNameMap = component.meshNameMap;
358
+ if ((_component$behaviors = component.behaviors) !== null && _component$behaviors !== void 0 && _component$behaviors.length) existing.behaviors = component.behaviors;
359
+ if (component.attachedDevices) {
360
+ existing.attachedDevices = _objectSpread2(_objectSpread2({}, existing.attachedDevices || {}), component.attachedDevices);
361
+ }
354
362
  console.log("\u26A0\uFE0F Skipping duplicate component: ".concat(key, " (").concat(component.name || 'unnamed', ")"));
355
363
  }
356
364
  });
@@ -382,17 +390,61 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
382
390
  }
383
391
  return extendComponentDictionary;
384
392
  }()
393
+ /**
394
+ * Merge mesh animation configs from host persistence into the live dictionary.
395
+ * @param {Object<string, { behaviorConfig?: Array, meshNameMap?: Object, behaviors?: Array }>} configsByAssetId
396
+ * @returns {number} Count of entries updated
397
+ */
398
+ )
399
+ }, {
400
+ key: "mergeBehaviorConfigsIntoDictionary",
401
+ value: function mergeBehaviorConfigsIntoDictionary(configsByAssetId) {
402
+ var _this$sceneViewer2;
403
+ if (!configsByAssetId || !this.componentDictionary) return 0;
404
+ var merged = 0;
405
+ for (var _i2 = 0, _Object$entries2 = Object.entries(configsByAssetId); _i2 < _Object$entries2.length; _i2++) {
406
+ var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
407
+ assetId = _Object$entries2$_i[0],
408
+ attrs = _Object$entries2$_i[1];
409
+ var entry = this.componentDictionary[assetId];
410
+ if (!entry || !attrs) continue;
411
+ var updated = false;
412
+ if (attrs.behaviorConfig) {
413
+ entry.behaviorConfig = attrs.behaviorConfig;
414
+ updated = true;
415
+ }
416
+ if (attrs.meshNameMap) {
417
+ entry.meshNameMap = attrs.meshNameMap;
418
+ updated = true;
419
+ }
420
+ if ('behaviors' in attrs) {
421
+ var _attrs$behaviors;
422
+ if ((_attrs$behaviors = attrs.behaviors) !== null && _attrs$behaviors !== void 0 && _attrs$behaviors.length) {
423
+ entry.behaviors = attrs.behaviors;
424
+ } else {
425
+ delete entry.behaviors;
426
+ }
427
+ updated = true;
428
+ }
429
+ if (updated) merged++;
430
+ }
431
+ var modelPreloader = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.centralPlant) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.utilities) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.modelPreloader;
432
+ if (modelPreloader) {
433
+ modelPreloader.componentDictionary = this.componentDictionary;
434
+ }
435
+ return merged;
436
+ }
437
+
385
438
  /**
386
439
  * Remove S3 components from the component dictionary
387
440
  * @returns {Promise<boolean>} True if components were removed successfully
388
441
  */
389
- )
390
442
  }, {
391
443
  key: "removeS3Components",
392
444
  value: (function () {
393
445
  var _removeS3Components = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
394
446
  var _this4 = this;
395
- var _this$sceneViewer2, keysToRemove, _i2, _Object$entries2, _Object$entries2$_i, key, component, modelPreloader, _t2;
447
+ var _this$sceneViewer3, keysToRemove, _i3, _Object$entries3, _Object$entries3$_i, key, component, modelPreloader, _t2;
396
448
  return _regenerator().w(function (_context4) {
397
449
  while (1) switch (_context4.n) {
398
450
  case 0:
@@ -409,8 +461,8 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
409
461
  _context4.p = 2;
410
462
  // Find and remove all S3 components
411
463
  keysToRemove = [];
412
- for (_i2 = 0, _Object$entries2 = Object.entries(this.componentDictionary); _i2 < _Object$entries2.length; _i2++) {
413
- _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2), key = _Object$entries2$_i[0], component = _Object$entries2$_i[1];
464
+ for (_i3 = 0, _Object$entries3 = Object.entries(this.componentDictionary); _i3 < _Object$entries3.length; _i3++) {
465
+ _Object$entries3$_i = _slicedToArray(_Object$entries3[_i3], 2), key = _Object$entries3$_i[0], component = _Object$entries3$_i[1];
414
466
  if (component.isS3Component) {
415
467
  keysToRemove.push(key);
416
468
  }
@@ -422,7 +474,7 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
422
474
  });
423
475
 
424
476
  // Update ModelPreloader's dictionary reference
425
- modelPreloader = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.centralPlant) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.utilities) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.modelPreloader;
477
+ modelPreloader = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.centralPlant) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.utilities) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.modelPreloader;
426
478
  if (modelPreloader) {
427
479
  modelPreloader.componentDictionary = this.componentDictionary;
428
480
  console.log("\uD83D\uDD04 Updated ModelPreloader's dictionary reference (".concat(Object.keys(this.componentDictionary).length, " total components)"));
@@ -455,7 +507,7 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
455
507
  key: "removeComponentFromDictionary",
456
508
  value: (function () {
457
509
  var _removeComponentFromDictionary = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(componentKey) {
458
- var _this$sceneViewer3, modelPreloader, _t3;
510
+ var _this$sceneViewer4, modelPreloader, _t3;
459
511
  return _regenerator().w(function (_context5) {
460
512
  while (1) switch (_context5.n) {
461
513
  case 0:
@@ -488,7 +540,7 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
488
540
  delete this.componentDictionary[componentKey];
489
541
 
490
542
  // Update ModelPreloader's dictionary reference
491
- modelPreloader = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.centralPlant) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.utilities) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.modelPreloader;
543
+ modelPreloader = (_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 || (_this$sceneViewer4 = _this$sceneViewer4.centralPlant) === null || _this$sceneViewer4 === void 0 || (_this$sceneViewer4 = _this$sceneViewer4.utilities) === null || _this$sceneViewer4 === void 0 ? void 0 : _this$sceneViewer4.modelPreloader;
492
544
  if (modelPreloader) {
493
545
  modelPreloader.componentDictionary = this.componentDictionary;
494
546
  console.log("\uD83D\uDD04 Updated ModelPreloader's dictionary reference (".concat(Object.keys(this.componentDictionary).length, " total components)"));
@@ -588,10 +640,10 @@ var ComponentDataManager = /*#__PURE__*/function (_BaseDisposable) {
588
640
  if (!this.componentDictionary) return 'unknown';
589
641
 
590
642
  // Look for component in dictionary
591
- for (var _i3 = 0, _Object$entries3 = Object.entries(this.componentDictionary); _i3 < _Object$entries3.length; _i3++) {
592
- var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i3], 2),
593
- key = _Object$entries3$_i[0],
594
- component = _Object$entries3$_i[1];
643
+ for (var _i4 = 0, _Object$entries4 = Object.entries(this.componentDictionary); _i4 < _Object$entries4.length; _i4++) {
644
+ var _Object$entries4$_i = _slicedToArray(_Object$entries4[_i4], 2),
645
+ key = _Object$entries4$_i[0],
646
+ component = _Object$entries4$_i[1];
595
647
  if (key === 'categories') continue;
596
648
  if (name && name.toLowerCase().includes(key.toLowerCase())) {
597
649
  return component.category || 'unknown';
@@ -1,6 +1,7 @@
1
1
  import { inherits as _inherits, createClass as _createClass, createForOfIteratorHelper as _createForOfIteratorHelper, classCallCheck as _classCallCheck, callSuper as _callSuper } from '../../../_virtual/_rollupPluginBabelHelpers.js';
2
2
  import * as THREE from 'three';
3
3
  import { BaseDisposable } from '../../core/baseDisposable.js';
4
+ import { resolveDataPoints, getIoBehaviorManager, getScopedAttachmentKey } from '../../utils/behaviorDispatch.js';
4
5
 
5
6
  // ---------------------------------------------------------------------------
6
7
  // Inline styles (injected once into the document head)
@@ -11,6 +12,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
11
12
  * @param {Object} sceneViewer - The sceneViewer instance
12
13
  */
13
14
  function ComponentTooltipManager(sceneViewer) {
15
+ var _this$sceneViewer, _this$sceneViewer$on;
14
16
  var _this;
15
17
  _classCallCheck(this, ComponentTooltipManager);
16
18
  _this = _callSuper(this, ComponentTooltipManager);
@@ -35,29 +37,38 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
35
37
  * Map of live DOM elements that display current data point values.
36
38
  * Key: `${attachmentId}::${dataPointId}`
37
39
  * Value: { el: HTMLElement, dp: Object, isInput: boolean }
38
- * Populated during _buildTooltip; polled each frame in _refreshStateDisplays.
40
+ * Populated during _buildTooltip; refreshed on io-device-state-changed events.
39
41
  * @type {Map<string, {el: HTMLElement, dp: Object, isInput: boolean}>}
40
42
  */
41
43
  _this._stateElements = new Map();
44
+ _this._onIoStateChanged = _this._onIoStateChanged.bind(_this);
42
45
  _this._injectStyles();
43
46
  _this._onKeyDown = _this._onKeyDown.bind(_this);
44
47
  document.addEventListener('keydown', _this._onKeyDown);
48
+ (_this$sceneViewer = _this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer$on = _this$sceneViewer.on) === null || _this$sceneViewer$on === void 0 || _this$sceneViewer$on.call(_this$sceneViewer, 'io-device-state-changed', _this._onIoStateChanged);
45
49
  return _this;
46
50
  }
47
-
48
- // -----------------------------------------------------------------------
49
- // Lifecycle
50
- // -----------------------------------------------------------------------
51
-
52
- /**
53
- * Called automatically by BaseDisposable.dispose()
54
- * @override
55
- */
56
51
  _inherits(ComponentTooltipManager, _BaseDisposable);
57
52
  return _createClass(ComponentTooltipManager, [{
53
+ key: "_onIoStateChanged",
54
+ value: function _onIoStateChanged() {
55
+ this._refreshStateDisplays();
56
+ }
57
+
58
+ // -----------------------------------------------------------------------
59
+ // Lifecycle
60
+ // -----------------------------------------------------------------------
61
+
62
+ /**
63
+ * Called automatically by BaseDisposable.dispose()
64
+ * @override
65
+ */
66
+ }, {
58
67
  key: "_doDispose",
59
68
  value: function _doDispose() {
69
+ var _this$sceneViewer2, _this$sceneViewer2$of;
60
70
  document.removeEventListener('keydown', this._onKeyDown);
71
+ (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2$of = _this$sceneViewer2.off) === null || _this$sceneViewer2$of === void 0 || _this$sceneViewer2$of.call(_this$sceneViewer2, 'io-device-state-changed', this._onIoStateChanged);
61
72
  this.hide();
62
73
  this._removeStyleTag();
63
74
  this._stateElements.clear();
@@ -105,7 +116,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
105
116
  }, {
106
117
  key: "toggleIODeviceBinaryState",
107
118
  value: function toggleIODeviceBinaryState(ioDeviceObject) {
108
- var _ref, _this$sceneViewer;
119
+ var _ref;
109
120
  if (!ioDeviceObject || !this._stateAdapter) return;
110
121
  var ud = ioDeviceObject.userData;
111
122
  var attachmentId = ud === null || ud === void 0 ? void 0 : ud.attachmentId;
@@ -126,7 +137,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
126
137
 
127
138
  // Create a scoped attachment key to prevent state sharing between instances
128
139
  // of the same smart component that share the same attachmentId
129
- var scopedAttachmentId = this._getScopedAttachmentKey(attachmentId, parentUuid);
140
+ var scopedAttachmentId = getScopedAttachmentKey(attachmentId, parentUuid);
130
141
 
131
142
  // Find the first binary state
132
143
  var binaryState = dataPoints.find(function (dp) {
@@ -138,8 +149,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
138
149
  // Fall back to defaultValue when state is uninitialized (null/undefined)
139
150
  var currentVal = (_ref = storedVal !== null && storedVal !== void 0 ? storedVal : binaryState.defaultValue) !== null && _ref !== void 0 ? _ref : false;
140
151
  var newVal = !Boolean(currentVal);
141
- this._stateAdapter.setState(scopedAttachmentId, dpId, newVal);
142
- (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.managers) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.ioBehaviorManager) === null || _this$sceneViewer === void 0 || _this$sceneViewer.triggerState(attachmentId, dpId, newVal, parentUuid);
152
+ this._dispatchIoState(attachmentId, dpId, newVal, parentUuid);
143
153
  console.log("\uD83D\uDD04 [IODevice] Toggled ".concat(scopedAttachmentId, ".").concat(dpId, ": ").concat(currentVal, " \u2192 ").concat(newVal));
144
154
  }
145
155
 
@@ -155,8 +165,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
155
165
  }, {
156
166
  key: "startIODeviceDrag",
157
167
  value: function startIODeviceDrag(ioDeviceObject, hitMesh) {
158
- var _this$sceneViewer2,
159
- _this2 = this;
168
+ var _this2 = this;
160
169
  if (!ioDeviceObject || !this._stateAdapter) return;
161
170
  var ud = ioDeviceObject.userData;
162
171
  var attachmentId = ud === null || ud === void 0 ? void 0 : ud.attachmentId;
@@ -171,15 +180,8 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
171
180
  }
172
181
  obj = obj.parent;
173
182
  }
174
- var scopedAttachmentId = this._getScopedAttachmentKey(attachmentId, parentUuid);
175
- var ioBehavMgr = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.managers) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.ioBehaviorManager;
176
- var dataPoints = ((ioBehavMgr === null || ioBehavMgr === void 0 ? void 0 : ioBehavMgr.getAnimationDataPoints(parentUuid, attachmentId, hitMesh)) || []).concat((ud === null || ud === void 0 ? void 0 : ud.dataPoints) || [])
177
- // deduplicate by id
178
- .filter(function (dp, i, arr) {
179
- return arr.findIndex(function (d) {
180
- return d.id === dp.id;
181
- }) === i;
182
- });
183
+ var scopedAttachmentId = getScopedAttachmentKey(attachmentId, parentUuid);
184
+ var dataPoints = resolveDataPoints(parentUuid, attachmentId, ud, getIoBehaviorManager(this.sceneViewer), hitMesh);
183
185
  var dpSessions = [];
184
186
  var _iterator = _createForOfIteratorHelper(dataPoints),
185
187
  _step;
@@ -188,7 +190,6 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
188
190
  var _this2$_stateAdapter$;
189
191
  var dp = _step.value;
190
192
  var stateType = (dp.stateType || '').toLowerCase();
191
- if (stateType !== 'binary' && stateType !== 'boolean' && stateType !== 'enum') return 1; // continue
192
193
  var curVal = (_this2$_stateAdapter$ = _this2._stateAdapter.getState(scopedAttachmentId, dp.id)) !== null && _this2$_stateAdapter$ !== void 0 ? _this2$_stateAdapter$ : dp.defaultValue;
193
194
  if (stateType === 'binary' || stateType === 'boolean') {
194
195
  dpSessions.push({
@@ -199,7 +200,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
199
200
  stateType: 'binary',
200
201
  lastApplied: curVal
201
202
  });
202
- } else {
203
+ } else if (stateType === 'enum') {
203
204
  var _dp$stateConfig;
204
205
  var opts = ((_dp$stateConfig = dp.stateConfig) === null || _dp$stateConfig === void 0 ? void 0 : _dp$stateConfig.options) || [];
205
206
  var curIdx = opts.findIndex(function (o) {
@@ -215,10 +216,27 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
215
216
  startIdx: curIdx >= 0 ? curIdx : 0,
216
217
  lastAppliedIdx: curIdx >= 0 ? curIdx : 0
217
218
  });
219
+ } else if (stateType === 'number' || stateType === 'continuous') {
220
+ var _dp$stateConfig$min, _dp$stateConfig2, _dp$stateConfig$max, _dp$stateConfig3;
221
+ var min = (_dp$stateConfig$min = (_dp$stateConfig2 = dp.stateConfig) === null || _dp$stateConfig2 === void 0 ? void 0 : _dp$stateConfig2.min) !== null && _dp$stateConfig$min !== void 0 ? _dp$stateConfig$min : 0;
222
+ var max = (_dp$stateConfig$max = (_dp$stateConfig3 = dp.stateConfig) === null || _dp$stateConfig3 === void 0 ? void 0 : _dp$stateConfig3.max) !== null && _dp$stateConfig$max !== void 0 ? _dp$stateConfig$max : 1;
223
+ var parsed = Number(curVal);
224
+ var startVal = Number.isFinite(parsed) ? Math.max(min, Math.min(max, parsed)) : min;
225
+ dpSessions.push({
226
+ dp: dp,
227
+ scopedAttachmentId: scopedAttachmentId,
228
+ attachmentId: attachmentId,
229
+ parentUuid: parentUuid,
230
+ stateType: 'number',
231
+ min: min,
232
+ max: max,
233
+ startVal: startVal,
234
+ lastApplied: startVal
235
+ });
218
236
  }
219
237
  };
220
238
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
221
- if (_loop()) continue;
239
+ _loop();
222
240
  }
223
241
  } catch (err) {
224
242
  _iterator.e(err);
@@ -235,8 +253,9 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
235
253
  * Called continuously during pointermove.
236
254
  *
237
255
  * Sign convention: up/right = positive `signedDelta`.
238
- * - Binary: > +20 px → true/on state, < −20 px → false/off state.
239
- * - Enum: each ±30 px step advances/retreats one option in the list.
256
+ * - Binary: > +20 px → true/on state, < −20 px → false/off state.
257
+ * - Enum: each ±30 px step advances/retreats one option in the list.
258
+ * - Continuous: ±200 px spans the configured min→max range.
240
259
  *
241
260
  * @param {number} signedDelta - Cumulative signed pixel displacement since drag start
242
261
  */
@@ -247,6 +266,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
247
266
  if (!session) return;
248
267
  var BINARY_THRESHOLD = 20;
249
268
  var ENUM_STEP_PX = 30;
269
+ var RANGE_PX = 200;
250
270
  var _iterator2 = _createForOfIteratorHelper(session.dpSessions),
251
271
  _step2;
252
272
  try {
@@ -270,6 +290,13 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
270
290
  if (newIdx === dps.lastAppliedIdx) continue;
271
291
  dps.lastAppliedIdx = newIdx;
272
292
  this._applyDpState(dps, dps.opts[newIdx]);
293
+ } else if (dps.stateType === 'number') {
294
+ var span = dps.max - dps.min || 1;
295
+ var delta = signedDelta / RANGE_PX * span;
296
+ var _newVal = Math.max(dps.min, Math.min(dps.max, dps.startVal + delta));
297
+ if (Math.abs(_newVal - dps.lastApplied) < span * 0.001) continue;
298
+ dps.lastApplied = _newVal;
299
+ this._applyDpState(dps, _newVal);
273
300
  }
274
301
  }
275
302
  } catch (err) {
@@ -295,14 +322,35 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
295
322
  }, {
296
323
  key: "_applyDpState",
297
324
  value: function _applyDpState(_ref2, newVal) {
298
- var _this$_stateAdapter, _this$sceneViewer3;
299
- var scopedAttachmentId = _ref2.scopedAttachmentId,
300
- attachmentId = _ref2.attachmentId,
325
+ _ref2.scopedAttachmentId;
326
+ var attachmentId = _ref2.attachmentId,
301
327
  parentUuid = _ref2.parentUuid,
302
328
  dp = _ref2.dp;
303
- var dpId = dp.id;
304
- (_this$_stateAdapter = this._stateAdapter) === null || _this$_stateAdapter === void 0 || _this$_stateAdapter.setState(scopedAttachmentId, dpId, newVal);
305
- (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.managers) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.ioBehaviorManager) === null || _this$sceneViewer3 === void 0 || _this$sceneViewer3.triggerState(attachmentId, dpId, newVal, parentUuid);
329
+ this._dispatchIoState(attachmentId, dp.id, newVal, parentUuid);
330
+ }
331
+
332
+ /**
333
+ * Unified I/O state dispatch with fallback when centralPlant is unavailable.
334
+ * @private
335
+ */
336
+ }, {
337
+ key: "_dispatchIoState",
338
+ value: function _dispatchIoState(attachmentId, stateId, value, parentUuid) {
339
+ var _this$sceneViewer3, _this$_stateAdapter, _getIoBehaviorManager, _this$sceneViewer4;
340
+ var cp = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.centralPlant;
341
+ if (cp && typeof cp._dispatchIoState === 'function') {
342
+ cp._dispatchIoState(attachmentId, stateId, value, parentUuid);
343
+ return;
344
+ }
345
+ var scopedKey = getScopedAttachmentKey(attachmentId, parentUuid);
346
+ (_this$_stateAdapter = this._stateAdapter) === null || _this$_stateAdapter === void 0 || _this$_stateAdapter.setState(scopedKey, stateId, value);
347
+ (_getIoBehaviorManager = getIoBehaviorManager(this.sceneViewer)) === null || _getIoBehaviorManager === void 0 || _getIoBehaviorManager.triggerState(attachmentId, stateId, value, parentUuid);
348
+ (_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 || _this$sceneViewer4.emit('io-device-state-changed', {
349
+ attachmentId: attachmentId,
350
+ stateId: stateId,
351
+ value: value,
352
+ parentUuid: parentUuid || null
353
+ });
306
354
  }
307
355
 
308
356
  /**
@@ -335,7 +383,6 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
335
383
  value: function update() {
336
384
  if (!this.tooltipEl || !this.selectedObject) return;
337
385
  this._positionTooltip();
338
- this._refreshStateDisplays();
339
386
  }
340
387
 
341
388
  /**
@@ -394,21 +441,6 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
394
441
  this._styleInjected = false;
395
442
  }
396
443
 
397
- /**
398
- * Generate a scoped attachment key that includes the parent component UUID.
399
- * This ensures each instance of a smart component has isolated IO device state.
400
- * @param {string} attachmentId - The original attachment ID from the component data
401
- * @param {string|null} parentUuid - The UUID of the parent smart component instance
402
- * @returns {string} A scoped key in the format "parentUuid::attachmentId" or just attachmentId if no parent
403
- * @private
404
- */
405
- }, {
406
- key: "_getScopedAttachmentKey",
407
- value: function _getScopedAttachmentKey(attachmentId, parentUuid) {
408
- if (!parentUuid) return attachmentId;
409
- return "".concat(parentUuid, "::").concat(attachmentId);
410
- }
411
-
412
444
  /**
413
445
  * Gather I/O device children from a component's Three.js hierarchy.
414
446
  * Returns richer data including attachmentId and data point definitions.
@@ -424,12 +456,11 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
424
456
  object.traverse(function (child) {
425
457
  var _child$userData;
426
458
  if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'io-device') {
427
- var _this3$sceneViewer$ma, _this3$sceneViewer;
428
459
  var attachmentId = child.userData.attachmentId || '';
429
460
 
430
461
  // Use only data points from the animate window (behaviorConfig).
431
462
  // The static ioConfig.states[] snapshot on userData is intentionally ignored.
432
- var dataPoints = (_this3$sceneViewer$ma = (_this3$sceneViewer = _this3.sceneViewer) === null || _this3$sceneViewer === void 0 || (_this3$sceneViewer = _this3$sceneViewer.managers) === null || _this3$sceneViewer === void 0 || (_this3$sceneViewer = _this3$sceneViewer.ioBehaviorManager) === null || _this3$sceneViewer === void 0 ? void 0 : _this3$sceneViewer.getAnimationDataPoints(parentUuid, attachmentId)) !== null && _this3$sceneViewer$ma !== void 0 ? _this3$sceneViewer$ma : [];
463
+ var dataPoints = resolveDataPoints(parentUuid, attachmentId, child.userData, getIoBehaviorManager(_this3.sceneViewer));
433
464
 
434
465
  // When data points come from behaviorConfig they already carry direction:'input'.
435
466
  // Pass null so _buildDataPointRow uses the per-dp direction instead of the
@@ -439,7 +470,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
439
470
  label: child.userData.attachmentLabel || child.name || child.userData.deviceId || 'Unknown Device',
440
471
  deviceId: child.userData.deviceId || '',
441
472
  attachmentId: attachmentId,
442
- scopedAttachmentId: _this3._getScopedAttachmentKey(attachmentId, parentUuid),
473
+ scopedAttachmentId: getScopedAttachmentKey(attachmentId, parentUuid),
443
474
  dataPoints: dataPoints,
444
475
  direction: deviceDirection
445
476
  });
@@ -585,11 +616,11 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
585
616
  }, {
586
617
  key: "_positionTooltip",
587
618
  value: function _positionTooltip() {
588
- var _this$sceneViewer4, _this$sceneViewer5;
619
+ var _this$sceneViewer5, _this$sceneViewer6;
589
620
  if (!this.tooltipEl || !this.selectedObject) return;
590
621
  var container = this._getContainer();
591
- var camera = (_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 ? void 0 : _this$sceneViewer4.camera;
592
- var renderer = (_this$sceneViewer5 = this.sceneViewer) === null || _this$sceneViewer5 === void 0 ? void 0 : _this$sceneViewer5.renderer;
622
+ var camera = (_this$sceneViewer5 = this.sceneViewer) === null || _this$sceneViewer5 === void 0 ? void 0 : _this$sceneViewer5.camera;
623
+ var renderer = (_this$sceneViewer6 = this.sceneViewer) === null || _this$sceneViewer6 === void 0 ? void 0 : _this$sceneViewer6.renderer;
593
624
  if (!container || !camera || !renderer) return;
594
625
 
595
626
  // Compute bounding box to position above the component
@@ -626,8 +657,8 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
626
657
  }, {
627
658
  key: "_getContainer",
628
659
  value: function _getContainer() {
629
- var _this$sceneViewer6;
630
- return ((_this$sceneViewer6 = this.sceneViewer) === null || _this$sceneViewer6 === void 0 || (_this$sceneViewer6 = _this$sceneViewer6.renderer) === null || _this$sceneViewer6 === void 0 || (_this$sceneViewer6 = _this$sceneViewer6.domElement) === null || _this$sceneViewer6 === void 0 ? void 0 : _this$sceneViewer6.parentElement) || null;
660
+ var _this$sceneViewer7;
661
+ return ((_this$sceneViewer7 = this.sceneViewer) === null || _this$sceneViewer7 === void 0 || (_this$sceneViewer7 = _this$sceneViewer7.renderer) === null || _this$sceneViewer7 === void 0 || (_this$sceneViewer7 = _this$sceneViewer7.domElement) === null || _this$sceneViewer7 === void 0 ? void 0 : _this$sceneViewer7.parentElement) || null;
631
662
  }
632
663
 
633
664
  // -----------------------------------------------------------------------
@@ -667,10 +698,9 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
667
698
  var currentVal = (_ref3 = (_this$_stateAdapter$g = (_this$_stateAdapter2 = this._stateAdapter) === null || _this$_stateAdapter2 === void 0 ? void 0 : _this$_stateAdapter2.getState(scopedAttachmentId, dpId)) !== null && _this$_stateAdapter$g !== void 0 ? _this$_stateAdapter$g : dp.defaultValue) !== null && _ref3 !== void 0 ? _ref3 : null;
668
699
  if (isInput) {
669
700
  var ctrl = this._buildInputControl(dp, currentVal, function (newVal) {
670
- var _this5$_stateAdapter, _this5$selectedObject, _this5$sceneViewer;
671
- (_this5$_stateAdapter = _this5._stateAdapter) === null || _this5$_stateAdapter === void 0 || _this5$_stateAdapter.setState(scopedAttachmentId, dpId, newVal);
701
+ var _this5$selectedObject;
672
702
  var parentUuid = ((_this5$selectedObject = _this5.selectedObject) === null || _this5$selectedObject === void 0 ? void 0 : _this5$selectedObject.uuid) || null;
673
- (_this5$sceneViewer = _this5.sceneViewer) === null || _this5$sceneViewer === void 0 || (_this5$sceneViewer = _this5$sceneViewer.managers) === null || _this5$sceneViewer === void 0 || (_this5$sceneViewer = _this5$sceneViewer.ioBehaviorManager) === null || _this5$sceneViewer === void 0 || _this5$sceneViewer.triggerState(originalAttachmentId || scopedAttachmentId, dpId, newVal, parentUuid);
703
+ _this5._dispatchIoState(originalAttachmentId || scopedAttachmentId, dpId, newVal, parentUuid);
674
704
  });
675
705
  row.appendChild(ctrl);
676
706
  this._stateElements.set(key, {
@@ -679,9 +709,9 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
679
709
  isInput: true
680
710
  });
681
711
  } else {
682
- var _dp$stateConfig2;
712
+ var _dp$stateConfig4;
683
713
  // unit suffix (optional, shown between name and badge)
684
- var unit = (_dp$stateConfig2 = dp.stateConfig) === null || _dp$stateConfig2 === void 0 ? void 0 : _dp$stateConfig2.unit;
714
+ var unit = (_dp$stateConfig4 = dp.stateConfig) === null || _dp$stateConfig4 === void 0 ? void 0 : _dp$stateConfig4.unit;
685
715
  if (unit) {
686
716
  var unitEl = document.createElement('span');
687
717
  unitEl.className = 'cp-tooltip__dp-unit';