@2112-lab/central-plant 0.3.21 → 0.3.22

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.
@@ -0,0 +1,398 @@
1
+ import { inherits as _inherits, createClass as _createClass, createForOfIteratorHelper as _createForOfIteratorHelper, superPropGet as _superPropGet, toConsumableArray as _toConsumableArray, classCallCheck as _classCallCheck, callSuper as _callSuper } from '../../../_virtual/_rollupPluginBabelHelpers.js';
2
+ import * as THREE from 'three';
3
+ import { BaseDisposable } from '../../core/baseDisposable.js';
4
+
5
+ var IoAnimationManager = /*#__PURE__*/function (_BaseDisposable) {
6
+ function IoAnimationManager(sceneViewer) {
7
+ var _this;
8
+ _classCallCheck(this, IoAnimationManager);
9
+ _this = _callSuper(this, IoAnimationManager);
10
+ _this.sceneViewer = sceneViewer;
11
+
12
+ /**
13
+ * Map: `${parentUuid}::${attachmentId}` → Array<{
14
+ * anim: Object,
15
+ * mesh: THREE.Object3D,
16
+ * origPos: THREE.Vector3,
17
+ * origRot: THREE.Euler
18
+ * }>
19
+ */
20
+ _this._entries = new Map();
21
+ return _this;
22
+ }
23
+
24
+ // ─────────────────────────────────────────────────────────────────────────
25
+ // PUBLIC API
26
+ // ─────────────────────────────────────────────────────────────────────────
27
+
28
+ /**
29
+ * Register animation entries for one attached I/O device.
30
+ * Should be called after the device GLB has been merged into the scene
31
+ * so that mesh references are live.
32
+ *
33
+ * @param {string} attachmentId - The attachment key (e.g. 'attch-switch-01')
34
+ * @param {Object|Array} animationConfig - Serialized config; either the full object
35
+ * { animations: [...] } or a plain array of animation entries.
36
+ * @param {THREE.Object3D} deviceModelRoot - The device's root Object3D as added to the scene
37
+ * @param {string} parentUuid - UUID of the host component Object3D
38
+ */
39
+ _inherits(IoAnimationManager, _BaseDisposable);
40
+ return _createClass(IoAnimationManager, [{
41
+ key: "loadAnimations",
42
+ value: function loadAnimations(attachmentId, animationConfig, deviceModelRoot, parentUuid) {
43
+ var _animationConfig$anim;
44
+ if (!animationConfig || !deviceModelRoot) return;
45
+ var anims = Array.isArray(animationConfig) ? animationConfig : (_animationConfig$anim = animationConfig.animations) !== null && _animationConfig$anim !== void 0 ? _animationConfig$anim : [];
46
+ if (!anims.length) return;
47
+ var key = this._key(parentUuid, attachmentId);
48
+ var entries = [];
49
+ var _iterator = _createForOfIteratorHelper(anims),
50
+ _step;
51
+ try {
52
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
53
+ var anim = _step.value;
54
+ var mesh = this._resolveMesh(anim, deviceModelRoot);
55
+ if (!mesh) {
56
+ console.warn("[IoAnimationManager] Could not find mesh for animation \"".concat(anim.name || anim.stateVariable, "\" (uuid: ").concat(anim.meshUuid, ", name: \"").concat(anim.meshName, "\")"));
57
+ continue;
58
+ }
59
+ entries.push({
60
+ anim: anim,
61
+ mesh: mesh,
62
+ origPos: mesh.position.clone(),
63
+ origRot: mesh.rotation.clone()
64
+ });
65
+ }
66
+ } catch (err) {
67
+ _iterator.e(err);
68
+ } finally {
69
+ _iterator.f();
70
+ }
71
+ if (entries.length) {
72
+ this._entries.set(key, entries);
73
+ console.log("[IoAnimationManager] Loaded ".concat(entries.length, " animation(s) for attachment \"").concat(attachmentId, "\" (parent: ").concat(parentUuid, ")"));
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Apply animations triggered by an IO device state change.
79
+ * Should be called in parallel with BehaviorManager.triggerState().
80
+ *
81
+ * @param {string} attachmentId - Raw attachment key (not scoped)
82
+ * @param {string} dataPointId - The data point / state variable id that changed
83
+ * @param {*} value - New state value
84
+ * @param {string} parentUuid - UUID of the host component
85
+ */
86
+ }, {
87
+ key: "triggerState",
88
+ value: function triggerState(attachmentId, dataPointId, value, parentUuid) {
89
+ var key = this._key(parentUuid, attachmentId);
90
+ var entries = this._entries.get(key);
91
+ if (!(entries !== null && entries !== void 0 && entries.length)) return;
92
+ var _iterator2 = _createForOfIteratorHelper(entries),
93
+ _step2;
94
+ try {
95
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
96
+ var entry = _step2.value;
97
+ if (entry.anim.stateVariable !== dataPointId) continue;
98
+ this._applyAnimation(entry, value);
99
+ }
100
+ } catch (err) {
101
+ _iterator2.e(err);
102
+ } finally {
103
+ _iterator2.f();
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Remove all animation entries associated with a given host component.
109
+ * Call when a component is removed from the scene.
110
+ *
111
+ * @param {string} parentUuid
112
+ */
113
+ }, {
114
+ key: "unloadForComponent",
115
+ value: function unloadForComponent(parentUuid) {
116
+ var prefix = "".concat(parentUuid, "::");
117
+ var _iterator3 = _createForOfIteratorHelper(this._entries.keys()),
118
+ _step3;
119
+ try {
120
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
121
+ var key = _step3.value;
122
+ if (key.startsWith(prefix)) {
123
+ this._entries.delete(key);
124
+ }
125
+ }
126
+ } catch (err) {
127
+ _iterator3.e(err);
128
+ } finally {
129
+ _iterator3.f();
130
+ }
131
+ }
132
+ }, {
133
+ key: "dispose",
134
+ value: function dispose() {
135
+ this._entries.clear();
136
+ _superPropGet(IoAnimationManager, "dispose", this, 3)([]);
137
+ }
138
+
139
+ // ─────────────────────────────────────────────────────────────────────────
140
+ // PRIVATE HELPERS
141
+ // ─────────────────────────────────────────────────────────────────────────
142
+ }, {
143
+ key: "_key",
144
+ value: function _key(parentUuid, attachmentId) {
145
+ return "".concat(parentUuid, "::").concat(attachmentId);
146
+ }
147
+
148
+ /**
149
+ * Find the mesh inside `root` using UUID first, then name as fallback.
150
+ * GLTFLoader assigns fresh UUIDs on every load, so name is the reliable key.
151
+ * @param {Object} anim
152
+ * @param {THREE.Object3D} root
153
+ * @returns {THREE.Object3D|null}
154
+ */
155
+ }, {
156
+ key: "_resolveMesh",
157
+ value: function _resolveMesh(anim, root) {
158
+ var found = null;
159
+ root.traverse(function (obj) {
160
+ if (found) return;
161
+
162
+ // Prefer UUID match (works when the device was cloned from a cached instance
163
+ // whose UUIDs were preserved)
164
+ if (anim.meshUuid && obj.uuid === anim.meshUuid) {
165
+ found = obj;
166
+ return;
167
+ }
168
+
169
+ // Reliable fallback: mesh name
170
+ if (anim.meshName && obj.name === anim.meshName) {
171
+ found = obj;
172
+ }
173
+ });
174
+ return found;
175
+ }
176
+
177
+ /**
178
+ * Resolve which mapping row to use and apply all declared transform types.
179
+ * @param {{ anim, mesh, origPos, origRot }} entry
180
+ * @param {*} value - Current state value
181
+ */
182
+ }, {
183
+ key: "_applyAnimation",
184
+ value: function _applyAnimation(entry, value) {
185
+ var anim = entry.anim,
186
+ mesh = entry.mesh,
187
+ origPos = entry.origPos,
188
+ origRot = entry.origRot;
189
+ var mapping = this._resolveMapping(anim, value);
190
+ if (!mapping) return;
191
+ var types = anim.transformTypes || [];
192
+ var _iterator4 = _createForOfIteratorHelper(types),
193
+ _step4;
194
+ try {
195
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
196
+ var type = _step4.value;
197
+ if (type === 'translation') {
198
+ this._applyTranslation(mesh, origPos, mapping.transform);
199
+ } else if (type === 'rotation') {
200
+ this._applyRotation(mesh, origPos, origRot, anim, mapping.rotationTransform);
201
+ } else if (type === 'color') {
202
+ this._applyColor(mesh, mapping.colorTransform);
203
+ }
204
+ }
205
+ } catch (err) {
206
+ _iterator4.e(err);
207
+ } finally {
208
+ _iterator4.f();
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Find the mapping row that matches `value` for the given animation entry.
214
+ *
215
+ * - binary / enum: find where mapping.stateValue == value (loose equality so
216
+ * JSON-deserialised "true" matches boolean true)
217
+ * - continuous: linear interpolation between ordered anchor points
218
+ *
219
+ * @returns {Object|null} The matched/interpolated mapping row, or null.
220
+ */
221
+ }, {
222
+ key: "_resolveMapping",
223
+ value: function _resolveMapping(anim, value) {
224
+ var stateType = anim.stateType,
225
+ mappings = anim.mappings;
226
+ if (!(mappings !== null && mappings !== void 0 && mappings.length)) return null;
227
+ if (stateType === 'binary' || stateType === 'enum') {
228
+ var _mappings$find;
229
+ // eslint-disable-next-line eqeqeq
230
+ return (_mappings$find = mappings.find(function (m) {
231
+ return m.stateValue == value;
232
+ })) !== null && _mappings$find !== void 0 ? _mappings$find : null;
233
+ }
234
+ if (stateType === 'continuous') {
235
+ var num = Number(value);
236
+ if (isNaN(num)) return null;
237
+
238
+ // Sort anchors by numeric stateValue
239
+ var sorted = _toConsumableArray(mappings).filter(function (m) {
240
+ return m.stateValue != null && !isNaN(Number(m.stateValue));
241
+ }).sort(function (a, b) {
242
+ return Number(a.stateValue) - Number(b.stateValue);
243
+ });
244
+ if (!sorted.length) return null;
245
+ if (sorted.length === 1) return sorted[0];
246
+
247
+ // Clamp to range
248
+ if (num <= Number(sorted[0].stateValue)) return sorted[0];
249
+ if (num >= Number(sorted[sorted.length - 1].stateValue)) return sorted[sorted.length - 1];
250
+
251
+ // Find surrounding anchors and interpolate
252
+ for (var i = 0; i < sorted.length - 1; i++) {
253
+ var lo = sorted[i];
254
+ var hi = sorted[i + 1];
255
+ var loVal = Number(lo.stateValue);
256
+ var hiVal = Number(hi.stateValue);
257
+ if (num >= loVal && num <= hiVal) {
258
+ var t = (num - loVal) / (hiVal - loVal);
259
+ return this._lerpMapping(lo, hi, t);
260
+ }
261
+ }
262
+ }
263
+ return null;
264
+ }
265
+
266
+ /**
267
+ * Linear-interpolate between two mapping rows.
268
+ * @param {Object} lo - lower anchor mapping
269
+ * @param {Object} hi - upper anchor mapping
270
+ * @param {number} t - 0..1
271
+ */
272
+ }, {
273
+ key: "_lerpMapping",
274
+ value: function _lerpMapping(lo, hi, t) {
275
+ var _lo$transform$x, _lo$transform, _hi$transform$x, _hi$transform, _lo$transform$y, _lo$transform2, _hi$transform$y, _hi$transform2, _lo$transform$z, _lo$transform3, _hi$transform$z, _hi$transform3;
276
+ var lerp = function lerp(a, b) {
277
+ return a + (b - a) * t;
278
+ };
279
+ var transform = {
280
+ x: lerp((_lo$transform$x = (_lo$transform = lo.transform) === null || _lo$transform === void 0 ? void 0 : _lo$transform.x) !== null && _lo$transform$x !== void 0 ? _lo$transform$x : 0, (_hi$transform$x = (_hi$transform = hi.transform) === null || _hi$transform === void 0 ? void 0 : _hi$transform.x) !== null && _hi$transform$x !== void 0 ? _hi$transform$x : 0),
281
+ y: lerp((_lo$transform$y = (_lo$transform2 = lo.transform) === null || _lo$transform2 === void 0 ? void 0 : _lo$transform2.y) !== null && _lo$transform$y !== void 0 ? _lo$transform$y : 0, (_hi$transform$y = (_hi$transform2 = hi.transform) === null || _hi$transform2 === void 0 ? void 0 : _hi$transform2.y) !== null && _hi$transform$y !== void 0 ? _hi$transform$y : 0),
282
+ z: lerp((_lo$transform$z = (_lo$transform3 = lo.transform) === null || _lo$transform3 === void 0 ? void 0 : _lo$transform3.z) !== null && _lo$transform$z !== void 0 ? _lo$transform$z : 0, (_hi$transform$z = (_hi$transform3 = hi.transform) === null || _hi$transform3 === void 0 ? void 0 : _hi$transform3.z) !== null && _hi$transform$z !== void 0 ? _hi$transform$z : 0)
283
+ };
284
+ var rotationTransform = lerp(typeof lo.rotationTransform === 'number' ? lo.rotationTransform : 0, typeof hi.rotationTransform === 'number' ? hi.rotationTransform : 0);
285
+
286
+ // Color interpolation: convert hex → RGB components → lerp → back to hex
287
+ var colorTransform = this._lerpHex(lo.colorTransform, hi.colorTransform, t);
288
+ return {
289
+ stateValue: null,
290
+ transform: transform,
291
+ rotationTransform: rotationTransform,
292
+ colorTransform: colorTransform
293
+ };
294
+ }
295
+
296
+ /**
297
+ * Interpolate between two hex colour strings.
298
+ */
299
+ }, {
300
+ key: "_lerpHex",
301
+ value: function _lerpHex(hexA, hexB, t) {
302
+ try {
303
+ var ca = new THREE.Color(hexA);
304
+ var cb = new THREE.Color(hexB);
305
+ ca.lerp(cb, t);
306
+ return "#".concat(ca.getHexString());
307
+ } catch (_unused) {
308
+ return hexA !== null && hexA !== void 0 ? hexA : '#ffffff';
309
+ }
310
+ }
311
+
312
+ // ─────────────────────────────────────────────────────────────────────────
313
+ // TRANSFORM APPLIERS
314
+ // ─────────────────────────────────────────────────────────────────────────
315
+
316
+ /**
317
+ * Apply a position delta relative to the mesh's original position.
318
+ * @param {THREE.Object3D} mesh
319
+ * @param {THREE.Vector3} origPos
320
+ * @param {{ x, y, z }} transform - Deltas
321
+ */
322
+ }, {
323
+ key: "_applyTranslation",
324
+ value: function _applyTranslation(mesh, origPos, transform) {
325
+ var _transform$x, _transform$y, _transform$z;
326
+ if (!transform) return;
327
+ mesh.position.set(origPos.x + ((_transform$x = transform.x) !== null && _transform$x !== void 0 ? _transform$x : 0), origPos.y + ((_transform$y = transform.y) !== null && _transform$y !== void 0 ? _transform$y : 0), origPos.z + ((_transform$z = transform.z) !== null && _transform$z !== void 0 ? _transform$z : 0));
328
+ }
329
+
330
+ /**
331
+ * Apply a rotation around an arbitrary pivot point in device-local space,
332
+ * optionally also displacing the mesh position to simulate orbital motion.
333
+ *
334
+ * Math (all in device-local space):
335
+ * pivot = rotAxisOffset
336
+ * delta = origPos - pivot
337
+ * newDelta = rotate(delta, angle, axis)
338
+ * newPos = pivot + newDelta
339
+ * newRot[axis] = origRot[axis] + angle
340
+ *
341
+ * @param {THREE.Object3D} mesh
342
+ * @param {THREE.Vector3} origPos
343
+ * @param {THREE.Euler} origRot
344
+ * @param {Object} anim
345
+ * @param {number} angleDeg - Degrees
346
+ */
347
+ }, {
348
+ key: "_applyRotation",
349
+ value: function _applyRotation(mesh, origPos, origRot, anim, angleDeg) {
350
+ var _anim$rotAxis, _anim$rotAxisOffset, _off$x, _off$y, _off$z;
351
+ var angle = THREE.MathUtils.degToRad(typeof angleDeg === 'number' ? angleDeg : 0);
352
+ var axis = ((_anim$rotAxis = anim.rotAxis) !== null && _anim$rotAxis !== void 0 ? _anim$rotAxis : 'x').toLowerCase();
353
+ var off = (_anim$rotAxisOffset = anim.rotAxisOffset) !== null && _anim$rotAxisOffset !== void 0 ? _anim$rotAxisOffset : {
354
+ x: 0,
355
+ y: 0,
356
+ z: 0
357
+ };
358
+
359
+ // Unit vector for the chosen axis
360
+ var axisVec = new THREE.Vector3(axis === 'x' ? 1 : 0, axis === 'y' ? 1 : 0, axis === 'z' ? 1 : 0);
361
+ var pivot = new THREE.Vector3((_off$x = off.x) !== null && _off$x !== void 0 ? _off$x : 0, (_off$y = off.y) !== null && _off$y !== void 0 ? _off$y : 0, (_off$z = off.z) !== null && _off$z !== void 0 ? _off$z : 0);
362
+ var delta = origPos.clone().sub(pivot);
363
+ delta.applyAxisAngle(axisVec, angle);
364
+ mesh.position.copy(pivot).add(delta);
365
+ mesh.rotation[axis] = origRot[axis] + angle;
366
+ }
367
+
368
+ /**
369
+ * Apply a colour to all Mesh descendants of `mesh`.
370
+ * Creates a cloned material per mesh on first call to avoid shared-material
371
+ * cross-contamination between different device instances.
372
+ *
373
+ * @param {THREE.Object3D} mesh
374
+ * @param {string} colorHex - e.g. '#ff0000'
375
+ */
376
+ }, {
377
+ key: "_applyColor",
378
+ value: function _applyColor(mesh, colorHex) {
379
+ if (!colorHex) return;
380
+ mesh.traverse(function (obj) {
381
+ if (!obj.isMesh || !obj.material) return;
382
+
383
+ // Ensure this mesh has its own material instance
384
+ if (!obj.userData._materialCloned) {
385
+ obj.material = obj.material.clone();
386
+ obj.userData._materialCloned = true;
387
+ }
388
+ try {
389
+ obj.material.color.set(colorHex);
390
+ } catch (e) {
391
+ // Material may not have a color property (e.g. MeshDepthMaterial)
392
+ }
393
+ });
394
+ }
395
+ }]);
396
+ }(BaseDisposable);
397
+
398
+ export { IoAnimationManager };
@@ -105,7 +105,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
105
105
  }, {
106
106
  key: "toggleIODeviceBinaryState",
107
107
  value: function toggleIODeviceBinaryState(ioDeviceObject) {
108
- var _ref, _this$sceneViewer;
108
+ var _ref, _this$sceneViewer, _this$sceneViewer2;
109
109
  if (!ioDeviceObject || !this._stateAdapter) return;
110
110
  var ud = ioDeviceObject.userData;
111
111
  var attachmentId = ud === null || ud === void 0 ? void 0 : ud.attachmentId;
@@ -140,6 +140,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
140
140
  var newVal = !Boolean(currentVal);
141
141
  this._stateAdapter.setState(scopedAttachmentId, dpId, newVal);
142
142
  (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.managers) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.behaviorManager) === null || _this$sceneViewer === void 0 || _this$sceneViewer.triggerState(attachmentId, dpId, newVal, parentUuid);
143
+ (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.managers) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.ioAnimationManager) === null || _this$sceneViewer2 === void 0 || _this$sceneViewer2.triggerState(attachmentId, dpId, newVal, parentUuid);
143
144
  console.log("\uD83D\uDD04 [IODevice] Toggled ".concat(scopedAttachmentId, ".").concat(dpId, ": ").concat(currentVal, " \u2192 ").concat(newVal));
144
145
  }
