@2112-lab/central-plant 0.3.48 → 0.3.50
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 +836 -264
- package/dist/cjs/src/core/centralPlant.js +119 -6
- package/dist/cjs/src/index.js +2 -0
- package/dist/cjs/src/managers/controls/cameraControlsManager.js +353 -7
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +285 -145
- package/dist/cjs/src/managers/scene/sceneExportManager.js +19 -37
- package/dist/cjs/src/managers/scene/sceneInitializationManager.js +2 -1
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +35 -3
- package/dist/esm/src/core/centralPlant.js +99 -6
- package/dist/esm/src/index.js +1 -1
- package/dist/esm/src/managers/controls/cameraControlsManager.js +333 -9
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +286 -146
- package/dist/esm/src/managers/scene/sceneExportManager.js +20 -36
- package/dist/esm/src/managers/scene/sceneInitializationManager.js +2 -1
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +35 -3
- package/dist/esm/src/utils/boundingBoxUtils.js +1 -1
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -12060,11 +12060,10 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
12060
12060
|
};
|
|
12061
12061
|
}
|
|
12062
12062
|
|
|
12063
|
-
//
|
|
12064
|
-
//
|
|
12065
|
-
//
|
|
12063
|
+
// Only manual segments persist their connector children here.
|
|
12064
|
+
// Component connectors are NOT exported — they are regenerated from the
|
|
12065
|
+
// component dictionary on load (see note below), keeping the scene JSON minimal.
|
|
12066
12066
|
if (threeObject.children && threeObject.children.length > 0) {
|
|
12067
|
-
var _threeObject$userData11;
|
|
12068
12067
|
var exportableChildren = [];
|
|
12069
12068
|
if (isManualSegment) {
|
|
12070
12069
|
// For manual segments, export their connector children
|
|
@@ -12078,30 +12077,15 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
12078
12077
|
}
|
|
12079
12078
|
}
|
|
12080
12079
|
});
|
|
12081
|
-
} else if (((_threeObject$userData11 = threeObject.userData) === null || _threeObject$userData11 === void 0 ? void 0 : _threeObject$userData11.objectType) === 'component') {
|
|
12082
|
-
// For components, export all connectors (including deep children within GLFs)
|
|
12083
|
-
threeObject.traverse(function (child) {
|
|
12084
|
-
var _child$userData2;
|
|
12085
|
-
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'connector') {
|
|
12086
|
-
// Calculate position relative to component root
|
|
12087
|
-
var componentMatrixWorldInverse = threeObject.matrixWorld.clone().invert();
|
|
12088
|
-
var childWorldPos = new THREE__namespace.Vector3();
|
|
12089
|
-
child.getWorldPosition(childWorldPos);
|
|
12090
|
-
var relativePos = childWorldPos.applyMatrix4(componentMatrixWorldInverse);
|
|
12091
|
-
exportableChildren.push({
|
|
12092
|
-
uuid: child.uuid,
|
|
12093
|
-
name: child.name,
|
|
12094
|
-
type: 'Mesh',
|
|
12095
|
-
position: {
|
|
12096
|
-
x: roundIfClose(relativePos.x),
|
|
12097
|
-
y: roundIfClose(relativePos.y),
|
|
12098
|
-
z: roundIfClose(relativePos.z)
|
|
12099
|
-
},
|
|
12100
|
-
userData: _objectSpread2({}, child.userData)
|
|
12101
|
-
});
|
|
12102
|
-
}
|
|
12103
|
-
});
|
|
12104
12080
|
}
|
|
12081
|
+
// NOTE: Component connectors are intentionally NOT exported.
|
|
12082
|
+
// They are defined in the component dictionary and regenerated on load by
|
|
12083
|
+
// sceneOperationsManager._injectConnectorChildrenFromDictionary using the
|
|
12084
|
+
// matching uuid scheme (`${componentUuid}_${dictConnectorUuid}`), and the
|
|
12085
|
+
// pathfinder rebuilds their world positions/bounding boxes on every run
|
|
12086
|
+
// (computeConnectorBoundingBoxes). Connections still resolve because the
|
|
12087
|
+
// regenerated connector uuids match the connection endpoints.
|
|
12088
|
+
|
|
12105
12089
|
if (exportableChildren.length > 0) {
|
|
12106
12090
|
jsonObject.children = exportableChildren;
|
|
12107
12091
|
}
|
|
@@ -12115,9 +12099,9 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
12115
12099
|
// Extract main scene objects (components and standalone connectors)
|
|
12116
12100
|
var sceneChildren = [];
|
|
12117
12101
|
this.sceneViewer.scene.children.forEach(function (child) {
|
|
12118
|
-
var _child$
|
|
12102
|
+
var _child$userData2;
|
|
12119
12103
|
// Only export components and connectors; skip segments, gateways, polylines, etc.
|
|
12120
|
-
var objectType = (_child$
|
|
12104
|
+
var objectType = (_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType;
|
|
12121
12105
|
if (objectType !== 'component' && objectType !== 'connector') {
|
|
12122
12106
|
return;
|
|
12123
12107
|
}
|
|
@@ -12281,14 +12265,14 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
12281
12265
|
BufferGeometryUtils$1 = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
|
|
12282
12266
|
exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
|
|
12283
12267
|
shouldExport = function shouldExport(child) {
|
|
12284
|
-
var _child$name, _child$
|
|
12268
|
+
var _child$name, _child$userData3, _child$userData4, _child$userData5, _child$userData6;
|
|
12285
12269
|
if ((_child$name = child.name) !== null && _child$name !== void 0 && _child$name.includes('Polyline')) return false; // Will handle separately
|
|
12286
12270
|
if (child.name === 'fogPlane') return false; // Skip fog plane
|
|
12287
|
-
if ((_child$
|
|
12288
|
-
if ((_child$
|
|
12289
|
-
if ((_child$
|
|
12271
|
+
if ((_child$userData3 = child.userData) !== null && _child$userData3 !== void 0 && _child$userData3.isBrickWall) return false; // Skip environment
|
|
12272
|
+
if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBaseGround) return false; // Skip environment
|
|
12273
|
+
if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGrid) return false; // Skip environment
|
|
12290
12274
|
if (child.isLight) return false; // Skip lights
|
|
12291
|
-
if ((_child$
|
|
12275
|
+
if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isTransformControls) return false; // Skip transform controls
|
|
12292
12276
|
if (child.isTransformControls) return false; // Skip transform controls
|
|
12293
12277
|
if (child.type && child.type.includes('TransformControls')) return false;
|
|
12294
12278
|
if (child.type && child.type.includes('Helper')) return false; // Skip helpers
|
|
@@ -25504,6 +25488,405 @@ function interceptControlUp( event ) {
|
|
|
25504
25488
|
|
|
25505
25489
|
}
|
|
25506
25490
|
|
|
25491
|
+
/** Default horizontal orbit bearing (target → camera, XY plane). */
|
|
25492
|
+
var DEFAULT_HOME_VIEW_DIRECTION = {
|
|
25493
|
+
x: -8,
|
|
25494
|
+
y: -9,
|
|
25495
|
+
z: 0
|
|
25496
|
+
};
|
|
25497
|
+
|
|
25498
|
+
/** Downward pitch from camera to the bottom-center look-at target (degrees). */
|
|
25499
|
+
var HOME_DOWNWARD_PITCH_DEG = 13;
|
|
25500
|
+
|
|
25501
|
+
/** Minimum camera height above the bbox floor (world units). */
|
|
25502
|
+
var HOME_CAMERA_MIN_HEIGHT = 0.8;
|
|
25503
|
+
|
|
25504
|
+
/** Ground plane height in world space (Z-up). */
|
|
25505
|
+
var WORLD_GROUND_Z = 0;
|
|
25506
|
+
|
|
25507
|
+
/** Camera height above the ground when the scene has no components. */
|
|
25508
|
+
var HOME_EMPTY_CAMERA_HEIGHT_ABOVE_GROUND = 2.5;
|
|
25509
|
+
|
|
25510
|
+
/** Default horizontal distance from world origin when the scene is empty. */
|
|
25511
|
+
var HOME_EMPTY_SCENE_DISTANCE = Math.hypot(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y);
|
|
25512
|
+
var WORLD_ORIGIN = new THREE__namespace.Vector3(0, 0, 0);
|
|
25513
|
+
var CameraControlsManager = /*#__PURE__*/function () {
|
|
25514
|
+
function CameraControlsManager(component) {
|
|
25515
|
+
_classCallCheck(this, CameraControlsManager);
|
|
25516
|
+
this.sceneViewer = component;
|
|
25517
|
+
this.autoRotateSpeed = 1.0; // Default rotation speed
|
|
25518
|
+
this._isAutoRotating = false; // Internal state tracking
|
|
25519
|
+
}
|
|
25520
|
+
|
|
25521
|
+
/**
|
|
25522
|
+
* Frame the camera so that every component in the scene fits perfectly in view.
|
|
25523
|
+
*
|
|
25524
|
+
* Computes the combined bounding box of all scene components, then moves the
|
|
25525
|
+
* (perspective) camera along its current viewing direction to the distance
|
|
25526
|
+
* required to fit that bounding sphere within the frustum. The orbit target,
|
|
25527
|
+
* clipping planes and distance limits are updated to match.
|
|
25528
|
+
*
|
|
25529
|
+
* @param {Object} [options]
|
|
25530
|
+
* @param {number} [options.padding=1.04] - Multiplier on the fit distance (>1 leaves margin).
|
|
25531
|
+
* @param {THREE.Vector3|{x:number,y:number,z:number}} [options.direction] - Override viewing
|
|
25532
|
+
* direction (target -> camera). When omitted, the current orbit angle is preserved.
|
|
25533
|
+
* @param {boolean} [options.groundLevel] - Pin camera low with a downward pitch toward
|
|
25534
|
+
* the bottom-center of the assembly. Defaults to true when a home direction is used.
|
|
25535
|
+
* @returns {boolean} True if the camera was reframed, false if there was nothing to frame.
|
|
25536
|
+
*/
|
|
25537
|
+
return _createClass(CameraControlsManager, [{
|
|
25538
|
+
key: "fitCameraToScene",
|
|
25539
|
+
value: function fitCameraToScene() {
|
|
25540
|
+
var _options$padding, _options$groundLevel;
|
|
25541
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
25542
|
+
var component = this.sceneViewer;
|
|
25543
|
+
var camera = component === null || component === void 0 ? void 0 : component.camera;
|
|
25544
|
+
var scene = component === null || component === void 0 ? void 0 : component.scene;
|
|
25545
|
+
var controls = component === null || component === void 0 ? void 0 : component.controls;
|
|
25546
|
+
if (!camera || !scene || !camera.isPerspectiveCamera) {
|
|
25547
|
+
console.warn('⚠️ fitCameraToScene: missing perspective camera or scene');
|
|
25548
|
+
return false;
|
|
25549
|
+
}
|
|
25550
|
+
var padding = (_options$padding = options.padding) !== null && _options$padding !== void 0 ? _options$padding : 1.04;
|
|
25551
|
+
|
|
25552
|
+
// Make sure world matrices are current before measuring bounds
|
|
25553
|
+
scene.updateMatrixWorld(true);
|
|
25554
|
+
var box = this._collectSceneBounds(scene);
|
|
25555
|
+
if (!box) {
|
|
25556
|
+
return this._aimCameraAtWorldCenter(camera, controls, options);
|
|
25557
|
+
}
|
|
25558
|
+
var useGroundLevel = (_options$groundLevel = options.groundLevel) !== null && _options$groundLevel !== void 0 ? _options$groundLevel : this._isHomeDirection(options.direction);
|
|
25559
|
+
if (useGroundLevel) {
|
|
25560
|
+
return this._fitCameraGroundLevel(box, camera, controls, options, padding);
|
|
25561
|
+
}
|
|
25562
|
+
return this._fitCameraFromCenter(box, camera, controls, options, padding);
|
|
25563
|
+
}
|
|
25564
|
+
|
|
25565
|
+
/**
|
|
25566
|
+
* Aim the camera at world origin when there are no components to frame.
|
|
25567
|
+
* @private
|
|
25568
|
+
*/
|
|
25569
|
+
}, {
|
|
25570
|
+
key: "_aimCameraAtWorldCenter",
|
|
25571
|
+
value: function _aimCameraAtWorldCenter(camera, controls) {
|
|
25572
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
25573
|
+
var frameTarget = WORLD_ORIGIN.clone();
|
|
25574
|
+
var distance = HOME_EMPTY_SCENE_DISTANCE;
|
|
25575
|
+
var horizDir = new THREE__namespace.Vector3();
|
|
25576
|
+
if (options.direction) {
|
|
25577
|
+
horizDir.set(options.direction.x, options.direction.y, 0);
|
|
25578
|
+
} else {
|
|
25579
|
+
horizDir.set(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y, 0);
|
|
25580
|
+
}
|
|
25581
|
+
if (horizDir.lengthSq() < 1e-6) {
|
|
25582
|
+
horizDir.set(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y, 0);
|
|
25583
|
+
}
|
|
25584
|
+
horizDir.normalize();
|
|
25585
|
+
var cameraHeight = WORLD_GROUND_Z + HOME_EMPTY_CAMERA_HEIGHT_ABOVE_GROUND;
|
|
25586
|
+
var camPos = new THREE__namespace.Vector3(frameTarget.x + horizDir.x * distance, frameTarget.y + horizDir.y * distance, cameraHeight);
|
|
25587
|
+
camera.position.copy(camPos);
|
|
25588
|
+
camera.near = 0.01;
|
|
25589
|
+
camera.far = 1000;
|
|
25590
|
+
camera.updateProjectionMatrix();
|
|
25591
|
+
camera.lookAt(frameTarget);
|
|
25592
|
+
if (controls) {
|
|
25593
|
+
controls.target.copy(frameTarget);
|
|
25594
|
+
controls.minDistance = 1;
|
|
25595
|
+
controls.maxDistance = 20;
|
|
25596
|
+
controls.update();
|
|
25597
|
+
}
|
|
25598
|
+
console.log('🎥 Camera aimed at world origin (empty scene)');
|
|
25599
|
+
return true;
|
|
25600
|
+
}
|
|
25601
|
+
|
|
25602
|
+
/**
|
|
25603
|
+
* @private
|
|
25604
|
+
*/
|
|
25605
|
+
}, {
|
|
25606
|
+
key: "_collectSceneBounds",
|
|
25607
|
+
value: function _collectSceneBounds(scene) {
|
|
25608
|
+
var includeTypes = ['component', 'gateway', 'segment'];
|
|
25609
|
+
var box = new THREE__namespace.Box3();
|
|
25610
|
+
var found = false;
|
|
25611
|
+
scene.traverse(function (obj) {
|
|
25612
|
+
var _obj$userData;
|
|
25613
|
+
if (includeTypes.includes((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType)) {
|
|
25614
|
+
var objBox = new THREE__namespace.Box3().setFromObject(obj);
|
|
25615
|
+
if (!objBox.isEmpty()) {
|
|
25616
|
+
box.union(objBox);
|
|
25617
|
+
found = true;
|
|
25618
|
+
}
|
|
25619
|
+
}
|
|
25620
|
+
});
|
|
25621
|
+
return found && !box.isEmpty() ? box : null;
|
|
25622
|
+
}
|
|
25623
|
+
|
|
25624
|
+
/**
|
|
25625
|
+
* @private
|
|
25626
|
+
*/
|
|
25627
|
+
}, {
|
|
25628
|
+
key: "_isHomeDirection",
|
|
25629
|
+
value: function _isHomeDirection(direction) {
|
|
25630
|
+
if (!direction) return false;
|
|
25631
|
+
var horiz = Math.hypot(direction.x, direction.y);
|
|
25632
|
+
if (horiz < 1e-6) return false;
|
|
25633
|
+
var dx = direction.x / horiz - DEFAULT_HOME_VIEW_DIRECTION.x / Math.hypot(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y);
|
|
25634
|
+
var dy = direction.y / horiz - DEFAULT_HOME_VIEW_DIRECTION.y / Math.hypot(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y);
|
|
25635
|
+
return Math.hypot(dx, dy) < 0.05 && Math.abs(direction.z) < 0.5;
|
|
25636
|
+
}
|
|
25637
|
+
|
|
25638
|
+
/**
|
|
25639
|
+
* Ground-hugging camera: horizontal offset with a fixed downward pitch toward
|
|
25640
|
+
* the bottom-center of the component group.
|
|
25641
|
+
* @private
|
|
25642
|
+
*/
|
|
25643
|
+
}, {
|
|
25644
|
+
key: "_fitCameraGroundLevel",
|
|
25645
|
+
value: function _fitCameraGroundLevel(box, camera, controls, options, padding) {
|
|
25646
|
+
var size = box.getSize(new THREE__namespace.Vector3());
|
|
25647
|
+
var frameTarget = this._getBoxBottomCenter(box);
|
|
25648
|
+
var downwardPitch = THREE__namespace.MathUtils.degToRad(HOME_DOWNWARD_PITCH_DEG);
|
|
25649
|
+
var horizDir = new THREE__namespace.Vector3();
|
|
25650
|
+
if (options.direction) {
|
|
25651
|
+
horizDir.set(options.direction.x, options.direction.y, 0);
|
|
25652
|
+
} else {
|
|
25653
|
+
horizDir.set(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y, 0);
|
|
25654
|
+
}
|
|
25655
|
+
if (horizDir.lengthSq() < 1e-6) {
|
|
25656
|
+
horizDir.set(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y, 0);
|
|
25657
|
+
}
|
|
25658
|
+
horizDir.normalize();
|
|
25659
|
+
var corners = this._getBoxCorners(box);
|
|
25660
|
+
var vFov = THREE__namespace.MathUtils.degToRad(camera.fov);
|
|
25661
|
+
var aspect = camera.aspect || 1;
|
|
25662
|
+
var tanHalfV = Math.tan(vFov / 2);
|
|
25663
|
+
var tanHalfH = tanHalfV * aspect;
|
|
25664
|
+
var fitsAtDistance = function fitsAtDistance(distance) {
|
|
25665
|
+
var cameraHeight = Math.max(frameTarget.z + distance * Math.tan(downwardPitch), box.min.z + HOME_CAMERA_MIN_HEIGHT);
|
|
25666
|
+
var camPos = new THREE__namespace.Vector3(frameTarget.x + horizDir.x * distance, frameTarget.y + horizDir.y * distance, cameraHeight);
|
|
25667
|
+
var forward = new THREE__namespace.Vector3().subVectors(frameTarget, camPos).normalize();
|
|
25668
|
+
var worldUp = camera.up.clone().normalize();
|
|
25669
|
+
var right = new THREE__namespace.Vector3().crossVectors(forward, worldUp);
|
|
25670
|
+
if (right.lengthSq() < 1e-6) {
|
|
25671
|
+
right = new THREE__namespace.Vector3().crossVectors(forward, new THREE__namespace.Vector3(1, 0, 0));
|
|
25672
|
+
}
|
|
25673
|
+
right.normalize();
|
|
25674
|
+
var up = new THREE__namespace.Vector3().crossVectors(right, forward).normalize();
|
|
25675
|
+
var _iterator = _createForOfIteratorHelper(corners),
|
|
25676
|
+
_step;
|
|
25677
|
+
try {
|
|
25678
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
25679
|
+
var corner = _step.value;
|
|
25680
|
+
var rel = new THREE__namespace.Vector3().subVectors(corner, camPos);
|
|
25681
|
+
var depth = rel.dot(forward);
|
|
25682
|
+
if (depth <= 0.01) return false;
|
|
25683
|
+
if (Math.abs(rel.dot(right)) / depth > tanHalfH) return false;
|
|
25684
|
+
if (Math.abs(rel.dot(up)) / depth > tanHalfV) return false;
|
|
25685
|
+
}
|
|
25686
|
+
} catch (err) {
|
|
25687
|
+
_iterator.e(err);
|
|
25688
|
+
} finally {
|
|
25689
|
+
_iterator.f();
|
|
25690
|
+
}
|
|
25691
|
+
return true;
|
|
25692
|
+
};
|
|
25693
|
+
var fitDistance = 0.5;
|
|
25694
|
+
while (!fitsAtDistance(fitDistance) && fitDistance < 500) {
|
|
25695
|
+
fitDistance *= 1.15;
|
|
25696
|
+
}
|
|
25697
|
+
if (fitDistance >= 500) {
|
|
25698
|
+
console.warn('⚠️ fitCameraToScene: could not frame scene from ground level');
|
|
25699
|
+
return false;
|
|
25700
|
+
}
|
|
25701
|
+
|
|
25702
|
+
// Tighten to the closest distance that still fits, then apply padding.
|
|
25703
|
+
var lo = 0.01;
|
|
25704
|
+
var hi = fitDistance;
|
|
25705
|
+
while (hi - lo > 0.1) {
|
|
25706
|
+
var mid = (lo + hi) / 2;
|
|
25707
|
+
if (fitsAtDistance(mid)) hi = mid;else lo = mid;
|
|
25708
|
+
}
|
|
25709
|
+
fitDistance = hi * padding;
|
|
25710
|
+
var cameraHeight = Math.max(frameTarget.z + fitDistance * Math.tan(downwardPitch), box.min.z + HOME_CAMERA_MIN_HEIGHT);
|
|
25711
|
+
var camPos = new THREE__namespace.Vector3(frameTarget.x + horizDir.x * fitDistance, frameTarget.y + horizDir.y * fitDistance, cameraHeight);
|
|
25712
|
+
camera.position.copy(camPos);
|
|
25713
|
+
var span = size.length();
|
|
25714
|
+
camera.near = Math.max(fitDistance / 1000, 0.01);
|
|
25715
|
+
camera.far = Math.max(fitDistance + span * 4, 1000);
|
|
25716
|
+
camera.updateProjectionMatrix();
|
|
25717
|
+
camera.lookAt(frameTarget);
|
|
25718
|
+
if (controls) {
|
|
25719
|
+
controls.target.copy(frameTarget);
|
|
25720
|
+
controls.minDistance = Math.max(span * 0.1, 0.1);
|
|
25721
|
+
controls.maxDistance = fitDistance * 4;
|
|
25722
|
+
controls.update();
|
|
25723
|
+
}
|
|
25724
|
+
console.log("\uD83C\uDFA5 Camera framed to scene at ground level (distance: ".concat(fitDistance.toFixed(2), ", height: ").concat(cameraHeight.toFixed(2), ")"));
|
|
25725
|
+
return true;
|
|
25726
|
+
}
|
|
25727
|
+
|
|
25728
|
+
/**
|
|
25729
|
+
* Bottom-center of a bounding box (centered in X/Y, at the floor in Z).
|
|
25730
|
+
* @private
|
|
25731
|
+
*/
|
|
25732
|
+
}, {
|
|
25733
|
+
key: "_getBoxBottomCenter",
|
|
25734
|
+
value: function _getBoxBottomCenter(box) {
|
|
25735
|
+
var center = box.getCenter(new THREE__namespace.Vector3());
|
|
25736
|
+
return new THREE__namespace.Vector3(center.x, center.y, box.min.z);
|
|
25737
|
+
}
|
|
25738
|
+
|
|
25739
|
+
/**
|
|
25740
|
+
* @private
|
|
25741
|
+
*/
|
|
25742
|
+
}, {
|
|
25743
|
+
key: "_getBoxCorners",
|
|
25744
|
+
value: function _getBoxCorners(box) {
|
|
25745
|
+
var min = box.min,
|
|
25746
|
+
max = box.max;
|
|
25747
|
+
var corners = [];
|
|
25748
|
+
for (var i = 0; i < 8; i++) {
|
|
25749
|
+
corners.push(new THREE__namespace.Vector3(i & 1 ? max.x : min.x, i & 2 ? max.y : min.y, i & 4 ? max.z : min.z));
|
|
25750
|
+
}
|
|
25751
|
+
return corners;
|
|
25752
|
+
}
|
|
25753
|
+
|
|
25754
|
+
/**
|
|
25755
|
+
* @private
|
|
25756
|
+
*/
|
|
25757
|
+
}, {
|
|
25758
|
+
key: "_fitCameraFromCenter",
|
|
25759
|
+
value: function _fitCameraFromCenter(box, camera, controls, options, padding) {
|
|
25760
|
+
var center = box.getCenter(new THREE__namespace.Vector3());
|
|
25761
|
+
var target = controls !== null && controls !== void 0 && controls.target ? controls.target.clone() : new THREE__namespace.Vector3();
|
|
25762
|
+
var direction = new THREE__namespace.Vector3();
|
|
25763
|
+
if (options.direction) {
|
|
25764
|
+
direction.set(options.direction.x, options.direction.y, options.direction.z);
|
|
25765
|
+
} else {
|
|
25766
|
+
direction.subVectors(camera.position, target);
|
|
25767
|
+
}
|
|
25768
|
+
if (direction.lengthSq() < 1e-6) {
|
|
25769
|
+
direction.set(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y, DEFAULT_HOME_VIEW_DIRECTION.z);
|
|
25770
|
+
}
|
|
25771
|
+
direction.normalize();
|
|
25772
|
+
var forward = direction.clone().negate();
|
|
25773
|
+
var worldUp = camera.up.clone().normalize();
|
|
25774
|
+
var right = new THREE__namespace.Vector3().crossVectors(forward, worldUp);
|
|
25775
|
+
if (right.lengthSq() < 1e-6) {
|
|
25776
|
+
right = new THREE__namespace.Vector3().crossVectors(forward, new THREE__namespace.Vector3(1, 0, 0));
|
|
25777
|
+
}
|
|
25778
|
+
right.normalize();
|
|
25779
|
+
var up = new THREE__namespace.Vector3().crossVectors(right, forward).normalize();
|
|
25780
|
+
var vFov = THREE__namespace.MathUtils.degToRad(camera.fov);
|
|
25781
|
+
var aspect = camera.aspect || 1;
|
|
25782
|
+
var tanHalfV = Math.tan(vFov / 2);
|
|
25783
|
+
var tanHalfH = tanHalfV * aspect;
|
|
25784
|
+
var min = box.min;
|
|
25785
|
+
var max = box.max;
|
|
25786
|
+
var fitDistance = 0.01;
|
|
25787
|
+
for (var i = 0; i < 8; i++) {
|
|
25788
|
+
var v = new THREE__namespace.Vector3(i & 1 ? max.x : min.x, i & 2 ? max.y : min.y, i & 4 ? max.z : min.z).sub(center);
|
|
25789
|
+
var vForward = v.dot(forward);
|
|
25790
|
+
var vRight = Math.abs(v.dot(right));
|
|
25791
|
+
var vUp = Math.abs(v.dot(up));
|
|
25792
|
+
var cornerDistance = Math.max(vRight / tanHalfH - vForward, vUp / tanHalfV - vForward, -vForward + 0.01);
|
|
25793
|
+
fitDistance = Math.max(fitDistance, cornerDistance);
|
|
25794
|
+
}
|
|
25795
|
+
fitDistance *= padding;
|
|
25796
|
+
camera.position.copy(center).addScaledVector(direction, fitDistance);
|
|
25797
|
+
var span = box.getSize(new THREE__namespace.Vector3()).length();
|
|
25798
|
+
camera.near = Math.max(fitDistance / 1000, 0.01);
|
|
25799
|
+
camera.far = Math.max(fitDistance + span * 4, 1000);
|
|
25800
|
+
camera.updateProjectionMatrix();
|
|
25801
|
+
camera.lookAt(center);
|
|
25802
|
+
if (controls) {
|
|
25803
|
+
controls.target.copy(center);
|
|
25804
|
+
controls.minDistance = Math.max(span * 0.1, 0.1);
|
|
25805
|
+
controls.maxDistance = fitDistance * 4;
|
|
25806
|
+
controls.update();
|
|
25807
|
+
}
|
|
25808
|
+
console.log("\uD83C\uDFA5 Camera framed to scene (distance: ".concat(fitDistance.toFixed(2), ")"));
|
|
25809
|
+
return true;
|
|
25810
|
+
}
|
|
25811
|
+
|
|
25812
|
+
/**
|
|
25813
|
+
* Frame the scene using the default low, ground-level home viewing angle.
|
|
25814
|
+
* @param {Object} [options] - Passed to fitCameraToScene (padding, etc.)
|
|
25815
|
+
* @returns {boolean}
|
|
25816
|
+
*/
|
|
25817
|
+
}, {
|
|
25818
|
+
key: "fitCameraToSceneHome",
|
|
25819
|
+
value: function fitCameraToSceneHome() {
|
|
25820
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
25821
|
+
return this.fitCameraToScene(_objectSpread2(_objectSpread2({}, options), {}, {
|
|
25822
|
+
direction: DEFAULT_HOME_VIEW_DIRECTION,
|
|
25823
|
+
groundLevel: true
|
|
25824
|
+
}));
|
|
25825
|
+
}
|
|
25826
|
+
|
|
25827
|
+
/**
|
|
25828
|
+
* Toggle camera auto-rotation on/off
|
|
25829
|
+
*
|
|
25830
|
+
* @returns {boolean} The new auto-rotation state
|
|
25831
|
+
*/
|
|
25832
|
+
}, {
|
|
25833
|
+
key: "toggleCameraRotation",
|
|
25834
|
+
value: function toggleCameraRotation() {
|
|
25835
|
+
var component = this.sceneViewer;
|
|
25836
|
+
if (!component.controls || !component.sceneInitializationManager) {
|
|
25837
|
+
console.warn('⚠️ Cannot toggle camera rotation: missing controls or sceneInitializationManager');
|
|
25838
|
+
return false;
|
|
25839
|
+
}
|
|
25840
|
+
|
|
25841
|
+
// Use the sceneInitializationManager to toggle auto-rotation
|
|
25842
|
+
var isAutoRotating = component.sceneInitializationManager.toggleAutoRotation();
|
|
25843
|
+
|
|
25844
|
+
// Update our internal state
|
|
25845
|
+
this._isAutoRotating = isAutoRotating;
|
|
25846
|
+
|
|
25847
|
+
// Set autoRotate speed if needed (using the stored preference)
|
|
25848
|
+
if (isAutoRotating && component.controls.autoRotateSpeed !== this.autoRotateSpeed) {
|
|
25849
|
+
component.controls.autoRotateSpeed = this.autoRotateSpeed;
|
|
25850
|
+
}
|
|
25851
|
+
console.log("\uD83D\uDD04 Camera auto-rotation ".concat(isAutoRotating ? 'enabled' : 'disabled', " via CameraControlsManager"));
|
|
25852
|
+
return isAutoRotating;
|
|
25853
|
+
}
|
|
25854
|
+
|
|
25855
|
+
/**
|
|
25856
|
+
* Get the current auto-rotation state
|
|
25857
|
+
*
|
|
25858
|
+
* @returns {boolean} Whether auto-rotation is enabled
|
|
25859
|
+
*/
|
|
25860
|
+
}, {
|
|
25861
|
+
key: "isAutoRotating",
|
|
25862
|
+
value: function isAutoRotating() {
|
|
25863
|
+
// If controls exist, sync our state with actual control state
|
|
25864
|
+
if (this.sceneViewer.controls) {
|
|
25865
|
+
this._isAutoRotating = this.sceneViewer.controls.autoRotate;
|
|
25866
|
+
}
|
|
25867
|
+
return this._isAutoRotating;
|
|
25868
|
+
}
|
|
25869
|
+
|
|
25870
|
+
/**
|
|
25871
|
+
* Directly enable or disable camera auto-rotation
|
|
25872
|
+
*
|
|
25873
|
+
* @param {boolean} enable - Whether to enable auto-rotation
|
|
25874
|
+
* @returns {boolean} The new auto-rotation state
|
|
25875
|
+
*/
|
|
25876
|
+
}, {
|
|
25877
|
+
key: "setAutoRotation",
|
|
25878
|
+
value: function setAutoRotation(enable) {
|
|
25879
|
+
var component = this.sceneViewer;
|
|
25880
|
+
if (component.sceneInitializationManager) {
|
|
25881
|
+
var result = component.sceneInitializationManager.toggleAutoRotation(enable);
|
|
25882
|
+
this._isAutoRotating = result;
|
|
25883
|
+
return result;
|
|
25884
|
+
}
|
|
25885
|
+
return false;
|
|
25886
|
+
}
|
|
25887
|
+
}]);
|
|
25888
|
+
}();
|
|
25889
|
+
|
|
25507
25890
|
var SceneInitializationManager = /*#__PURE__*/function () {
|
|
25508
25891
|
function SceneInitializationManager(sceneViewer) {
|
|
25509
25892
|
_classCallCheck(this, SceneInitializationManager);
|
|
@@ -25531,7 +25914,7 @@ var SceneInitializationManager = /*#__PURE__*/function () {
|
|
|
25531
25914
|
containerWidth = containerRect.width;
|
|
25532
25915
|
containerHeight = containerRect.height; // Create camera (Z-up coordinate system with flipped Y)
|
|
25533
25916
|
component.camera = new THREE__namespace.PerspectiveCamera(50, containerWidth / containerHeight, 0.01, 1000);
|
|
25534
|
-
component.camera.position.set(
|
|
25917
|
+
component.camera.position.set(DEFAULT_HOME_VIEW_DIRECTION.x, DEFAULT_HOME_VIEW_DIRECTION.y, HOME_EMPTY_CAMERA_HEIGHT_ABOVE_GROUND);
|
|
25535
25918
|
component.camera.up.set(0, 0, 1); // Set Z as up vector
|
|
25536
25919
|
|
|
25537
25920
|
// Create renderer
|
|
@@ -29225,204 +29608,344 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
29225
29608
|
}
|
|
29226
29609
|
|
|
29227
29610
|
/**
|
|
29228
|
-
* Enrich
|
|
29229
|
-
*
|
|
29230
|
-
*
|
|
29611
|
+
* Enrich sceneData with worldBoundingBox for segments and components
|
|
29612
|
+
* Connectors remain with just position information.
|
|
29613
|
+
*
|
|
29614
|
+
* Uses _bboxCache to avoid recomputing filtered / io-device bboxes
|
|
29615
|
+
* when the underlying object's world matrix has not changed.
|
|
29616
|
+
*
|
|
29617
|
+
* @param {Object} sceneData - Original scene data
|
|
29618
|
+
* @returns {Object} Enriched scene data (shallow copy with modifications)
|
|
29231
29619
|
* @private
|
|
29232
29620
|
*/
|
|
29233
29621
|
}, {
|
|
29234
29622
|
key: "_enrichSceneDataWithBoundingBoxes",
|
|
29235
29623
|
value: function _enrichSceneDataWithBoundingBoxes(sceneData) {
|
|
29236
29624
|
var _this4 = this;
|
|
29237
|
-
|
|
29238
|
-
|
|
29239
|
-
|
|
29240
|
-
|
|
29241
|
-
|
|
29242
|
-
|
|
29625
|
+
// Create a shallow copy of sceneData structure
|
|
29626
|
+
var enriched = _objectSpread2({}, sceneData);
|
|
29627
|
+
if (!sceneData.children || !Array.isArray(sceneData.children)) {
|
|
29628
|
+
console.warn('⚠️ sceneData has no children array');
|
|
29629
|
+
return enriched;
|
|
29630
|
+
}
|
|
29243
29631
|
|
|
29632
|
+
// Process children to add worldBoundingBox to segments and components
|
|
29633
|
+
enriched.children = sceneData.children.map(function (child) {
|
|
29244
29634
|
// Skip computed objects ( elbows etc )
|
|
29245
|
-
if (
|
|
29246
|
-
return
|
|
29635
|
+
if (child.userData && (child.userData.isComputed === true || child.userData.objectType === 'elbow')) {
|
|
29636
|
+
return child;
|
|
29247
29637
|
}
|
|
29248
29638
|
|
|
29249
|
-
//
|
|
29250
|
-
if (
|
|
29251
|
-
|
|
29639
|
+
// Enrich segments (check if objectType is 'segment' in userData)
|
|
29640
|
+
if (child.userData && child.userData.objectType === 'segment') {
|
|
29641
|
+
// Find the actual segment object in the scene
|
|
29642
|
+
var segmentObject = _this4.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
29252
29643
|
if (segmentObject) {
|
|
29644
|
+
// ── Cache check ──
|
|
29253
29645
|
var hash = _this4._matrixHash(segmentObject);
|
|
29254
|
-
var cached = _this4._bboxCache.get(
|
|
29646
|
+
var cached = _this4._bboxCache.get(child.uuid);
|
|
29255
29647
|
if (cached && cached.matrixHash === hash && cached.segmentBBox) {
|
|
29256
|
-
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
|
|
29260
|
-
var worldBBox = new THREE__namespace.Box3().setFromObject(segmentObject);
|
|
29261
|
-
var bboxData = {
|
|
29262
|
-
min: [worldBBox.min.x, worldBBox.min.y, worldBBox.min.z],
|
|
29263
|
-
max: [worldBBox.max.x, worldBBox.max.y, worldBBox.max.z]
|
|
29264
|
-
};
|
|
29265
|
-
_this4._bboxCache.set(node.uuid, {
|
|
29266
|
-
matrixHash: hash,
|
|
29267
|
-
segmentBBox: bboxData
|
|
29268
|
-
});
|
|
29269
|
-
enrichedNode.userData = _objectSpread2(_objectSpread2({}, node.userData), {}, {
|
|
29270
|
-
worldBoundingBox: bboxData
|
|
29648
|
+
return _objectSpread2(_objectSpread2({}, child), {}, {
|
|
29649
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
29650
|
+
worldBoundingBox: cached.segmentBBox
|
|
29651
|
+
})
|
|
29271
29652
|
});
|
|
29272
29653
|
}
|
|
29654
|
+
|
|
29655
|
+
// Compute world bounding box
|
|
29656
|
+
var worldBBox = new THREE__namespace.Box3().setFromObject(segmentObject);
|
|
29657
|
+
var bboxData = {
|
|
29658
|
+
min: [worldBBox.min.x, worldBBox.min.y, worldBBox.min.z],
|
|
29659
|
+
max: [worldBBox.max.x, worldBBox.max.y, worldBBox.max.z]
|
|
29660
|
+
};
|
|
29661
|
+
|
|
29662
|
+
// Store in cache
|
|
29663
|
+
_this4._bboxCache.set(child.uuid, {
|
|
29664
|
+
matrixHash: hash,
|
|
29665
|
+
segmentBBox: bboxData
|
|
29666
|
+
});
|
|
29667
|
+
return _objectSpread2(_objectSpread2({}, child), {}, {
|
|
29668
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
29669
|
+
worldBoundingBox: bboxData
|
|
29670
|
+
})
|
|
29671
|
+
});
|
|
29672
|
+
} else {
|
|
29673
|
+
console.warn("\u26A0\uFE0F Could not find segment object in scene: ".concat(child.uuid));
|
|
29273
29674
|
}
|
|
29274
29675
|
}
|
|
29275
29676
|
|
|
29276
|
-
//
|
|
29277
|
-
|
|
29278
|
-
|
|
29677
|
+
// Enrich components (check if objectType is 'component' in userData)
|
|
29678
|
+
if (child.userData && child.userData.objectType === 'component') {
|
|
29679
|
+
// Find the actual component object in the scene
|
|
29680
|
+
var componentObject = _this4.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
29279
29681
|
if (componentObject) {
|
|
29682
|
+
// Explicitly update matrices for this component subtree before computing bounding boxes
|
|
29280
29683
|
componentObject.updateMatrixWorld(true);
|
|
29684
|
+
|
|
29685
|
+
// ── Cache check ──
|
|
29281
29686
|
var _hash = _this4._matrixHash(componentObject);
|
|
29282
|
-
var _cached = _this4._bboxCache.get(
|
|
29687
|
+
var _cached = _this4._bboxCache.get(child.uuid);
|
|
29283
29688
|
if (_cached && _cached.matrixHash === _hash && _cached.filteredBBox) {
|
|
29284
|
-
|
|
29285
|
-
|
|
29286
|
-
|
|
29287
|
-
|
|
29288
|
-
|
|
29289
|
-
|
|
29290
|
-
|
|
29291
|
-
|
|
29292
|
-
|
|
29293
|
-
|
|
29294
|
-
|
|
29295
|
-
|
|
29296
|
-
|
|
29689
|
+
// Rebuild enriched child from cached data
|
|
29690
|
+
var _enrichedChild = _objectSpread2(_objectSpread2({}, child), {}, {
|
|
29691
|
+
// Sync live transform even on cache hit just in case the manifest (child) is stale
|
|
29692
|
+
position: {
|
|
29693
|
+
x: componentObject.position.x,
|
|
29694
|
+
y: componentObject.position.y,
|
|
29695
|
+
z: componentObject.position.z
|
|
29696
|
+
},
|
|
29697
|
+
rotation: {
|
|
29698
|
+
x: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.x),
|
|
29699
|
+
y: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.y),
|
|
29700
|
+
z: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.z)
|
|
29701
|
+
},
|
|
29702
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
29703
|
+
worldBoundingBox: _cached.filteredBBox,
|
|
29704
|
+
position: [componentObject.position.x, componentObject.position.y, componentObject.position.z]
|
|
29705
|
+
})
|
|
29297
29706
|
});
|
|
29298
|
-
|
|
29299
|
-
|
|
29300
|
-
|
|
29301
|
-
|
|
29302
|
-
|
|
29303
|
-
|
|
29707
|
+
if (_cached.ioDeviceBBoxes && _cached.ioDeviceBBoxes.length > 0) {
|
|
29708
|
+
if (!_enrichedChild.children) _enrichedChild.children = [];
|
|
29709
|
+
_cached.ioDeviceBBoxes.forEach(function (deviceBBox) {
|
|
29710
|
+
var existingIndex = _enrichedChild.children.findIndex(function (c) {
|
|
29711
|
+
return c.uuid === deviceBBox.uuid;
|
|
29712
|
+
});
|
|
29713
|
+
if (existingIndex >= 0) {
|
|
29714
|
+
_enrichedChild.children[existingIndex] = _objectSpread2(_objectSpread2({}, _enrichedChild.children[existingIndex]), {}, {
|
|
29715
|
+
position: {
|
|
29716
|
+
x: deviceBBox.userData.position[0],
|
|
29717
|
+
y: deviceBBox.userData.position[1],
|
|
29718
|
+
z: deviceBBox.userData.position[2]
|
|
29719
|
+
},
|
|
29720
|
+
userData: _objectSpread2(_objectSpread2({}, _enrichedChild.children[existingIndex].userData), {}, {
|
|
29721
|
+
objectType: 'io-device',
|
|
29722
|
+
worldBoundingBox: deviceBBox.worldBoundingBox,
|
|
29723
|
+
position: deviceBBox.userData.position
|
|
29724
|
+
})
|
|
29725
|
+
});
|
|
29726
|
+
} else {
|
|
29727
|
+
_enrichedChild.children.push({
|
|
29728
|
+
uuid: deviceBBox.uuid,
|
|
29729
|
+
position: {
|
|
29730
|
+
x: deviceBBox.userData.position[0],
|
|
29731
|
+
y: deviceBBox.userData.position[1],
|
|
29732
|
+
z: deviceBBox.userData.position[2]
|
|
29733
|
+
},
|
|
29734
|
+
userData: _objectSpread2(_objectSpread2({}, deviceBBox.userData), {}, {
|
|
29735
|
+
worldBoundingBox: deviceBBox.worldBoundingBox,
|
|
29736
|
+
position: deviceBBox.userData.position
|
|
29737
|
+
}),
|
|
29738
|
+
children: []
|
|
29739
|
+
});
|
|
29740
|
+
}
|
|
29304
29741
|
});
|
|
29305
29742
|
}
|
|
29306
|
-
|
|
29307
|
-
|
|
29308
|
-
|
|
29743
|
+
|
|
29744
|
+
// Also reinject connectors from cache
|
|
29745
|
+
if (_cached.connectorBBoxes && _cached.connectorBBoxes.length > 0) {
|
|
29746
|
+
if (!_enrichedChild.children) _enrichedChild.children = [];
|
|
29747
|
+
_cached.connectorBBoxes.forEach(function (connBBox) {
|
|
29748
|
+
var existingIndex = _enrichedChild.children.findIndex(function (c) {
|
|
29749
|
+
return c.uuid === connBBox.uuid;
|
|
29750
|
+
});
|
|
29751
|
+
if (existingIndex >= 0) {
|
|
29752
|
+
_enrichedChild.children[existingIndex] = _objectSpread2(_objectSpread2({}, _enrichedChild.children[existingIndex]), {}, {
|
|
29753
|
+
position: {
|
|
29754
|
+
x: connBBox.userData.position[0],
|
|
29755
|
+
y: connBBox.userData.position[1],
|
|
29756
|
+
z: connBBox.userData.position[2]
|
|
29757
|
+
},
|
|
29758
|
+
userData: _objectSpread2(_objectSpread2({}, _enrichedChild.children[existingIndex].userData), {}, {
|
|
29759
|
+
worldBoundingBox: connBBox.worldBoundingBox,
|
|
29760
|
+
position: connBBox.userData.position
|
|
29761
|
+
})
|
|
29762
|
+
});
|
|
29763
|
+
} else {
|
|
29764
|
+
_enrichedChild.children.push({
|
|
29765
|
+
uuid: connBBox.uuid,
|
|
29766
|
+
position: {
|
|
29767
|
+
x: connBBox.userData.position[0],
|
|
29768
|
+
y: connBBox.userData.position[1],
|
|
29769
|
+
z: connBBox.userData.position[2]
|
|
29770
|
+
},
|
|
29771
|
+
userData: _objectSpread2(_objectSpread2({}, connBBox.userData), {}, {
|
|
29772
|
+
worldBoundingBox: connBBox.worldBoundingBox,
|
|
29773
|
+
position: connBBox.userData.position
|
|
29774
|
+
}),
|
|
29775
|
+
children: []
|
|
29776
|
+
});
|
|
29777
|
+
}
|
|
29309
29778
|
});
|
|
29310
29779
|
}
|
|
29311
|
-
|
|
29312
|
-
|
|
29313
|
-
|
|
29314
|
-
|
|
29315
|
-
|
|
29316
|
-
|
|
29317
|
-
|
|
29780
|
+
return _enrichedChild;
|
|
29781
|
+
}
|
|
29782
|
+
|
|
29783
|
+
// Compute FILTERED bounding box — excludes io-device and connector subtrees
|
|
29784
|
+
// so the component body bbox is tight-fitting and doesn't envelop attached devices
|
|
29785
|
+
var filteredBBox = computeFilteredBoundingBox(componentObject, ['io-device', 'connector']);
|
|
29786
|
+
console.log("\uD83D\uDD04 Updated worldBoundingBox for component ".concat(child.uuid, " (filtered): min=[").concat(filteredBBox.min.x.toFixed(2), ", ").concat(filteredBBox.min.y.toFixed(2), ", ").concat(filteredBBox.min.z.toFixed(2), "], max=[").concat(filteredBBox.max.x.toFixed(2), ", ").concat(filteredBBox.max.y.toFixed(2), ", ").concat(filteredBBox.max.z.toFixed(2), "]"));
|
|
29787
|
+
var _bboxData = {
|
|
29788
|
+
min: [filteredBBox.min.x, filteredBBox.min.y, filteredBBox.min.z],
|
|
29789
|
+
max: [filteredBBox.max.x, filteredBBox.max.y, filteredBBox.max.z]
|
|
29790
|
+
};
|
|
29791
|
+
|
|
29792
|
+
// Build the enriched component entry
|
|
29793
|
+
var enrichedChild = _objectSpread2(_objectSpread2({}, child), {}, {
|
|
29794
|
+
// Sync live transform to ensure pathfinder has latest coordinates
|
|
29795
|
+
position: {
|
|
29318
29796
|
x: componentObject.position.x,
|
|
29319
29797
|
y: componentObject.position.y,
|
|
29320
29798
|
z: componentObject.position.z
|
|
29321
|
-
}
|
|
29322
|
-
|
|
29799
|
+
},
|
|
29800
|
+
rotation: {
|
|
29323
29801
|
x: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.x),
|
|
29324
29802
|
y: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.y),
|
|
29325
29803
|
z: THREE__namespace.MathUtils.radToDeg(componentObject.rotation.z)
|
|
29326
|
-
}
|
|
29327
|
-
|
|
29804
|
+
},
|
|
29805
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
29328
29806
|
worldBoundingBox: _bboxData,
|
|
29329
29807
|
position: [componentObject.position.x, componentObject.position.y, componentObject.position.z]
|
|
29808
|
+
})
|
|
29809
|
+
});
|
|
29810
|
+
|
|
29811
|
+
// Compute separate bounding boxes for each attached io-device
|
|
29812
|
+
var ioDeviceBBoxes = computeIODeviceBoundingBoxes(componentObject);
|
|
29813
|
+
if (ioDeviceBBoxes.length > 0) {
|
|
29814
|
+
// Ensure children array exists (may already contain connectors)
|
|
29815
|
+
if (!enrichedChild.children) {
|
|
29816
|
+
enrichedChild.children = [];
|
|
29817
|
+
}
|
|
29818
|
+
|
|
29819
|
+
// Inject io-device entries with their own worldBoundingBox
|
|
29820
|
+
ioDeviceBBoxes.forEach(function (deviceBBox) {
|
|
29821
|
+
var existingIndex = enrichedChild.children.findIndex(function (c) {
|
|
29822
|
+
return c.uuid === deviceBBox.uuid;
|
|
29823
|
+
});
|
|
29824
|
+
if (existingIndex >= 0) {
|
|
29825
|
+
enrichedChild.children[existingIndex] = _objectSpread2(_objectSpread2({}, enrichedChild.children[existingIndex]), {}, {
|
|
29826
|
+
position: {
|
|
29827
|
+
x: deviceBBox.userData.position[0],
|
|
29828
|
+
y: deviceBBox.userData.position[1],
|
|
29829
|
+
z: deviceBBox.userData.position[2]
|
|
29830
|
+
},
|
|
29831
|
+
userData: _objectSpread2(_objectSpread2({}, enrichedChild.children[existingIndex].userData), {}, {
|
|
29832
|
+
objectType: 'io-device',
|
|
29833
|
+
worldBoundingBox: deviceBBox.worldBoundingBox,
|
|
29834
|
+
position: deviceBBox.userData.position
|
|
29835
|
+
})
|
|
29836
|
+
});
|
|
29837
|
+
} else {
|
|
29838
|
+
enrichedChild.children.push({
|
|
29839
|
+
uuid: deviceBBox.uuid,
|
|
29840
|
+
position: {
|
|
29841
|
+
x: deviceBBox.userData.position[0],
|
|
29842
|
+
y: deviceBBox.userData.position[1],
|
|
29843
|
+
z: deviceBBox.userData.position[2]
|
|
29844
|
+
},
|
|
29845
|
+
userData: _objectSpread2(_objectSpread2({}, deviceBBox.userData), {}, {
|
|
29846
|
+
worldBoundingBox: deviceBBox.worldBoundingBox,
|
|
29847
|
+
position: deviceBBox.userData.position
|
|
29848
|
+
}),
|
|
29849
|
+
children: []
|
|
29850
|
+
});
|
|
29851
|
+
}
|
|
29852
|
+
console.log("\uD83D\uDCE6 Injected io-device bbox for ".concat(deviceBBox.uuid, ": min=[").concat(deviceBBox.worldBoundingBox.min.map(function (v) {
|
|
29853
|
+
return v.toFixed(2);
|
|
29854
|
+
}).join(', '), "], max=[").concat(deviceBBox.worldBoundingBox.max.map(function (v) {
|
|
29855
|
+
return v.toFixed(2);
|
|
29856
|
+
}).join(', '), "]"));
|
|
29330
29857
|
});
|
|
29331
|
-
|
|
29332
|
-
|
|
29333
|
-
|
|
29334
|
-
|
|
29335
|
-
|
|
29336
|
-
|
|
29337
|
-
|
|
29338
|
-
|
|
29339
|
-
|
|
29340
|
-
|
|
29341
|
-
|
|
29342
|
-
|
|
29343
|
-
|
|
29344
|
-
|
|
29858
|
+
console.log("\uD83D\uDCE6 Injected ".concat(ioDeviceBBoxes.length, " io-device bounding box(es) for component ").concat(child.uuid));
|
|
29859
|
+
}
|
|
29860
|
+
|
|
29861
|
+
// PHASE 2: Enrich Connectors (CRITICAL for pathfinding API)
|
|
29862
|
+
// Also compute world bounding boxes for connectors and inject into children.
|
|
29863
|
+
// This ensures endpoints have world coordinates in sceneDataCopy.
|
|
29864
|
+
var connectorBBoxes = computeConnectorBoundingBoxes(componentObject);
|
|
29865
|
+
if (connectorBBoxes.length > 0) {
|
|
29866
|
+
if (!enrichedChild.children) enrichedChild.children = [];
|
|
29867
|
+
connectorBBoxes.forEach(function (connBBox) {
|
|
29868
|
+
var existingIndex = enrichedChild.children.findIndex(function (c) {
|
|
29869
|
+
return c.uuid === connBBox.uuid;
|
|
29870
|
+
});
|
|
29871
|
+
if (existingIndex >= 0) {
|
|
29872
|
+
enrichedChild.children[existingIndex] = _objectSpread2(_objectSpread2({}, enrichedChild.children[existingIndex]), {}, {
|
|
29873
|
+
position: {
|
|
29874
|
+
x: connBBox.userData.position[0],
|
|
29875
|
+
y: connBBox.userData.position[1],
|
|
29876
|
+
z: connBBox.userData.position[2]
|
|
29877
|
+
},
|
|
29878
|
+
userData: _objectSpread2(_objectSpread2({}, enrichedChild.children[existingIndex].userData), {}, {
|
|
29879
|
+
worldBoundingBox: connBBox.worldBoundingBox,
|
|
29880
|
+
position: connBBox.userData.position
|
|
29881
|
+
})
|
|
29882
|
+
});
|
|
29883
|
+
} else {
|
|
29884
|
+
enrichedChild.children.push({
|
|
29885
|
+
uuid: connBBox.uuid,
|
|
29886
|
+
position: {
|
|
29887
|
+
x: connBBox.userData.position[0],
|
|
29888
|
+
y: connBBox.userData.position[1],
|
|
29889
|
+
z: connBBox.userData.position[2]
|
|
29890
|
+
},
|
|
29891
|
+
userData: _objectSpread2(_objectSpread2({}, connBBox.userData), {}, {
|
|
29892
|
+
worldBoundingBox: connBBox.worldBoundingBox,
|
|
29893
|
+
position: connBBox.userData.position
|
|
29894
|
+
}),
|
|
29895
|
+
children: []
|
|
29896
|
+
});
|
|
29897
|
+
}
|
|
29345
29898
|
});
|
|
29346
29899
|
}
|
|
29900
|
+
|
|
29901
|
+
// Store in cache
|
|
29902
|
+
_this4._bboxCache.set(child.uuid, {
|
|
29903
|
+
matrixHash: _hash,
|
|
29904
|
+
filteredBBox: _bboxData,
|
|
29905
|
+
ioDeviceBBoxes: ioDeviceBBoxes,
|
|
29906
|
+
connectorBBoxes: connectorBBoxes
|
|
29907
|
+
});
|
|
29908
|
+
return enrichedChild;
|
|
29909
|
+
} else {
|
|
29910
|
+
console.warn("\u26A0\uFE0F Could not find component object in scene: ".concat(child.uuid));
|
|
29347
29911
|
}
|
|
29348
29912
|
}
|
|
29349
29913
|
|
|
29350
|
-
//
|
|
29351
|
-
|
|
29352
|
-
|
|
29353
|
-
|
|
29914
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
29915
|
+
// PHASE 3: Handle top-level Gateways and Connectors
|
|
29916
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
29917
|
+
if (child.userData && (child.userData.objectType === 'gateway' || child.userData.objectType === 'connector')) {
|
|
29918
|
+
var _child$userData;
|
|
29919
|
+
var object = _this4.sceneViewer.scene.getObjectByProperty('uuid', child.uuid) || _this4.sceneViewer.scene.getObjectByProperty('uuid', (_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid);
|
|
29354
29920
|
if (object) {
|
|
29355
29921
|
var worldPos = new THREE__namespace.Vector3();
|
|
29356
29922
|
object.getWorldPosition(worldPos);
|
|
29357
|
-
|
|
29358
|
-
|
|
29359
|
-
|
|
29360
|
-
|
|
29361
|
-
|
|
29362
|
-
|
|
29363
|
-
|
|
29923
|
+
return _objectSpread2(_objectSpread2({}, child), {}, {
|
|
29924
|
+
// Sync live transform to ensure pathfinder has latest coordinates
|
|
29925
|
+
position: {
|
|
29926
|
+
x: worldPos.x,
|
|
29927
|
+
y: worldPos.y,
|
|
29928
|
+
z: worldPos.z
|
|
29929
|
+
},
|
|
29930
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
29931
|
+
position: [worldPos.x, worldPos.y, worldPos.z]
|
|
29932
|
+
})
|
|
29364
29933
|
});
|
|
29365
|
-
|
|
29366
|
-
// If it's a connector, also sync direction
|
|
29367
|
-
if (node.userData.objectType === 'connector') {
|
|
29368
|
-
var worldDir = new THREE__namespace.Vector3(0, 0, 1);
|
|
29369
|
-
if (node.userData.direction) worldDir.set(node.userData.direction[0], node.userData.direction[1], node.userData.direction[2]);
|
|
29370
|
-
worldDir.applyQuaternion(object.getWorldQuaternion(new THREE__namespace.Quaternion())).normalize();
|
|
29371
|
-
enrichedNode.userData.direction = [worldDir.x, worldDir.y, worldDir.z];
|
|
29372
|
-
}
|
|
29373
29934
|
}
|
|
29374
29935
|
}
|
|
29375
29936
|
|
|
29376
|
-
//
|
|
29377
|
-
|
|
29378
|
-
|
|
29379
|
-
|
|
29380
|
-
return enrichedNode;
|
|
29381
|
-
};
|
|
29382
|
-
|
|
29383
|
-
// Handle root being an array or object
|
|
29384
|
-
if (Array.isArray(sceneData)) {
|
|
29385
|
-
return sceneData.map(_enrichNode);
|
|
29386
|
-
} else if (sceneData.children && Array.isArray(sceneData.children)) {
|
|
29387
|
-
var enrichedRoot = _objectSpread2({}, sceneData);
|
|
29388
|
-
enrichedRoot.children = sceneData.children.map(_enrichNode);
|
|
29389
|
-
return enrichedRoot;
|
|
29390
|
-
} else {
|
|
29391
|
-
return _enrichNode(sceneData);
|
|
29392
|
-
}
|
|
29937
|
+
// For non-segments and non-components (and if object search failed), return as-is
|
|
29938
|
+
return child;
|
|
29939
|
+
});
|
|
29940
|
+
return enriched;
|
|
29393
29941
|
}
|
|
29394
29942
|
|
|
29395
29943
|
/**
|
|
29396
|
-
*
|
|
29397
|
-
* @private
|
|
29944
|
+
* Core pathfinding logic shared across initialization and updates
|
|
29398
29945
|
*/
|
|
29399
|
-
}, {
|
|
29400
|
-
key: "_mergeEnrichedChild",
|
|
29401
|
-
value: function _mergeEnrichedChild(childrenArray, enrichedData) {
|
|
29402
|
-
var existingIndex = childrenArray.findIndex(function (c) {
|
|
29403
|
-
return c.uuid === enrichedData.uuid;
|
|
29404
|
-
});
|
|
29405
|
-
var nodeToMerge = {
|
|
29406
|
-
uuid: enrichedData.uuid,
|
|
29407
|
-
position: {
|
|
29408
|
-
x: enrichedData.userData.position[0],
|
|
29409
|
-
y: enrichedData.userData.position[1],
|
|
29410
|
-
z: enrichedData.userData.position[2]
|
|
29411
|
-
},
|
|
29412
|
-
userData: _objectSpread2(_objectSpread2({}, enrichedData.userData), {}, {
|
|
29413
|
-
worldBoundingBox: enrichedData.worldBoundingBox
|
|
29414
|
-
}),
|
|
29415
|
-
children: []
|
|
29416
|
-
};
|
|
29417
|
-
if (existingIndex >= 0) {
|
|
29418
|
-
childrenArray[existingIndex] = _objectSpread2(_objectSpread2({}, childrenArray[existingIndex]), nodeToMerge);
|
|
29419
|
-
} else {
|
|
29420
|
-
childrenArray.push(nodeToMerge);
|
|
29421
|
-
}
|
|
29422
|
-
}
|
|
29423
29946
|
}, {
|
|
29424
29947
|
key: "_executePathfinding",
|
|
29425
|
-
value: function () {
|
|
29948
|
+
value: (function () {
|
|
29426
29949
|
var _executePathfinding2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(sceneData, connections) {
|
|
29427
29950
|
var _this5 = this,
|
|
29428
29951
|
_sceneDataCopy$childr,
|
|
@@ -29597,7 +30120,7 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
29597
30120
|
return _executePathfinding2.apply(this, arguments);
|
|
29598
30121
|
}
|
|
29599
30122
|
return _executePathfinding;
|
|
29600
|
-
}()
|
|
30123
|
+
}())
|
|
29601
30124
|
}, {
|
|
29602
30125
|
key: "getSimplifiedSceneData",
|
|
29603
30126
|
value: function getSimplifiedSceneData() {
|
|
@@ -33855,6 +34378,19 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
33855
34378
|
if (!(data !== null && data !== void 0 && (_data$scene2 = data.scene) !== null && _data$scene2 !== void 0 && _data$scene2.children) || !componentDictionary) {
|
|
33856
34379
|
return;
|
|
33857
34380
|
}
|
|
34381
|
+
|
|
34382
|
+
// Collect every connector uuid referenced by the scene's connections so we
|
|
34383
|
+
// can inject connectors under the SAME uuid scheme the scene actually uses.
|
|
34384
|
+
// Two schemes exist in the wild:
|
|
34385
|
+
// - Preferred (runtime add path + minimal export): `${componentUuid}_${dictConnectorUuid}`
|
|
34386
|
+
// - Legacy (older hand-authored scenes): `${componentUuid}-CONNECTOR-${index+1}`
|
|
34387
|
+
var connectionEndpoints = new Set();
|
|
34388
|
+
if (Array.isArray(data.connections)) {
|
|
34389
|
+
data.connections.forEach(function (conn) {
|
|
34390
|
+
if (conn !== null && conn !== void 0 && conn.from) connectionEndpoints.add(conn.from);
|
|
34391
|
+
if (conn !== null && conn !== void 0 && conn.to) connectionEndpoints.add(conn.to);
|
|
34392
|
+
});
|
|
34393
|
+
}
|
|
33858
34394
|
var componentsProcessed = 0;
|
|
33859
34395
|
var connectorsInjected = 0;
|
|
33860
34396
|
data.scene.children.forEach(function (child) {
|
|
@@ -33877,9 +34413,18 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
33877
34413
|
|
|
33878
34414
|
// Deep clone the connector children from the dictionary
|
|
33879
34415
|
child.children = dictEntry.children.map(function (connector, index) {
|
|
33880
|
-
//
|
|
33881
|
-
//
|
|
33882
|
-
|
|
34416
|
+
// Choose the connector uuid that matches the scheme the scene's
|
|
34417
|
+
// connections reference. Prefer `${componentUuid}_${dictConnectorUuid}`
|
|
34418
|
+
// (sandbox add path + minimal export); fall back to the legacy
|
|
34419
|
+
// index-based scheme `${componentUuid}-CONNECTOR-${index+1}` when the
|
|
34420
|
+
// connections reference that form. If neither is referenced (e.g. an
|
|
34421
|
+
// unconnected connector), default to the preferred scheme.
|
|
34422
|
+
var legacyUuid = "".concat(child.uuid, "-CONNECTOR-").concat(index + 1);
|
|
34423
|
+
var preferredUuid = connector.uuid ? "".concat(child.uuid, "_").concat(connector.uuid) : legacyUuid;
|
|
34424
|
+
var connectorUuid = preferredUuid;
|
|
34425
|
+
if (!connectionEndpoints.has(preferredUuid) && connectionEndpoints.has(legacyUuid)) {
|
|
34426
|
+
connectorUuid = legacyUuid;
|
|
34427
|
+
}
|
|
33883
34428
|
|
|
33884
34429
|
// Clone connector with deep copy of userData
|
|
33885
34430
|
var clonedConnector = _objectSpread2(_objectSpread2({}, connector), {}, {
|
|
@@ -34085,6 +34630,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
34085
34630
|
}, {
|
|
34086
34631
|
key: "_finalizeScene",
|
|
34087
34632
|
value: function _finalizeScene(data, crosscubeTextureSet, isImported) {
|
|
34633
|
+
var _component$cameraCont;
|
|
34088
34634
|
var component = this.sceneViewer;
|
|
34089
34635
|
component.currentSceneData = data;
|
|
34090
34636
|
component.crosscubeTextureSet = crosscubeTextureSet;
|
|
@@ -34096,6 +34642,14 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
34096
34642
|
}
|
|
34097
34643
|
this._setTransformControlsState(true, false); // Enable but keep hidden initially
|
|
34098
34644
|
}
|
|
34645
|
+
|
|
34646
|
+
// Frame the camera so all components fit perfectly in view (low, ground-level angle)
|
|
34647
|
+
if ((_component$cameraCont = component.cameraControlsManager) !== null && _component$cameraCont !== void 0 && _component$cameraCont.fitCameraToScene) {
|
|
34648
|
+
component.cameraControlsManager.fitCameraToScene({
|
|
34649
|
+
direction: DEFAULT_HOME_VIEW_DIRECTION,
|
|
34650
|
+
groundLevel: true
|
|
34651
|
+
});
|
|
34652
|
+
}
|
|
34099
34653
|
}
|
|
34100
34654
|
|
|
34101
34655
|
/**
|
|
@@ -34978,82 +35532,6 @@ var AnimationManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
34978
35532
|
}]);
|
|
34979
35533
|
}(BaseDisposable);
|
|
34980
35534
|
|
|
34981
|
-
/**
|
|
34982
|
-
* CameraControlsManager
|
|
34983
|
-
* Handles camera movement, rotation, and other camera-specific controls
|
|
34984
|
-
*/
|
|
34985
|
-
|
|
34986
|
-
var CameraControlsManager = /*#__PURE__*/function () {
|
|
34987
|
-
function CameraControlsManager(component) {
|
|
34988
|
-
_classCallCheck(this, CameraControlsManager);
|
|
34989
|
-
this.sceneViewer = component;
|
|
34990
|
-
this.autoRotateSpeed = 1.0; // Default rotation speed
|
|
34991
|
-
this._isAutoRotating = false; // Internal state tracking
|
|
34992
|
-
}
|
|
34993
|
-
|
|
34994
|
-
/**
|
|
34995
|
-
* Toggle camera auto-rotation on/off
|
|
34996
|
-
*
|
|
34997
|
-
* @returns {boolean} The new auto-rotation state
|
|
34998
|
-
*/
|
|
34999
|
-
return _createClass(CameraControlsManager, [{
|
|
35000
|
-
key: "toggleCameraRotation",
|
|
35001
|
-
value: function toggleCameraRotation() {
|
|
35002
|
-
var component = this.sceneViewer;
|
|
35003
|
-
if (!component.controls || !component.sceneInitializationManager) {
|
|
35004
|
-
console.warn('⚠️ Cannot toggle camera rotation: missing controls or sceneInitializationManager');
|
|
35005
|
-
return false;
|
|
35006
|
-
}
|
|
35007
|
-
|
|
35008
|
-
// Use the sceneInitializationManager to toggle auto-rotation
|
|
35009
|
-
var isAutoRotating = component.sceneInitializationManager.toggleAutoRotation();
|
|
35010
|
-
|
|
35011
|
-
// Update our internal state
|
|
35012
|
-
this._isAutoRotating = isAutoRotating;
|
|
35013
|
-
|
|
35014
|
-
// Set autoRotate speed if needed (using the stored preference)
|
|
35015
|
-
if (isAutoRotating && component.controls.autoRotateSpeed !== this.autoRotateSpeed) {
|
|
35016
|
-
component.controls.autoRotateSpeed = this.autoRotateSpeed;
|
|
35017
|
-
}
|
|
35018
|
-
console.log("\uD83D\uDD04 Camera auto-rotation ".concat(isAutoRotating ? 'enabled' : 'disabled', " via CameraControlsManager"));
|
|
35019
|
-
return isAutoRotating;
|
|
35020
|
-
}
|
|
35021
|
-
|
|
35022
|
-
/**
|
|
35023
|
-
* Get the current auto-rotation state
|
|
35024
|
-
*
|
|
35025
|
-
* @returns {boolean} Whether auto-rotation is enabled
|
|
35026
|
-
*/
|
|
35027
|
-
}, {
|
|
35028
|
-
key: "isAutoRotating",
|
|
35029
|
-
value: function isAutoRotating() {
|
|
35030
|
-
// If controls exist, sync our state with actual control state
|
|
35031
|
-
if (this.sceneViewer.controls) {
|
|
35032
|
-
this._isAutoRotating = this.sceneViewer.controls.autoRotate;
|
|
35033
|
-
}
|
|
35034
|
-
return this._isAutoRotating;
|
|
35035
|
-
}
|
|
35036
|
-
|
|
35037
|
-
/**
|
|
35038
|
-
* Directly enable or disable camera auto-rotation
|
|
35039
|
-
*
|
|
35040
|
-
* @param {boolean} enable - Whether to enable auto-rotation
|
|
35041
|
-
* @returns {boolean} The new auto-rotation state
|
|
35042
|
-
*/
|
|
35043
|
-
}, {
|
|
35044
|
-
key: "setAutoRotation",
|
|
35045
|
-
value: function setAutoRotation(enable) {
|
|
35046
|
-
var component = this.sceneViewer;
|
|
35047
|
-
if (component.sceneInitializationManager) {
|
|
35048
|
-
var result = component.sceneInitializationManager.toggleAutoRotation(enable);
|
|
35049
|
-
this._isAutoRotating = result;
|
|
35050
|
-
return result;
|
|
35051
|
-
}
|
|
35052
|
-
return false;
|
|
35053
|
-
}
|
|
35054
|
-
}]);
|
|
35055
|
-
}();
|
|
35056
|
-
|
|
35057
35535
|
/**
|
|
35058
35536
|
* ComponentDragManager handles drag and drop from external UI elements to the 3D scene
|
|
35059
35537
|
*/
|
|
@@ -41119,7 +41597,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
41119
41597
|
* Initialize the CentralPlant manager
|
|
41120
41598
|
*
|
|
41121
41599
|
* @constructor
|
|
41122
|
-
* @version 0.3.
|
|
41600
|
+
* @version 0.3.50
|
|
41123
41601
|
* @updated 2025-10-22
|
|
41124
41602
|
*
|
|
41125
41603
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -42995,6 +43473,98 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
42995
43473
|
}
|
|
42996
43474
|
}
|
|
42997
43475
|
|
|
43476
|
+
/**
|
|
43477
|
+
* Get the world-space axis-aligned bounding box for a scene object.
|
|
43478
|
+
* @param {string|THREE.Object3D} objectOrId - The object's UUID/name, or the Three.js object itself
|
|
43479
|
+
* @param {Object} [options={}] - Bounding box options
|
|
43480
|
+
* @param {boolean} [options.filtered=true] - When true, exclude connector and io-device
|
|
43481
|
+
* subtrees so the box reflects the component body footprint. When false, the box
|
|
43482
|
+
* envelops all descendants (equivalent to THREE.Box3.setFromObject).
|
|
43483
|
+
* @param {string[]} [options.excludeTypes] - Override the userData.objectType values to
|
|
43484
|
+
* exclude (defaults to ['io-device', 'connector'] when filtered is true).
|
|
43485
|
+
* @returns {{min: {x,y,z}, max: {x,y,z}, size: {x,y,z}, center: {x,y,z}}|null}
|
|
43486
|
+
* The bounding box descriptor in world space, or null if the object can't be found
|
|
43487
|
+
* or has no geometry.
|
|
43488
|
+
* @description Computes a tight world-space bounding box for a component (or any scene
|
|
43489
|
+
* object). By default the component body is measured independently of its attached
|
|
43490
|
+
* connectors and io-devices, which is useful for layout and spacing operations.
|
|
43491
|
+
* @example
|
|
43492
|
+
* // Component body bounding box (excludes connectors / io-devices)
|
|
43493
|
+
* const bbox = centralPlant.getBoundingBox('PUMP-1');
|
|
43494
|
+
* console.log(bbox.size.x, bbox.size.y, bbox.size.z);
|
|
43495
|
+
*
|
|
43496
|
+
* @example
|
|
43497
|
+
* // Full bounding box including connectors and io-devices
|
|
43498
|
+
* const fullBox = centralPlant.getBoundingBox('PUMP-1', { filtered: false });
|
|
43499
|
+
*
|
|
43500
|
+
* @since 0.3.50
|
|
43501
|
+
*/
|
|
43502
|
+
}, {
|
|
43503
|
+
key: "getBoundingBox",
|
|
43504
|
+
value: function getBoundingBox(objectOrId) {
|
|
43505
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
43506
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
43507
|
+
console.warn('⚠️ getBoundingBox(): Scene viewer or scene not available');
|
|
43508
|
+
return null;
|
|
43509
|
+
}
|
|
43510
|
+
var _options$filtered = options.filtered,
|
|
43511
|
+
filtered = _options$filtered === void 0 ? true : _options$filtered,
|
|
43512
|
+
excludeTypes = options.excludeTypes;
|
|
43513
|
+
|
|
43514
|
+
// Resolve the target object
|
|
43515
|
+
var object = objectOrId;
|
|
43516
|
+
if (typeof objectOrId === 'string') {
|
|
43517
|
+
object = this.sceneViewer.scene.getObjectByProperty('uuid', objectOrId) || this.sceneViewer.scene.getObjectByProperty('name', objectOrId);
|
|
43518
|
+
if (!object) {
|
|
43519
|
+
// Fall back to a full traverse (matches translate's lookup by originalUuid)
|
|
43520
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
43521
|
+
var _child$userData2;
|
|
43522
|
+
if (!object && ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === objectOrId) {
|
|
43523
|
+
object = child;
|
|
43524
|
+
}
|
|
43525
|
+
});
|
|
43526
|
+
}
|
|
43527
|
+
}
|
|
43528
|
+
if (!object || typeof object.traverse !== 'function') {
|
|
43529
|
+
console.warn("\u26A0\uFE0F getBoundingBox(): Object '".concat(objectOrId, "' not found in scene"));
|
|
43530
|
+
return null;
|
|
43531
|
+
}
|
|
43532
|
+
try {
|
|
43533
|
+
var typesToExclude = filtered ? excludeTypes || ['io-device', 'connector'] : [];
|
|
43534
|
+
var box = computeFilteredBoundingBox(object, typesToExclude);
|
|
43535
|
+
if (box.isEmpty()) {
|
|
43536
|
+
return null;
|
|
43537
|
+
}
|
|
43538
|
+
var size = box.getSize(new THREE__namespace.Vector3());
|
|
43539
|
+
var center = box.getCenter(new THREE__namespace.Vector3());
|
|
43540
|
+
return {
|
|
43541
|
+
min: {
|
|
43542
|
+
x: box.min.x,
|
|
43543
|
+
y: box.min.y,
|
|
43544
|
+
z: box.min.z
|
|
43545
|
+
},
|
|
43546
|
+
max: {
|
|
43547
|
+
x: box.max.x,
|
|
43548
|
+
y: box.max.y,
|
|
43549
|
+
z: box.max.z
|
|
43550
|
+
},
|
|
43551
|
+
size: {
|
|
43552
|
+
x: size.x,
|
|
43553
|
+
y: size.y,
|
|
43554
|
+
z: size.z
|
|
43555
|
+
},
|
|
43556
|
+
center: {
|
|
43557
|
+
x: center.x,
|
|
43558
|
+
y: center.y,
|
|
43559
|
+
z: center.z
|
|
43560
|
+
}
|
|
43561
|
+
};
|
|
43562
|
+
} catch (error) {
|
|
43563
|
+
console.error('❌ getBoundingBox(): Error computing bounding box:', error);
|
|
43564
|
+
return null;
|
|
43565
|
+
}
|
|
43566
|
+
}
|
|
43567
|
+
|
|
42998
43568
|
/**
|
|
42999
43569
|
* Get available component categories
|
|
43000
43570
|
* @returns {Array<Object>} Array of category objects with id, label, icon, and description
|
|
@@ -43229,8 +43799,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
43229
43799
|
var componentDictionary = ((_this$managers$compon = this.managers.componentDataManager) === null || _this$managers$compon === void 0 ? void 0 : _this$managers$compon.componentDictionary) || {};
|
|
43230
43800
|
var missingIds = [];
|
|
43231
43801
|
sceneData.scene.children.forEach(function (child) {
|
|
43232
|
-
var _child$
|
|
43233
|
-
var libraryId = (_child$
|
|
43802
|
+
var _child$userData3;
|
|
43803
|
+
var libraryId = (_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.libraryId;
|
|
43234
43804
|
if (libraryId && !componentDictionary[libraryId]) {
|
|
43235
43805
|
// Only add unique IDs
|
|
43236
43806
|
if (!missingIds.includes(libraryId)) {
|
|
@@ -43308,8 +43878,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
43308
43878
|
// If still not found, try finding by originalUuid in userData
|
|
43309
43879
|
if (!targetObject) {
|
|
43310
43880
|
this.sceneViewer.scene.traverse(function (child) {
|
|
43311
|
-
var _child$
|
|
43312
|
-
if (((_child$
|
|
43881
|
+
var _child$userData4;
|
|
43882
|
+
if (((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === objectId) {
|
|
43313
43883
|
targetObject = child;
|
|
43314
43884
|
return;
|
|
43315
43885
|
}
|
|
@@ -49934,9 +50504,11 @@ exports.ComponentDataManager = ComponentDataManager;
|
|
|
49934
50504
|
exports.ComponentDragManager = ComponentDragManager;
|
|
49935
50505
|
exports.ComponentManager = ComponentManager;
|
|
49936
50506
|
exports.ComponentTooltipManager = ComponentTooltipManager;
|
|
50507
|
+
exports.DEFAULT_HOME_VIEW_DIRECTION = DEFAULT_HOME_VIEW_DIRECTION;
|
|
49937
50508
|
exports.EnvironmentManager = EnvironmentManager;
|
|
49938
50509
|
exports.FLOW_ATTRIBUTE_KEYS = FLOW_ATTRIBUTE_KEYS;
|
|
49939
50510
|
exports.GLOBAL_CACHE_NAME = GLOBAL_CACHE_NAME;
|
|
50511
|
+
exports.HOME_EMPTY_CAMERA_HEIGHT_ABOVE_GROUND = HOME_EMPTY_CAMERA_HEIGHT_ABOVE_GROUND;
|
|
49940
50512
|
exports.IoBehaviorManager = IoBehaviorManager;
|
|
49941
50513
|
exports.KeyboardControlsManager = KeyboardControlsManager;
|
|
49942
50514
|
exports.ModelManager = ModelManager;
|