@2112-lab/central-plant 0.3.36 → 0.3.38
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.
- package/dist/bundle/index.js +62 -18
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/behaviors/IoBehaviorManager.js +58 -15
- package/dist/cjs/src/managers/scene/componentTooltipManager.js +1 -1
- package/dist/cjs/src/managers/scene/sceneExportManager.js +2 -1
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/managers/behaviors/IoBehaviorManager.js +58 -15
- package/dist/esm/src/managers/scene/componentTooltipManager.js +1 -1
- package/dist/esm/src/managers/scene/sceneExportManager.js +2 -1
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -11772,7 +11772,8 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
11772
11772
|
|
|
11773
11773
|
// Copy only essential userData properties (libraryId, objectType, direction, group)
|
|
11774
11774
|
Object.keys(threeObject.userData).forEach(function (key) {
|
|
11775
|
-
|
|
11775
|
+
// Skip runtime/internal keys (e.g. _filteredBBoxCache from boundingBoxUtils)
|
|
11776
|
+
if (!excludedKeys.has(key) && !key.startsWith('_')) {
|
|
11776
11777
|
jsonObject.userData[key] = threeObject.userData[key];
|
|
11777
11778
|
}
|
|
11778
11779
|
});
|
|
@@ -36542,7 +36543,7 @@ var SceneTooltipsManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
36542
36543
|
// ---------------------------------------------------------------------------
|
|
36543
36544
|
// Inline styles (injected once into the document head)
|
|
36544
36545
|
// ---------------------------------------------------------------------------
|
|
36545
|
-
var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n}\n\n.cp-tooltip__card {\n background: rgba(
|
|
36546
|
+
var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n color-scheme: light;\n}\n\n.cp-tooltip__card {\n background: rgba(255, 255, 255, 0.97);\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__header {\n padding: 10px 14px;\n font-weight: 600;\n font-size: 14px;\n color: #2c3e50;\n background: rgba(0, 0, 0, 0.02);\n border-bottom: 1px solid rgba(0, 0, 0, 0.08);\n letter-spacing: 0.2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 I/O Devices section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__io-section {\n position: relative;\n}\n\n.cp-tooltip__io-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px;\n color: #666666;\n cursor: pointer;\n transition: background 0.12s ease, color 0.12s ease;\n}\n\n.cp-tooltip__io-trigger:hover {\n background: rgba(0, 0, 0, 0.04);\n color: #333333;\n}\n\n.cp-tooltip__io-trigger-label {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n font-weight: 500;\n}\n\n.cp-tooltip__io-arrow {\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__io-arrow {\n transform: rotate(90deg);\n}\n\n/* \u2500\u2500 Device list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__device-list {\n max-height: 0;\n overflow: hidden;\n transition: max-height 0.25s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__device-list {\n max-height: 300px;\n}\n\n.cp-tooltip__device-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 14px 6px 20px;\n color: #555555;\n font-size: 12px;\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n transition: background 0.1s ease;\n}\n\n.cp-tooltip__device-item:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n\n.cp-tooltip__device-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #1976d2;\n flex-shrink: 0;\n}\n\n.cp-tooltip__device-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__no-devices {\n padding: 8px 14px;\n color: #888888;\n font-size: 12px;\n font-style: italic;\n}\n\n/* \u2500\u2500 Caret arrow pointing down \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__caret {\n width: 0;\n height: 0;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 7px solid rgba(255, 255, 255, 0.97);\n margin: 0 auto;\n position: relative;\n top: -1px;\n filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.1));\n}\n\n/* \u2500\u2500 Data point rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__dp-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 4px 12px 4px 30px;\n font-size: 11.5px;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n min-height: 24px;\n}\n\n.cp-tooltip__dp-name {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: #666666;\n}\n\n/* Read-only state badge */\n.cp-tooltip__dp-badge {\n font-size: 10.5px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 8px;\n flex-shrink: 0;\n background: #f0f2f5;\n color: #666666;\n min-width: 30px;\n text-align: center;\n letter-spacing: 0.2px;\n}\n\n.cp-tooltip__dp-badge.active {\n background: rgba(76, 175, 80, 0.15);\n color: #2e7d32;\n}\n\n/* Binary toggle button */\n.cp-tooltip__dp-toggle {\n font-size: 10.5px;\n font-weight: 600;\n padding: 2px 9px;\n border-radius: 8px;\n flex-shrink: 0;\n border: 1px solid #dddddd;\n background: #f8f9fa;\n color: #555555;\n cursor: pointer;\n min-width: 40px;\n text-align: center;\n transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n}\n\n.cp-tooltip__dp-toggle:hover {\n background: #eeeeee;\n border-color: #cccccc;\n}\n\n.cp-tooltip__dp-toggle.on {\n background: rgba(76, 175, 80, 0.15);\n border-color: rgba(76, 175, 80, 0.45);\n color: #2e7d32;\n}\n\n/* Number / float input */\n.cp-tooltip__dp-input {\n width: 62px;\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 5px;\n text-align: right;\n outline: none;\n flex-shrink: 0;\n}\n\n.cp-tooltip__dp-input:focus {\n border-color: #1976d2;\n}\n\n/* Enum select */\n.cp-tooltip__dp-select {\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 4px;\n outline: none;\n flex-shrink: 0;\n max-width: 96px;\n cursor: pointer;\n}\n\n.cp-tooltip__dp-select:focus {\n border-color: #1976d2;\n}\n\n/* Unit suffix */\n.cp-tooltip__dp-unit {\n font-size: 10px;\n color: #888888;\n flex-shrink: 0;\n margin-left: -4px;\n}\n";
|
|
36546
36547
|
var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
36547
36548
|
/**
|
|
36548
36549
|
* @param {Object} sceneViewer - The sceneViewer instance
|
|
@@ -37474,6 +37475,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
37474
37475
|
entries.push({
|
|
37475
37476
|
anim: anim,
|
|
37476
37477
|
mesh: mesh,
|
|
37478
|
+
deviceModelRoot: deviceModelRoot,
|
|
37477
37479
|
origPos: mesh.position.clone(),
|
|
37478
37480
|
origRot: mesh.rotation.clone(),
|
|
37479
37481
|
origWorldPos: worldPos,
|
|
@@ -38224,13 +38226,9 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38224
38226
|
value: function _applyAnimation(entry, value) {
|
|
38225
38227
|
var anim = entry.anim,
|
|
38226
38228
|
mesh = entry.mesh,
|
|
38227
|
-
origPos = entry.origPos
|
|
38228
|
-
|
|
38229
|
-
|
|
38230
|
-
origWorldQuat = entry.origWorldQuat,
|
|
38231
|
-
origWorldCenter = entry.origWorldCenter,
|
|
38232
|
-
deviceWorldQuat = entry.deviceWorldQuat,
|
|
38233
|
-
viewerMaxDim = entry.viewerMaxDim;
|
|
38229
|
+
origPos = entry.origPos;
|
|
38230
|
+
entry.origRot;
|
|
38231
|
+
var viewerMaxDim = entry.viewerMaxDim;
|
|
38234
38232
|
var mapping = this._resolveMapping(anim, value);
|
|
38235
38233
|
if (!mapping) return;
|
|
38236
38234
|
var types = anim.transformTypes || [];
|
|
@@ -38242,7 +38240,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38242
38240
|
if (type === 'translation') {
|
|
38243
38241
|
this._applyTranslation(mesh, origPos, mapping.transform);
|
|
38244
38242
|
} else if (type === 'rotation') {
|
|
38245
|
-
this._applyRotation(
|
|
38243
|
+
this._applyRotation(entry, anim, mapping.rotationTransform, viewerMaxDim);
|
|
38246
38244
|
} else if (type === 'color') {
|
|
38247
38245
|
this._applyColor(mesh, mapping.colorTransform);
|
|
38248
38246
|
}
|
|
@@ -38386,25 +38384,71 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38386
38384
|
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));
|
|
38387
38385
|
}
|
|
38388
38386
|
|
|
38387
|
+
/**
|
|
38388
|
+
* Recompute world-space rest-pose transforms for a behavior entry using the
|
|
38389
|
+
* current parent/device world matrix. origPos/origRot are local rest pose and
|
|
38390
|
+
* stay valid after parent moves; world anchors must be derived at apply time.
|
|
38391
|
+
*
|
|
38392
|
+
* @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
|
|
38393
|
+
* @returns {{ origWorldPos: THREE.Vector3, origWorldQuat: THREE.Quaternion, origWorldCenter: THREE.Vector3, deviceWorldQuat: THREE.Quaternion }|null}
|
|
38394
|
+
*/
|
|
38395
|
+
}, {
|
|
38396
|
+
key: "_getRestWorldTransforms",
|
|
38397
|
+
value: function _getRestWorldTransforms(entry) {
|
|
38398
|
+
var mesh = entry.mesh,
|
|
38399
|
+
origPos = entry.origPos,
|
|
38400
|
+
origRot = entry.origRot,
|
|
38401
|
+
deviceModelRoot = entry.deviceModelRoot;
|
|
38402
|
+
if (!mesh || !origPos || !origRot) return null;
|
|
38403
|
+
var savedPos = mesh.position.clone();
|
|
38404
|
+
var savedQuat = mesh.quaternion.clone();
|
|
38405
|
+
mesh.position.copy(origPos);
|
|
38406
|
+
mesh.rotation.copy(origRot);
|
|
38407
|
+
mesh.updateMatrixWorld(true);
|
|
38408
|
+
var origWorldPos = new THREE__namespace.Vector3();
|
|
38409
|
+
mesh.getWorldPosition(origWorldPos);
|
|
38410
|
+
var origWorldQuat = new THREE__namespace.Quaternion();
|
|
38411
|
+
mesh.getWorldQuaternion(origWorldQuat);
|
|
38412
|
+
var box = new THREE__namespace.Box3().setFromObject(mesh);
|
|
38413
|
+
var origWorldCenter = new THREE__namespace.Vector3();
|
|
38414
|
+
if (!box.isEmpty()) box.getCenter(origWorldCenter);else origWorldCenter.copy(origWorldPos);
|
|
38415
|
+
var deviceWorldQuat = new THREE__namespace.Quaternion();
|
|
38416
|
+
if (deviceModelRoot) {
|
|
38417
|
+
deviceModelRoot.getWorldQuaternion(deviceWorldQuat);
|
|
38418
|
+
}
|
|
38419
|
+
mesh.position.copy(savedPos);
|
|
38420
|
+
mesh.quaternion.copy(savedQuat);
|
|
38421
|
+
return {
|
|
38422
|
+
origWorldPos: origWorldPos,
|
|
38423
|
+
origWorldQuat: origWorldQuat,
|
|
38424
|
+
origWorldCenter: origWorldCenter,
|
|
38425
|
+
deviceWorldQuat: deviceWorldQuat
|
|
38426
|
+
};
|
|
38427
|
+
}
|
|
38428
|
+
|
|
38389
38429
|
/**
|
|
38390
38430
|
* Apply a rotation around an arbitrary pivot point using world-space quaternion
|
|
38391
38431
|
* math matching the ReconstructionViewer's setMeshPreviewRotationAxis approach.
|
|
38392
38432
|
* This ensures the runtime axis/pivot matches what the user configured in the
|
|
38393
38433
|
* animation dialog, regardless of the device's parent transform in the scene.
|
|
38394
38434
|
*
|
|
38395
|
-
* @param {
|
|
38396
|
-
* @param {THREE.Vector3} origPos - local position at load time (unused, kept for signature compat)
|
|
38397
|
-
* @param {THREE.Euler} origRot - local rotation at load time (unused)
|
|
38435
|
+
* @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
|
|
38398
38436
|
* @param {Object} anim
|
|
38399
38437
|
* @param {number} angleDeg - Degrees
|
|
38400
|
-
* @param {
|
|
38401
|
-
* @param {THREE.Quaternion} origWorldQuat - world quaternion at load time
|
|
38402
|
-
* @param {THREE.Vector3} origWorldCenter - world bounding-box center at load time
|
|
38438
|
+
* @param {number} viewerMaxDim
|
|
38403
38439
|
*/
|
|
38404
38440
|
}, {
|
|
38405
38441
|
key: "_applyRotation",
|
|
38406
|
-
value: function _applyRotation(
|
|
38442
|
+
value: function _applyRotation(entry, anim, angleDeg, viewerMaxDim) {
|
|
38407
38443
|
var _anim$rotAxis, _anim$rotAxisOffset;
|
|
38444
|
+
var mesh = entry.mesh,
|
|
38445
|
+
origPos = entry.origPos,
|
|
38446
|
+
origRot = entry.origRot;
|
|
38447
|
+
var restWorld = this._getRestWorldTransforms(entry);
|
|
38448
|
+
var origWorldPos = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldPos;
|
|
38449
|
+
var origWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldQuat;
|
|
38450
|
+
var origWorldCenter = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldCenter;
|
|
38451
|
+
var deviceWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.deviceWorldQuat;
|
|
38408
38452
|
var angle = THREE__namespace.MathUtils.degToRad(typeof angleDeg === 'number' ? angleDeg : 0);
|
|
38409
38453
|
var axis = ((_anim$rotAxis = anim.rotAxis) !== null && _anim$rotAxis !== void 0 ? _anim$rotAxis : 'x').toLowerCase();
|
|
38410
38454
|
var off = (_anim$rotAxisOffset = anim.rotAxisOffset) !== null && _anim$rotAxisOffset !== void 0 ? _anim$rotAxisOffset : {
|
|
@@ -40151,7 +40195,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
40151
40195
|
* Initialize the CentralPlant manager
|
|
40152
40196
|
*
|
|
40153
40197
|
* @constructor
|
|
40154
|
-
* @version 0.3.
|
|
40198
|
+
* @version 0.3.38
|
|
40155
40199
|
* @updated 2025-10-22
|
|
40156
40200
|
*
|
|
40157
40201
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -35,7 +35,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
35
35
|
* Initialize the CentralPlant manager
|
|
36
36
|
*
|
|
37
37
|
* @constructor
|
|
38
|
-
* @version 0.3.
|
|
38
|
+
* @version 0.3.38
|
|
39
39
|
* @updated 2025-10-22
|
|
40
40
|
*
|
|
41
41
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -121,6 +121,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
121
121
|
entries.push({
|
|
122
122
|
anim: anim,
|
|
123
123
|
mesh: mesh,
|
|
124
|
+
deviceModelRoot: deviceModelRoot,
|
|
124
125
|
origPos: mesh.position.clone(),
|
|
125
126
|
origRot: mesh.rotation.clone(),
|
|
126
127
|
origWorldPos: worldPos,
|
|
@@ -871,13 +872,9 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
871
872
|
value: function _applyAnimation(entry, value) {
|
|
872
873
|
var anim = entry.anim,
|
|
873
874
|
mesh = entry.mesh,
|
|
874
|
-
origPos = entry.origPos
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
origWorldQuat = entry.origWorldQuat,
|
|
878
|
-
origWorldCenter = entry.origWorldCenter,
|
|
879
|
-
deviceWorldQuat = entry.deviceWorldQuat,
|
|
880
|
-
viewerMaxDim = entry.viewerMaxDim;
|
|
875
|
+
origPos = entry.origPos;
|
|
876
|
+
entry.origRot;
|
|
877
|
+
var viewerMaxDim = entry.viewerMaxDim;
|
|
881
878
|
var mapping = this._resolveMapping(anim, value);
|
|
882
879
|
if (!mapping) return;
|
|
883
880
|
var types = anim.transformTypes || [];
|
|
@@ -889,7 +886,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
889
886
|
if (type === 'translation') {
|
|
890
887
|
this._applyTranslation(mesh, origPos, mapping.transform);
|
|
891
888
|
} else if (type === 'rotation') {
|
|
892
|
-
this._applyRotation(
|
|
889
|
+
this._applyRotation(entry, anim, mapping.rotationTransform, viewerMaxDim);
|
|
893
890
|
} else if (type === 'color') {
|
|
894
891
|
this._applyColor(mesh, mapping.colorTransform);
|
|
895
892
|
}
|
|
@@ -1033,25 +1030,71 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1033
1030
|
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));
|
|
1034
1031
|
}
|
|
1035
1032
|
|
|
1033
|
+
/**
|
|
1034
|
+
* Recompute world-space rest-pose transforms for a behavior entry using the
|
|
1035
|
+
* current parent/device world matrix. origPos/origRot are local rest pose and
|
|
1036
|
+
* stay valid after parent moves; world anchors must be derived at apply time.
|
|
1037
|
+
*
|
|
1038
|
+
* @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
|
|
1039
|
+
* @returns {{ origWorldPos: THREE.Vector3, origWorldQuat: THREE.Quaternion, origWorldCenter: THREE.Vector3, deviceWorldQuat: THREE.Quaternion }|null}
|
|
1040
|
+
*/
|
|
1041
|
+
}, {
|
|
1042
|
+
key: "_getRestWorldTransforms",
|
|
1043
|
+
value: function _getRestWorldTransforms(entry) {
|
|
1044
|
+
var mesh = entry.mesh,
|
|
1045
|
+
origPos = entry.origPos,
|
|
1046
|
+
origRot = entry.origRot,
|
|
1047
|
+
deviceModelRoot = entry.deviceModelRoot;
|
|
1048
|
+
if (!mesh || !origPos || !origRot) return null;
|
|
1049
|
+
var savedPos = mesh.position.clone();
|
|
1050
|
+
var savedQuat = mesh.quaternion.clone();
|
|
1051
|
+
mesh.position.copy(origPos);
|
|
1052
|
+
mesh.rotation.copy(origRot);
|
|
1053
|
+
mesh.updateMatrixWorld(true);
|
|
1054
|
+
var origWorldPos = new THREE__namespace.Vector3();
|
|
1055
|
+
mesh.getWorldPosition(origWorldPos);
|
|
1056
|
+
var origWorldQuat = new THREE__namespace.Quaternion();
|
|
1057
|
+
mesh.getWorldQuaternion(origWorldQuat);
|
|
1058
|
+
var box = new THREE__namespace.Box3().setFromObject(mesh);
|
|
1059
|
+
var origWorldCenter = new THREE__namespace.Vector3();
|
|
1060
|
+
if (!box.isEmpty()) box.getCenter(origWorldCenter);else origWorldCenter.copy(origWorldPos);
|
|
1061
|
+
var deviceWorldQuat = new THREE__namespace.Quaternion();
|
|
1062
|
+
if (deviceModelRoot) {
|
|
1063
|
+
deviceModelRoot.getWorldQuaternion(deviceWorldQuat);
|
|
1064
|
+
}
|
|
1065
|
+
mesh.position.copy(savedPos);
|
|
1066
|
+
mesh.quaternion.copy(savedQuat);
|
|
1067
|
+
return {
|
|
1068
|
+
origWorldPos: origWorldPos,
|
|
1069
|
+
origWorldQuat: origWorldQuat,
|
|
1070
|
+
origWorldCenter: origWorldCenter,
|
|
1071
|
+
deviceWorldQuat: deviceWorldQuat
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1036
1075
|
/**
|
|
1037
1076
|
* Apply a rotation around an arbitrary pivot point using world-space quaternion
|
|
1038
1077
|
* math matching the ReconstructionViewer's setMeshPreviewRotationAxis approach.
|
|
1039
1078
|
* This ensures the runtime axis/pivot matches what the user configured in the
|
|
1040
1079
|
* animation dialog, regardless of the device's parent transform in the scene.
|
|
1041
1080
|
*
|
|
1042
|
-
* @param {
|
|
1043
|
-
* @param {THREE.Vector3} origPos - local position at load time (unused, kept for signature compat)
|
|
1044
|
-
* @param {THREE.Euler} origRot - local rotation at load time (unused)
|
|
1081
|
+
* @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
|
|
1045
1082
|
* @param {Object} anim
|
|
1046
1083
|
* @param {number} angleDeg - Degrees
|
|
1047
|
-
* @param {
|
|
1048
|
-
* @param {THREE.Quaternion} origWorldQuat - world quaternion at load time
|
|
1049
|
-
* @param {THREE.Vector3} origWorldCenter - world bounding-box center at load time
|
|
1084
|
+
* @param {number} viewerMaxDim
|
|
1050
1085
|
*/
|
|
1051
1086
|
}, {
|
|
1052
1087
|
key: "_applyRotation",
|
|
1053
|
-
value: function _applyRotation(
|
|
1088
|
+
value: function _applyRotation(entry, anim, angleDeg, viewerMaxDim) {
|
|
1054
1089
|
var _anim$rotAxis, _anim$rotAxisOffset;
|
|
1090
|
+
var mesh = entry.mesh,
|
|
1091
|
+
origPos = entry.origPos,
|
|
1092
|
+
origRot = entry.origRot;
|
|
1093
|
+
var restWorld = this._getRestWorldTransforms(entry);
|
|
1094
|
+
var origWorldPos = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldPos;
|
|
1095
|
+
var origWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldQuat;
|
|
1096
|
+
var origWorldCenter = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldCenter;
|
|
1097
|
+
var deviceWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.deviceWorldQuat;
|
|
1055
1098
|
var angle = THREE__namespace.MathUtils.degToRad(typeof angleDeg === 'number' ? angleDeg : 0);
|
|
1056
1099
|
var axis = ((_anim$rotAxis = anim.rotAxis) !== null && _anim$rotAxis !== void 0 ? _anim$rotAxis : 'x').toLowerCase();
|
|
1057
1100
|
var off = (_anim$rotAxisOffset = anim.rotAxisOffset) !== null && _anim$rotAxisOffset !== void 0 ? _anim$rotAxisOffset : {
|
|
@@ -29,7 +29,7 @@ var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
30
30
|
// Inline styles (injected once into the document head)
|
|
31
31
|
// ---------------------------------------------------------------------------
|
|
32
|
-
var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n}\n\n.cp-tooltip__card {\n background: rgba(
|
|
32
|
+
var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n color-scheme: light;\n}\n\n.cp-tooltip__card {\n background: rgba(255, 255, 255, 0.97);\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__header {\n padding: 10px 14px;\n font-weight: 600;\n font-size: 14px;\n color: #2c3e50;\n background: rgba(0, 0, 0, 0.02);\n border-bottom: 1px solid rgba(0, 0, 0, 0.08);\n letter-spacing: 0.2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 I/O Devices section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__io-section {\n position: relative;\n}\n\n.cp-tooltip__io-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px;\n color: #666666;\n cursor: pointer;\n transition: background 0.12s ease, color 0.12s ease;\n}\n\n.cp-tooltip__io-trigger:hover {\n background: rgba(0, 0, 0, 0.04);\n color: #333333;\n}\n\n.cp-tooltip__io-trigger-label {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n font-weight: 500;\n}\n\n.cp-tooltip__io-arrow {\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__io-arrow {\n transform: rotate(90deg);\n}\n\n/* \u2500\u2500 Device list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__device-list {\n max-height: 0;\n overflow: hidden;\n transition: max-height 0.25s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__device-list {\n max-height: 300px;\n}\n\n.cp-tooltip__device-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 14px 6px 20px;\n color: #555555;\n font-size: 12px;\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n transition: background 0.1s ease;\n}\n\n.cp-tooltip__device-item:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n\n.cp-tooltip__device-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #1976d2;\n flex-shrink: 0;\n}\n\n.cp-tooltip__device-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__no-devices {\n padding: 8px 14px;\n color: #888888;\n font-size: 12px;\n font-style: italic;\n}\n\n/* \u2500\u2500 Caret arrow pointing down \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__caret {\n width: 0;\n height: 0;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 7px solid rgba(255, 255, 255, 0.97);\n margin: 0 auto;\n position: relative;\n top: -1px;\n filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.1));\n}\n\n/* \u2500\u2500 Data point rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__dp-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 4px 12px 4px 30px;\n font-size: 11.5px;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n min-height: 24px;\n}\n\n.cp-tooltip__dp-name {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: #666666;\n}\n\n/* Read-only state badge */\n.cp-tooltip__dp-badge {\n font-size: 10.5px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 8px;\n flex-shrink: 0;\n background: #f0f2f5;\n color: #666666;\n min-width: 30px;\n text-align: center;\n letter-spacing: 0.2px;\n}\n\n.cp-tooltip__dp-badge.active {\n background: rgba(76, 175, 80, 0.15);\n color: #2e7d32;\n}\n\n/* Binary toggle button */\n.cp-tooltip__dp-toggle {\n font-size: 10.5px;\n font-weight: 600;\n padding: 2px 9px;\n border-radius: 8px;\n flex-shrink: 0;\n border: 1px solid #dddddd;\n background: #f8f9fa;\n color: #555555;\n cursor: pointer;\n min-width: 40px;\n text-align: center;\n transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n}\n\n.cp-tooltip__dp-toggle:hover {\n background: #eeeeee;\n border-color: #cccccc;\n}\n\n.cp-tooltip__dp-toggle.on {\n background: rgba(76, 175, 80, 0.15);\n border-color: rgba(76, 175, 80, 0.45);\n color: #2e7d32;\n}\n\n/* Number / float input */\n.cp-tooltip__dp-input {\n width: 62px;\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 5px;\n text-align: right;\n outline: none;\n flex-shrink: 0;\n}\n\n.cp-tooltip__dp-input:focus {\n border-color: #1976d2;\n}\n\n/* Enum select */\n.cp-tooltip__dp-select {\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 4px;\n outline: none;\n flex-shrink: 0;\n max-width: 96px;\n cursor: pointer;\n}\n\n.cp-tooltip__dp-select:focus {\n border-color: #1976d2;\n}\n\n/* Unit suffix */\n.cp-tooltip__dp-unit {\n font-size: 10px;\n color: #888888;\n flex-shrink: 0;\n margin-left: -4px;\n}\n";
|
|
33
33
|
var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
34
34
|
/**
|
|
35
35
|
* @param {Object} sceneViewer - The sceneViewer instance
|
|
@@ -199,7 +199,8 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
199
199
|
|
|
200
200
|
// Copy only essential userData properties (libraryId, objectType, direction, group)
|
|
201
201
|
Object.keys(threeObject.userData).forEach(function (key) {
|
|
202
|
-
|
|
202
|
+
// Skip runtime/internal keys (e.g. _filteredBBoxCache from boundingBoxUtils)
|
|
203
|
+
if (!excludedKeys.has(key) && !key.startsWith('_')) {
|
|
203
204
|
jsonObject.userData[key] = threeObject.userData[key];
|
|
204
205
|
}
|
|
205
206
|
});
|
|
@@ -31,7 +31,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
31
31
|
* Initialize the CentralPlant manager
|
|
32
32
|
*
|
|
33
33
|
* @constructor
|
|
34
|
-
* @version 0.3.
|
|
34
|
+
* @version 0.3.38
|
|
35
35
|
* @updated 2025-10-22
|
|
36
36
|
*
|
|
37
37
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -97,6 +97,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
97
97
|
entries.push({
|
|
98
98
|
anim: anim,
|
|
99
99
|
mesh: mesh,
|
|
100
|
+
deviceModelRoot: deviceModelRoot,
|
|
100
101
|
origPos: mesh.position.clone(),
|
|
101
102
|
origRot: mesh.rotation.clone(),
|
|
102
103
|
origWorldPos: worldPos,
|
|
@@ -847,13 +848,9 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
847
848
|
value: function _applyAnimation(entry, value) {
|
|
848
849
|
var anim = entry.anim,
|
|
849
850
|
mesh = entry.mesh,
|
|
850
|
-
origPos = entry.origPos
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
origWorldQuat = entry.origWorldQuat,
|
|
854
|
-
origWorldCenter = entry.origWorldCenter,
|
|
855
|
-
deviceWorldQuat = entry.deviceWorldQuat,
|
|
856
|
-
viewerMaxDim = entry.viewerMaxDim;
|
|
851
|
+
origPos = entry.origPos;
|
|
852
|
+
entry.origRot;
|
|
853
|
+
var viewerMaxDim = entry.viewerMaxDim;
|
|
857
854
|
var mapping = this._resolveMapping(anim, value);
|
|
858
855
|
if (!mapping) return;
|
|
859
856
|
var types = anim.transformTypes || [];
|
|
@@ -865,7 +862,7 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
865
862
|
if (type === 'translation') {
|
|
866
863
|
this._applyTranslation(mesh, origPos, mapping.transform);
|
|
867
864
|
} else if (type === 'rotation') {
|
|
868
|
-
this._applyRotation(
|
|
865
|
+
this._applyRotation(entry, anim, mapping.rotationTransform, viewerMaxDim);
|
|
869
866
|
} else if (type === 'color') {
|
|
870
867
|
this._applyColor(mesh, mapping.colorTransform);
|
|
871
868
|
}
|
|
@@ -1009,25 +1006,71 @@ var IoBehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1009
1006
|
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));
|
|
1010
1007
|
}
|
|
1011
1008
|
|
|
1009
|
+
/**
|
|
1010
|
+
* Recompute world-space rest-pose transforms for a behavior entry using the
|
|
1011
|
+
* current parent/device world matrix. origPos/origRot are local rest pose and
|
|
1012
|
+
* stay valid after parent moves; world anchors must be derived at apply time.
|
|
1013
|
+
*
|
|
1014
|
+
* @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
|
|
1015
|
+
* @returns {{ origWorldPos: THREE.Vector3, origWorldQuat: THREE.Quaternion, origWorldCenter: THREE.Vector3, deviceWorldQuat: THREE.Quaternion }|null}
|
|
1016
|
+
*/
|
|
1017
|
+
}, {
|
|
1018
|
+
key: "_getRestWorldTransforms",
|
|
1019
|
+
value: function _getRestWorldTransforms(entry) {
|
|
1020
|
+
var mesh = entry.mesh,
|
|
1021
|
+
origPos = entry.origPos,
|
|
1022
|
+
origRot = entry.origRot,
|
|
1023
|
+
deviceModelRoot = entry.deviceModelRoot;
|
|
1024
|
+
if (!mesh || !origPos || !origRot) return null;
|
|
1025
|
+
var savedPos = mesh.position.clone();
|
|
1026
|
+
var savedQuat = mesh.quaternion.clone();
|
|
1027
|
+
mesh.position.copy(origPos);
|
|
1028
|
+
mesh.rotation.copy(origRot);
|
|
1029
|
+
mesh.updateMatrixWorld(true);
|
|
1030
|
+
var origWorldPos = new THREE.Vector3();
|
|
1031
|
+
mesh.getWorldPosition(origWorldPos);
|
|
1032
|
+
var origWorldQuat = new THREE.Quaternion();
|
|
1033
|
+
mesh.getWorldQuaternion(origWorldQuat);
|
|
1034
|
+
var box = new THREE.Box3().setFromObject(mesh);
|
|
1035
|
+
var origWorldCenter = new THREE.Vector3();
|
|
1036
|
+
if (!box.isEmpty()) box.getCenter(origWorldCenter);else origWorldCenter.copy(origWorldPos);
|
|
1037
|
+
var deviceWorldQuat = new THREE.Quaternion();
|
|
1038
|
+
if (deviceModelRoot) {
|
|
1039
|
+
deviceModelRoot.getWorldQuaternion(deviceWorldQuat);
|
|
1040
|
+
}
|
|
1041
|
+
mesh.position.copy(savedPos);
|
|
1042
|
+
mesh.quaternion.copy(savedQuat);
|
|
1043
|
+
return {
|
|
1044
|
+
origWorldPos: origWorldPos,
|
|
1045
|
+
origWorldQuat: origWorldQuat,
|
|
1046
|
+
origWorldCenter: origWorldCenter,
|
|
1047
|
+
deviceWorldQuat: deviceWorldQuat
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1012
1051
|
/**
|
|
1013
1052
|
* Apply a rotation around an arbitrary pivot point using world-space quaternion
|
|
1014
1053
|
* math matching the ReconstructionViewer's setMeshPreviewRotationAxis approach.
|
|
1015
1054
|
* This ensures the runtime axis/pivot matches what the user configured in the
|
|
1016
1055
|
* animation dialog, regardless of the device's parent transform in the scene.
|
|
1017
1056
|
*
|
|
1018
|
-
* @param {
|
|
1019
|
-
* @param {THREE.Vector3} origPos - local position at load time (unused, kept for signature compat)
|
|
1020
|
-
* @param {THREE.Euler} origRot - local rotation at load time (unused)
|
|
1057
|
+
* @param {{ mesh, origPos, origRot, deviceModelRoot }} entry
|
|
1021
1058
|
* @param {Object} anim
|
|
1022
1059
|
* @param {number} angleDeg - Degrees
|
|
1023
|
-
* @param {
|
|
1024
|
-
* @param {THREE.Quaternion} origWorldQuat - world quaternion at load time
|
|
1025
|
-
* @param {THREE.Vector3} origWorldCenter - world bounding-box center at load time
|
|
1060
|
+
* @param {number} viewerMaxDim
|
|
1026
1061
|
*/
|
|
1027
1062
|
}, {
|
|
1028
1063
|
key: "_applyRotation",
|
|
1029
|
-
value: function _applyRotation(
|
|
1064
|
+
value: function _applyRotation(entry, anim, angleDeg, viewerMaxDim) {
|
|
1030
1065
|
var _anim$rotAxis, _anim$rotAxisOffset;
|
|
1066
|
+
var mesh = entry.mesh,
|
|
1067
|
+
origPos = entry.origPos,
|
|
1068
|
+
origRot = entry.origRot;
|
|
1069
|
+
var restWorld = this._getRestWorldTransforms(entry);
|
|
1070
|
+
var origWorldPos = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldPos;
|
|
1071
|
+
var origWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldQuat;
|
|
1072
|
+
var origWorldCenter = restWorld === null || restWorld === void 0 ? void 0 : restWorld.origWorldCenter;
|
|
1073
|
+
var deviceWorldQuat = restWorld === null || restWorld === void 0 ? void 0 : restWorld.deviceWorldQuat;
|
|
1031
1074
|
var angle = THREE.MathUtils.degToRad(typeof angleDeg === 'number' ? angleDeg : 0);
|
|
1032
1075
|
var axis = ((_anim$rotAxis = anim.rotAxis) !== null && _anim$rotAxis !== void 0 ? _anim$rotAxis : 'x').toLowerCase();
|
|
1033
1076
|
var off = (_anim$rotAxisOffset = anim.rotAxisOffset) !== null && _anim$rotAxisOffset !== void 0 ? _anim$rotAxisOffset : {
|
|
@@ -5,7 +5,7 @@ import { BaseDisposable } from '../../core/baseDisposable.js';
|
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
6
6
|
// Inline styles (injected once into the document head)
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
|
-
var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n}\n\n.cp-tooltip__card {\n background: rgba(
|
|
8
|
+
var TOOLTIP_STYLES = "\n.cp-tooltip {\n position: absolute;\n pointer-events: auto;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n user-select: none;\n min-width: 200px;\n max-width: 280px;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n transition: opacity 0.15s ease;\n color-scheme: light;\n}\n\n.cp-tooltip__card {\n background: rgba(255, 255, 255, 0.97);\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__header {\n padding: 10px 14px;\n font-weight: 600;\n font-size: 14px;\n color: #2c3e50;\n background: rgba(0, 0, 0, 0.02);\n border-bottom: 1px solid rgba(0, 0, 0, 0.08);\n letter-spacing: 0.2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 I/O Devices section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__io-section {\n position: relative;\n}\n\n.cp-tooltip__io-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px;\n color: #666666;\n cursor: pointer;\n transition: background 0.12s ease, color 0.12s ease;\n}\n\n.cp-tooltip__io-trigger:hover {\n background: rgba(0, 0, 0, 0.04);\n color: #333333;\n}\n\n.cp-tooltip__io-trigger-label {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n font-weight: 500;\n}\n\n.cp-tooltip__io-arrow {\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__io-arrow {\n transform: rotate(90deg);\n}\n\n/* \u2500\u2500 Device list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__device-list {\n max-height: 0;\n overflow: hidden;\n transition: max-height 0.25s ease;\n}\n\n.cp-tooltip__io-section.expanded .cp-tooltip__device-list {\n max-height: 300px;\n}\n\n.cp-tooltip__device-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 14px 6px 20px;\n color: #555555;\n font-size: 12px;\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n transition: background 0.1s ease;\n}\n\n.cp-tooltip__device-item:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n\n.cp-tooltip__device-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #1976d2;\n flex-shrink: 0;\n}\n\n.cp-tooltip__device-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__no-devices {\n padding: 8px 14px;\n color: #888888;\n font-size: 12px;\n font-style: italic;\n}\n\n/* \u2500\u2500 Caret arrow pointing down \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__caret {\n width: 0;\n height: 0;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 7px solid rgba(255, 255, 255, 0.97);\n margin: 0 auto;\n position: relative;\n top: -1px;\n filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.1));\n}\n\n/* \u2500\u2500 Data point rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.cp-tooltip__dp-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 4px 12px 4px 30px;\n font-size: 11.5px;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n min-height: 24px;\n}\n\n.cp-tooltip__dp-name {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: #666666;\n}\n\n/* Read-only state badge */\n.cp-tooltip__dp-badge {\n font-size: 10.5px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 8px;\n flex-shrink: 0;\n background: #f0f2f5;\n color: #666666;\n min-width: 30px;\n text-align: center;\n letter-spacing: 0.2px;\n}\n\n.cp-tooltip__dp-badge.active {\n background: rgba(76, 175, 80, 0.15);\n color: #2e7d32;\n}\n\n/* Binary toggle button */\n.cp-tooltip__dp-toggle {\n font-size: 10.5px;\n font-weight: 600;\n padding: 2px 9px;\n border-radius: 8px;\n flex-shrink: 0;\n border: 1px solid #dddddd;\n background: #f8f9fa;\n color: #555555;\n cursor: pointer;\n min-width: 40px;\n text-align: center;\n transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n}\n\n.cp-tooltip__dp-toggle:hover {\n background: #eeeeee;\n border-color: #cccccc;\n}\n\n.cp-tooltip__dp-toggle.on {\n background: rgba(76, 175, 80, 0.15);\n border-color: rgba(76, 175, 80, 0.45);\n color: #2e7d32;\n}\n\n/* Number / float input */\n.cp-tooltip__dp-input {\n width: 62px;\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 5px;\n text-align: right;\n outline: none;\n flex-shrink: 0;\n}\n\n.cp-tooltip__dp-input:focus {\n border-color: #1976d2;\n}\n\n/* Enum select */\n.cp-tooltip__dp-select {\n background: #f8f9fa;\n border: 1px solid #dddddd;\n border-radius: 4px;\n color: #333333;\n font-size: 11px;\n padding: 2px 4px;\n outline: none;\n flex-shrink: 0;\n max-width: 96px;\n cursor: pointer;\n}\n\n.cp-tooltip__dp-select:focus {\n border-color: #1976d2;\n}\n\n/* Unit suffix */\n.cp-tooltip__dp-unit {\n font-size: 10px;\n color: #888888;\n flex-shrink: 0;\n margin-left: -4px;\n}\n";
|
|
9
9
|
var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
10
10
|
/**
|
|
11
11
|
* @param {Object} sceneViewer - The sceneViewer instance
|
|
@@ -177,7 +177,8 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
177
177
|
|
|
178
178
|
// Copy only essential userData properties (libraryId, objectType, direction, group)
|
|
179
179
|
Object.keys(threeObject.userData).forEach(function (key) {
|
|
180
|
-
|
|
180
|
+
// Skip runtime/internal keys (e.g. _filteredBBoxCache from boundingBoxUtils)
|
|
181
|
+
if (!excludedKeys.has(key) && !key.startsWith('_')) {
|
|
181
182
|
jsonObject.userData[key] = threeObject.userData[key];
|
|
182
183
|
}
|
|
183
184
|
});
|