145
146
 
@@ -413,11 +414,11 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
413
414
  }, {
414
415
  key: "_positionTooltip",
415
416
  value: function _positionTooltip() {
416
- var _this$sceneViewer2, _this$sceneViewer3;
417
+ var _this$sceneViewer3, _this$sceneViewer4;
417
418
  if (!this.tooltipEl || !this.selectedObject) return;
418
419
  var container = this._getContainer();
419
- var camera = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.camera;
420
- var renderer = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.renderer;
420
+ var camera = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.camera;
421
+ var renderer = (_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 ? void 0 : _this$sceneViewer4.renderer;
421
422
  if (!container || !camera || !renderer) return;
422
423
 
423
424
  // Compute bounding box to position above the component
@@ -454,8 +455,8 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
454
455
  }, {
455
456
  key: "_getContainer",
456
457
  value: function _getContainer() {
457
- var _this$sceneViewer4;
458
- return ((_this$sceneViewer4 = this.sceneViewer) === null || _this$sceneViewer4 === void 0 || (_this$sceneViewer4 = _this$sceneViewer4.renderer) === null || _this$sceneViewer4 === void 0 || (_this$sceneViewer4 = _this$sceneViewer4.domElement) === null || _this$sceneViewer4 === void 0 ? void 0 : _this$sceneViewer4.parentElement) || null;
458
+ var _this$sceneViewer5;
459
+ return ((_this$sceneViewer5 = this.sceneViewer) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.renderer) === null || _this$sceneViewer5 === void 0 || (_this$sceneViewer5 = _this$sceneViewer5.domElement) === null || _this$sceneViewer5 === void 0 ? void 0 : _this$sceneViewer5.parentElement) || null;
459
460
  }
460
461
 
461
462
  // -----------------------------------------------------------------------
@@ -495,7 +496,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
495
496
  var currentVal = (_ref2 = (_this$_stateAdapter$g = (_this$_stateAdapter = this._stateAdapter) === null || _this$_stateAdapter === void 0 ? void 0 : _this$_stateAdapter.getState(scopedAttachmentId, dpId)) !== null && _this$_stateAdapter$g !== void 0 ? _this$_stateAdapter$g : dp.defaultValue) !== null && _ref2 !== void 0 ? _ref2 : null;
496
497
  if (isInput) {
497
498
  var ctrl = this._buildInputControl(dp, currentVal, function (newVal) {
498
- var _this4$_stateAdapter, _this4$selectedObject, _this4$sceneViewer;
499
+ var _this4$_stateAdapter, _this4$selectedObject, _this4$sceneViewer, _this4$sceneViewer2;
499
500
  (_this4$_stateAdapter = _this4._stateAdapter) === null || _this4$_stateAdapter === void 0 || _this4$_stateAdapter.setState(scopedAttachmentId, dpId, newVal);
500
501
  // Also fire BehaviorManager so any wired behaviors react immediately.
501
502
  // Pass the parent component UUID so behaviors scoped to a specific instance
@@ -503,6 +504,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
503
504
  // Use originalAttachmentId for behavior triggering as behaviors are keyed by original ID
504
505
  var parentUuid = ((_this4$selectedObject = _this4.selectedObject) === null || _this4$selectedObject === void 0 ? void 0 : _this4$selectedObject.uuid) || null;
505
506
  (_this4$sceneViewer = _this4.sceneViewer) === null || _this4$sceneViewer === void 0 || (_this4$sceneViewer = _this4$sceneViewer.managers) === null || _this4$sceneViewer === void 0 || (_this4$sceneViewer = _this4$sceneViewer.behaviorManager) === null || _this4$sceneViewer === void 0 || _this4$sceneViewer.triggerState(originalAttachmentId || scopedAttachmentId, dpId, newVal, parentUuid);
507
+ (_this4$sceneViewer2 = _this4.sceneViewer) === null || _this4$sceneViewer2 === void 0 || (_this4$sceneViewer2 = _this4$sceneViewer2.managers) === null || _this4$sceneViewer2 === void 0 || (_this4$sceneViewer2 = _this4$sceneViewer2.ioAnimationManager) === null || _this4$sceneViewer2 === void 0 || _this4$sceneViewer2.triggerState(originalAttachmentId || scopedAttachmentId, dpId, newVal, parentUuid);
506
508
  });
507
509
  row.appendChild(ctrl);
508
510
  this._stateElements.set(key, {