@2112-lab/central-plant 0.1.60 → 0.1.62
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 +468 -19
- package/dist/cjs/src/core/centralPlant.js +284 -1
- package/dist/cjs/src/core/centralPlantInternals.js +103 -6
- package/dist/cjs/src/managers/components/transformOperationsManager.js +30 -4
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +29 -8
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +22 -0
- package/dist/esm/src/core/centralPlant.js +284 -1
- package/dist/esm/src/core/centralPlantInternals.js +104 -7
- package/dist/esm/src/managers/components/transformOperationsManager.js +30 -4
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +30 -9
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +22 -0
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -20136,7 +20136,24 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20136
20136
|
// Check if this is a valid T-junction (moving segment endpoint touching manual segment)
|
|
20137
20137
|
var isTJunction = _this2.isTJunction(segmentEndpoints.start, segmentEndpoints.end, otherEndpoints.start, otherEndpoints.end, endpointTolerance);
|
|
20138
20138
|
if (isTJunction) {
|
|
20139
|
-
|
|
20139
|
+
// T-junction detected, but we need to verify segments are NOT parallel
|
|
20140
|
+
// Parallel segments with touching endpoints indicate overlapping along the same line
|
|
20141
|
+
var _dir = new THREE__namespace.Vector3().subVectors(segmentEndpoints.end, segmentEndpoints.start).normalize();
|
|
20142
|
+
var _dir2 = new THREE__namespace.Vector3().subVectors(otherEndpoints.end, otherEndpoints.start).normalize();
|
|
20143
|
+
var _dotProduct = Math.abs(_dir.dot(_dir2));
|
|
20144
|
+
var parallelThreshold = 0.9999; // Same threshold as collinear check above
|
|
20145
|
+
|
|
20146
|
+
if (_dotProduct > parallelThreshold) {
|
|
20147
|
+
// Segments are parallel - this is NOT a valid T-junction, it's an overlap
|
|
20148
|
+
console.log("\uD83D\uDD34 T-junction rejected - segments are parallel (dot product: ".concat(_dotProduct.toFixed(6), ")"));
|
|
20149
|
+
console.log(" Moving segment: [".concat(segmentEndpoints.start.x.toFixed(2), ", ").concat(segmentEndpoints.start.y.toFixed(2), ", ").concat(segmentEndpoints.start.z.toFixed(2), "] to [").concat(segmentEndpoints.end.x.toFixed(2), ", ").concat(segmentEndpoints.end.y.toFixed(2), ", ").concat(segmentEndpoints.end.z.toFixed(2), "]"));
|
|
20150
|
+
console.log(" Manual segment: [".concat(otherEndpoints.start.x.toFixed(2), ", ").concat(otherEndpoints.start.y.toFixed(2), ", ").concat(otherEndpoints.start.z.toFixed(2), "] to [").concat(otherEndpoints.end.x.toFixed(2), ", ").concat(otherEndpoints.end.y.toFixed(2), ", ").concat(otherEndpoints.end.z.toFixed(2), "]"));
|
|
20151
|
+
hasIntersection = true;
|
|
20152
|
+
return;
|
|
20153
|
+
}
|
|
20154
|
+
|
|
20155
|
+
// Valid non-parallel T-junction - allowed
|
|
20156
|
+
console.log("\u2705 T-junction detected and allowed - moving segment endpoint touches manual segment at different angle (dot product: ".concat(_dotProduct.toFixed(6), ")"));
|
|
20140
20157
|
console.log(" Moving segment: [".concat(segmentEndpoints.start.x.toFixed(2), ", ").concat(segmentEndpoints.start.y.toFixed(2), ", ").concat(segmentEndpoints.start.z.toFixed(2), "] to [").concat(segmentEndpoints.end.x.toFixed(2), ", ").concat(segmentEndpoints.end.y.toFixed(2), ", ").concat(segmentEndpoints.end.z.toFixed(2), "]"));
|
|
20141
20158
|
console.log(" Manual segment: [".concat(otherEndpoints.start.x.toFixed(2), ", ").concat(otherEndpoints.start.y.toFixed(2), ", ").concat(otherEndpoints.start.z.toFixed(2), "] to [").concat(otherEndpoints.end.x.toFixed(2), ", ").concat(otherEndpoints.end.y.toFixed(2), ", ").concat(otherEndpoints.end.z.toFixed(2), "]"));
|
|
20142
20159
|
return;
|
|
@@ -20257,7 +20274,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20257
20274
|
return null;
|
|
20258
20275
|
}
|
|
20259
20276
|
var collisionRadius = 0.5; // Radius around connector that triggers collision
|
|
20260
|
-
var endpointTolerance = 0.
|
|
20277
|
+
var endpointTolerance = 0.1; // Tolerance for determining if connector is at segment endpoint
|
|
20261
20278
|
|
|
20262
20279
|
// Get segment endpoints in world coordinates
|
|
20263
20280
|
var endpoints = this.calculateSegmentEndpoints(segment);
|
|
@@ -20272,6 +20289,15 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20272
20289
|
|
|
20273
20290
|
// Check if this is a component connector (not a segment-connector)
|
|
20274
20291
|
if (((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType) === 'connector') {
|
|
20292
|
+
var _segment$userData10, _segment$userData11;
|
|
20293
|
+
// Skip connectors that are connected to this segment (pathFrom or pathTo)
|
|
20294
|
+
var segmentPathFrom = (_segment$userData10 = segment.userData) === null || _segment$userData10 === void 0 ? void 0 : _segment$userData10.pathFrom;
|
|
20295
|
+
var segmentPathTo = (_segment$userData11 = segment.userData) === null || _segment$userData11 === void 0 ? void 0 : _segment$userData11.pathTo;
|
|
20296
|
+
var connectorId = child.uuid;
|
|
20297
|
+
if (connectorId === segmentPathFrom || connectorId === segmentPathTo) {
|
|
20298
|
+
return; // Skip this connector - it's connected to this segment
|
|
20299
|
+
}
|
|
20300
|
+
|
|
20275
20301
|
// Get world position of connector
|
|
20276
20302
|
var connectorWorldPos = new THREE__namespace.Vector3();
|
|
20277
20303
|
child.getWorldPosition(connectorWorldPos);
|
|
@@ -21285,8 +21311,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
21285
21311
|
// Remove segment from scene data
|
|
21286
21312
|
if (currentSceneData.scene && currentSceneData.scene.children) {
|
|
21287
21313
|
var segmentIndex = currentSceneData.scene.children.findIndex(function (child) {
|
|
21288
|
-
var _segment$
|
|
21289
|
-
return child.uuid === segment.uuid || child.uuid === ((_segment$
|
|
21314
|
+
var _segment$userData12;
|
|
21315
|
+
return child.uuid === segment.uuid || child.uuid === ((_segment$userData12 = segment.userData) === null || _segment$userData12 === void 0 ? void 0 : _segment$userData12.originalUuid);
|
|
21290
21316
|
});
|
|
21291
21317
|
if (segmentIndex !== -1) {
|
|
21292
21318
|
currentSceneData.scene.children.splice(segmentIndex, 1);
|
|
@@ -27027,15 +27053,12 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
27027
27053
|
var objectsToRemove = [];
|
|
27028
27054
|
sceneViewer.scene.traverse(function (obj) {
|
|
27029
27055
|
// Remove computed Segments (uppercase SEGMENT-)
|
|
27056
|
+
// Note: Elbows are children of segments, so they'll be removed automatically
|
|
27030
27057
|
if (obj.uuid && obj.uuid.startsWith("SEGMENT-") && obj.userData.isDeclared !== true) {
|
|
27031
27058
|
console.log("[removeComputedObjects] to be removed: ".concat(obj.uuid, ")"));
|
|
27032
27059
|
objectsToRemove.push(obj);
|
|
27033
27060
|
}
|
|
27034
|
-
//
|
|
27035
|
-
if (obj.userData && obj.userData.isPipeElbow && obj.userData.isDeclared !== true) {
|
|
27036
|
-
console.log("[removeComputedObjects] to be removed: ".concat(obj.uuid, ")"));
|
|
27037
|
-
objectsToRemove.push(obj);
|
|
27038
|
-
}
|
|
27061
|
+
// Don't separately collect elbows - they're children of segments and will be handled below
|
|
27039
27062
|
// Also remove computed Gateways
|
|
27040
27063
|
if (obj.uuid && obj.uuid.includes("Gateway") && obj.userData && obj.userData.isDeclared !== true) {
|
|
27041
27064
|
console.log("[removeComputedObjects] to be removed: ".concat(obj.uuid));
|
|
@@ -27044,9 +27067,30 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
27044
27067
|
});
|
|
27045
27068
|
|
|
27046
27069
|
// console.log(`[removeComputedObjects] objectsToRemove:`, objectsToRemove);
|
|
27047
|
-
|
|
27048
|
-
for (var _i = 0, _objectsToRemove = objectsToRemove; _i < _objectsToRemove.length; _i++) {
|
|
27070
|
+
var _loop = function _loop() {
|
|
27049
27071
|
var obj = _objectsToRemove[_i];
|
|
27072
|
+
// Dispose of children (elbows) before removing parent segment
|
|
27073
|
+
// Clone children array since we'll be modifying it during removal
|
|
27074
|
+
if (obj.children && obj.children.length > 0) {
|
|
27075
|
+
var childrenToRemove = _toConsumableArray(obj.children);
|
|
27076
|
+
childrenToRemove.forEach(function (child) {
|
|
27077
|
+
// Remove child from parent first
|
|
27078
|
+
obj.remove(child);
|
|
27079
|
+
// Then dispose of its resources
|
|
27080
|
+
if (child.geometry) child.geometry.dispose();
|
|
27081
|
+
if (child.material) {
|
|
27082
|
+
if (Array.isArray(child.material)) {
|
|
27083
|
+
child.material.forEach(function (mat) {
|
|
27084
|
+
return mat.dispose();
|
|
27085
|
+
});
|
|
27086
|
+
} else {
|
|
27087
|
+
child.material.dispose();
|
|
27088
|
+
}
|
|
27089
|
+
}
|
|
27090
|
+
});
|
|
27091
|
+
}
|
|
27092
|
+
|
|
27093
|
+
// Now remove the parent object from scene
|
|
27050
27094
|
sceneViewer.scene.remove(obj);
|
|
27051
27095
|
if (obj.geometry) obj.geometry.dispose();
|
|
27052
27096
|
if (obj.material) {
|
|
@@ -27058,8 +27102,11 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
27058
27102
|
obj.material.dispose();
|
|
27059
27103
|
}
|
|
27060
27104
|
}
|
|
27105
|
+
};
|
|
27106
|
+
for (var _i = 0, _objectsToRemove = objectsToRemove; _i < _objectsToRemove.length; _i++) {
|
|
27107
|
+
_loop();
|
|
27061
27108
|
}
|
|
27062
|
-
console.log("\u2705 Removed ".concat(objectsToRemove.length, " computed objects from scene (segments
|
|
27109
|
+
console.log("\u2705 Removed ".concat(objectsToRemove.length, " computed objects from scene (segments with elbows, and gateways)"));
|
|
27063
27110
|
}
|
|
27064
27111
|
|
|
27065
27112
|
/**
|
|
@@ -29645,6 +29692,28 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
29645
29692
|
return;
|
|
29646
29693
|
}
|
|
29647
29694
|
|
|
29695
|
+
// Remove any child elbows from computed segment before manualizing
|
|
29696
|
+
if (segment.children && segment.children.length > 0) {
|
|
29697
|
+
var childrenToRemove = _toConsumableArray(segment.children);
|
|
29698
|
+
childrenToRemove.forEach(function (child) {
|
|
29699
|
+
var _child$userData10;
|
|
29700
|
+
if ((_child$userData10 = child.userData) !== null && _child$userData10 !== void 0 && _child$userData10.isPipeElbow) {
|
|
29701
|
+
console.log("\uD83D\uDDD1\uFE0F Removing elbow child from segment before manualization: ".concat(child.uuid));
|
|
29702
|
+
segment.remove(child);
|
|
29703
|
+
if (child.geometry) child.geometry.dispose();
|
|
29704
|
+
if (child.material) {
|
|
29705
|
+
if (Array.isArray(child.material)) {
|
|
29706
|
+
child.material.forEach(function (mat) {
|
|
29707
|
+
return mat.dispose();
|
|
29708
|
+
});
|
|
29709
|
+
} else {
|
|
29710
|
+
child.material.dispose();
|
|
29711
|
+
}
|
|
29712
|
+
}
|
|
29713
|
+
}
|
|
29714
|
+
});
|
|
29715
|
+
}
|
|
29716
|
+
|
|
29648
29717
|
// CRITICAL: Clone the material BEFORE changing its color
|
|
29649
29718
|
// This prevents the color change from affecting other segments that share the same material instance
|
|
29650
29719
|
if (segment.material && !((_segment$material$use = segment.material.userData) !== null && _segment$material$use !== void 0 && _segment$material$use.isCloned)) {
|
|
@@ -33360,6 +33429,103 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
33360
33429
|
return this.centralPlant.managers.transformOperationsManager.translateGateway(gatewayId, axis, value);
|
|
33361
33430
|
}
|
|
33362
33431
|
|
|
33432
|
+
/**
|
|
33433
|
+
* Translate currently selected objects
|
|
33434
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
33435
|
+
* @param {number} value - The value to translate by
|
|
33436
|
+
* @param {boolean} [skipPathUpdate=false] - If true, skip automatic path regeneration
|
|
33437
|
+
* @returns {Object} Result object with success status and details
|
|
33438
|
+
*/
|
|
33439
|
+
}, {
|
|
33440
|
+
key: "translateSelectedObjects",
|
|
33441
|
+
value: function translateSelectedObjects(axis, value) {
|
|
33442
|
+
var _this$centralPlant$sc2;
|
|
33443
|
+
var skipPathUpdate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
33444
|
+
var result = {
|
|
33445
|
+
success: false,
|
|
33446
|
+
translatedCount: 0,
|
|
33447
|
+
totalCount: 0,
|
|
33448
|
+
errors: []
|
|
33449
|
+
};
|
|
33450
|
+
|
|
33451
|
+
// Get selected objects from transform manager
|
|
33452
|
+
var transformManager = (_this$centralPlant$sc2 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc2 === void 0 ? void 0 : _this$centralPlant$sc2.transformManager;
|
|
33453
|
+
if (!transformManager) {
|
|
33454
|
+
result.errors.push('Transform manager not available');
|
|
33455
|
+
console.error('❌ translateSelectedObjects(): Transform manager not available');
|
|
33456
|
+
return result;
|
|
33457
|
+
}
|
|
33458
|
+
var selectedObjects = transformManager.selectedObjects || [];
|
|
33459
|
+
result.totalCount = selectedObjects.length;
|
|
33460
|
+
if (selectedObjects.length === 0) {
|
|
33461
|
+
result.errors.push('No objects selected');
|
|
33462
|
+
console.warn('⚠️ translateSelectedObjects(): No objects selected');
|
|
33463
|
+
return result;
|
|
33464
|
+
}
|
|
33465
|
+
console.log("\uD83D\uDD27 Translating ".concat(selectedObjects.length, " selected object(s) on ").concat(axis, " axis by ").concat(value));
|
|
33466
|
+
|
|
33467
|
+
// Translate each selected object using the appropriate method
|
|
33468
|
+
var _iterator = _createForOfIteratorHelper(selectedObjects),
|
|
33469
|
+
_step;
|
|
33470
|
+
try {
|
|
33471
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
33472
|
+
var _obj$userData;
|
|
33473
|
+
var obj = _step.value;
|
|
33474
|
+
var objectType = (_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType;
|
|
33475
|
+
var objectId = obj.uuid;
|
|
33476
|
+
var success = false;
|
|
33477
|
+
try {
|
|
33478
|
+
if (objectType === 'segment') {
|
|
33479
|
+
success = this.translateSegment(objectId, axis, value, skipPathUpdate);
|
|
33480
|
+
} else if (objectType === 'gateway') {
|
|
33481
|
+
success = this.translateGateway(objectId, axis, value);
|
|
33482
|
+
} else if (objectType === 'component') {
|
|
33483
|
+
success = this.translateComponent(objectId, axis, value);
|
|
33484
|
+
} else {
|
|
33485
|
+
result.errors.push("Unknown object type: ".concat(objectType, " (").concat(objectId, ")"));
|
|
33486
|
+
console.warn("\u26A0\uFE0F Unknown object type: ".concat(objectType, " for ").concat(objectId));
|
|
33487
|
+
continue;
|
|
33488
|
+
}
|
|
33489
|
+
if (success) {
|
|
33490
|
+
result.translatedCount++;
|
|
33491
|
+
} else {
|
|
33492
|
+
result.errors.push("Failed to translate ".concat(objectType, ": ").concat(objectId));
|
|
33493
|
+
}
|
|
33494
|
+
} catch (error) {
|
|
33495
|
+
result.errors.push("Error translating ".concat(objectId, ": ").concat(error.message));
|
|
33496
|
+
console.error("\u274C Error translating ".concat(objectId, ":"), error);
|
|
33497
|
+
}
|
|
33498
|
+
}
|
|
33499
|
+
} catch (err) {
|
|
33500
|
+
_iterator.e(err);
|
|
33501
|
+
} finally {
|
|
33502
|
+
_iterator.f();
|
|
33503
|
+
}
|
|
33504
|
+
result.success = result.translatedCount === result.totalCount;
|
|
33505
|
+
if (result.success) {
|
|
33506
|
+
console.log("\u2705 Successfully translated all ".concat(result.translatedCount, " object(s)"));
|
|
33507
|
+
} else {
|
|
33508
|
+
console.warn("\u26A0\uFE0F Translated ".concat(result.translatedCount, "/").concat(result.totalCount, " objects. ").concat(result.errors.length, " error(s) occurred."));
|
|
33509
|
+
}
|
|
33510
|
+
return result;
|
|
33511
|
+
}
|
|
33512
|
+
|
|
33513
|
+
/**
|
|
33514
|
+
* Get currently selected objects
|
|
33515
|
+
* @returns {Array<THREE.Object3D>} Array of currently selected objects
|
|
33516
|
+
*/
|
|
33517
|
+
}, {
|
|
33518
|
+
key: "getSelectedObjects",
|
|
33519
|
+
value: function getSelectedObjects() {
|
|
33520
|
+
var _this$centralPlant$sc3;
|
|
33521
|
+
var transformManager = (_this$centralPlant$sc3 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc3 === void 0 ? void 0 : _this$centralPlant$sc3.transformManager;
|
|
33522
|
+
if (!transformManager) {
|
|
33523
|
+
console.warn('⚠️ getSelectedObjects(): Transform manager not available');
|
|
33524
|
+
return [];
|
|
33525
|
+
}
|
|
33526
|
+
return transformManager.selectedObjects || [];
|
|
33527
|
+
}
|
|
33528
|
+
|
|
33363
33529
|
/**
|
|
33364
33530
|
* Rotate a component by componentId (delegates to TransformOperationsManager)
|
|
33365
33531
|
* @param {string} componentId - The UUID of the component to rotate
|
|
@@ -33517,9 +33683,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
33517
33683
|
}, {
|
|
33518
33684
|
key: "addConnection",
|
|
33519
33685
|
value: function addConnection(fromConnectorId, toConnectorId) {
|
|
33520
|
-
var _this$centralPlant$
|
|
33686
|
+
var _this$centralPlant$sc4;
|
|
33521
33687
|
// Use centralized validation for connection parameters
|
|
33522
|
-
var existingConnections = ((_this$centralPlant$
|
|
33688
|
+
var existingConnections = ((_this$centralPlant$sc4 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc4 === void 0 || (_this$centralPlant$sc4 = _this$centralPlant$sc4.currentSceneData) === null || _this$centralPlant$sc4 === void 0 ? void 0 : _this$centralPlant$sc4.connections) || [];
|
|
33523
33689
|
var validation = this.validator.validateConnectionParams(fromConnectorId, toConnectorId, existingConnections);
|
|
33524
33690
|
if (!validation.isValid) {
|
|
33525
33691
|
return false; // Validator already logged the error
|
|
@@ -33645,7 +33811,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
33645
33811
|
}, {
|
|
33646
33812
|
key: "addComponent",
|
|
33647
33813
|
value: function addComponent(libraryId) {
|
|
33648
|
-
var _this$centralPlant$
|
|
33814
|
+
var _this$centralPlant$sc5;
|
|
33649
33815
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
33650
33816
|
// Use centralized validation for component addition parameters
|
|
33651
33817
|
var existingIds = this.getComponentIds();
|
|
@@ -33655,7 +33821,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
33655
33821
|
}
|
|
33656
33822
|
|
|
33657
33823
|
// Validate scene availability
|
|
33658
|
-
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$
|
|
33824
|
+
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$sc5 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc5 === void 0 ? void 0 : _this$centralPlant$sc5.scene);
|
|
33659
33825
|
if (!sceneValidation.isValid) {
|
|
33660
33826
|
return false;
|
|
33661
33827
|
}
|
|
@@ -33674,7 +33840,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
33674
33840
|
return false;
|
|
33675
33841
|
}
|
|
33676
33842
|
try {
|
|
33677
|
-
var _this$centralPlant$
|
|
33843
|
+
var _this$centralPlant$sc6;
|
|
33678
33844
|
// Generate a unique component ID if not provided
|
|
33679
33845
|
var componentId = options.customId || this.generateUniqueComponentId(libraryId);
|
|
33680
33846
|
|
|
@@ -33748,7 +33914,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
33748
33914
|
componentModel.updateMatrixWorld(true);
|
|
33749
33915
|
|
|
33750
33916
|
// Check if component is underground and fix if needed (based on settings)
|
|
33751
|
-
var checkUnderground = (_this$centralPlant$
|
|
33917
|
+
var checkUnderground = (_this$centralPlant$sc6 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc6 === void 0 || (_this$centralPlant$sc6 = _this$centralPlant$sc6.managers) === null || _this$centralPlant$sc6 === void 0 || (_this$centralPlant$sc6 = _this$centralPlant$sc6.settingsManager) === null || _this$centralPlant$sc6 === void 0 ? void 0 : _this$centralPlant$sc6.getSetting('scene', 'checkUnderground');
|
|
33752
33918
|
if (checkUnderground) {
|
|
33753
33919
|
var wasFixed = this.fixUndergroundComponent(componentModel);
|
|
33754
33920
|
if (wasFixed) {
|
|
@@ -33888,7 +34054,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
33888
34054
|
* Initialize the CentralPlant manager
|
|
33889
34055
|
*
|
|
33890
34056
|
* @constructor
|
|
33891
|
-
* @version 0.1.
|
|
34057
|
+
* @version 0.1.62
|
|
33892
34058
|
* @updated 2025-10-22
|
|
33893
34059
|
*
|
|
33894
34060
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -34160,6 +34326,179 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
34160
34326
|
return this.internals.translateSegment(segmentId, axis, value, skipPathUpdate);
|
|
34161
34327
|
}
|
|
34162
34328
|
|
|
34329
|
+
/**
|
|
34330
|
+
* Select an object in the scene
|
|
34331
|
+
* @param {THREE.Object3D|string} objectOrId - The Three.js object to select, or its UUID
|
|
34332
|
+
* @returns {boolean} True if selection was successful, false otherwise
|
|
34333
|
+
* @description Selects an object in the scene, showing the transform controls and bounding box.
|
|
34334
|
+
* This is useful for programmatically selecting objects before performing operations like translation.
|
|
34335
|
+
* Objects marked as immutable (userData.immutable = true) cannot be selected.
|
|
34336
|
+
* @example
|
|
34337
|
+
* // Select by object reference
|
|
34338
|
+
* const segment = scene.getObjectByProperty('uuid', 'segment-uuid-123');
|
|
34339
|
+
* centralPlant.selectObject(segment);
|
|
34340
|
+
*
|
|
34341
|
+
* // Select by UUID
|
|
34342
|
+
* centralPlant.selectObject('segment-uuid-123');
|
|
34343
|
+
*
|
|
34344
|
+
* // Then translate the selected object
|
|
34345
|
+
* centralPlant.translateSegment('segment-uuid-123', 'x', 1.0);
|
|
34346
|
+
*
|
|
34347
|
+
* @since 0.1.37
|
|
34348
|
+
*/
|
|
34349
|
+
}, {
|
|
34350
|
+
key: "selectObject",
|
|
34351
|
+
value: function selectObject(objectOrId) {
|
|
34352
|
+
var _this$sceneViewer, _object;
|
|
34353
|
+
if (!((_this$sceneViewer = this.sceneViewer) !== null && _this$sceneViewer !== void 0 && _this$sceneViewer.transformManager)) {
|
|
34354
|
+
console.warn('⚠️ Transform manager not initialized');
|
|
34355
|
+
return false;
|
|
34356
|
+
}
|
|
34357
|
+
var object = objectOrId;
|
|
34358
|
+
|
|
34359
|
+
// If a string UUID was provided, find the object in the scene
|
|
34360
|
+
if (typeof objectOrId === 'string') {
|
|
34361
|
+
object = this.sceneViewer.scene.getObjectByProperty('uuid', objectOrId);
|
|
34362
|
+
if (!object) {
|
|
34363
|
+
console.warn("\u26A0\uFE0F Object with UUID ".concat(objectOrId, " not found in scene"));
|
|
34364
|
+
return false;
|
|
34365
|
+
}
|
|
34366
|
+
}
|
|
34367
|
+
|
|
34368
|
+
// Check if object is immutable
|
|
34369
|
+
if (((_object = object) === null || _object === void 0 || (_object = _object.userData) === null || _object === void 0 ? void 0 : _object.immutable) === true) {
|
|
34370
|
+
console.warn("\u26A0\uFE0F Cannot select immutable object: ".concat(object.name || object.uuid));
|
|
34371
|
+
return false;
|
|
34372
|
+
}
|
|
34373
|
+
return this.sceneViewer.transformManager.selectObject(object);
|
|
34374
|
+
}
|
|
34375
|
+
|
|
34376
|
+
/**
|
|
34377
|
+
* Toggle object selection (add/remove from multi-selection)
|
|
34378
|
+
* @param {THREE.Object3D|string} objectOrId - The Three.js object to toggle, or its UUID
|
|
34379
|
+
* @returns {boolean} True if toggle was successful, false otherwise
|
|
34380
|
+
* @description Toggles an object in the multi-selection. If the object is already selected,
|
|
34381
|
+
* it will be removed from the selection. If not selected, it will be added to the selection.
|
|
34382
|
+
* This is useful for programmatic multi-selection (similar to shift+click behavior).
|
|
34383
|
+
* Objects marked as immutable (userData.immutable = true) cannot be toggled.
|
|
34384
|
+
* @example
|
|
34385
|
+
* // Toggle selection by UUID
|
|
34386
|
+
* centralPlant.toggleObject('segment-uuid-123');
|
|
34387
|
+
* centralPlant.toggleObject('segment-uuid-456'); // Now both selected
|
|
34388
|
+
* centralPlant.toggleObject('segment-uuid-123'); // Removes first, keeps second
|
|
34389
|
+
*
|
|
34390
|
+
* // Toggle by object reference
|
|
34391
|
+
* const segment = scene.getObjectByProperty('uuid', 'segment-uuid-789');
|
|
34392
|
+
* centralPlant.toggleObject(segment);
|
|
34393
|
+
*
|
|
34394
|
+
* @since 0.1.37
|
|
34395
|
+
*/
|
|
34396
|
+
}, {
|
|
34397
|
+
key: "toggleObject",
|
|
34398
|
+
value: function toggleObject(objectOrId) {
|
|
34399
|
+
var _this$sceneViewer2, _object2;
|
|
34400
|
+
if (!((_this$sceneViewer2 = this.sceneViewer) !== null && _this$sceneViewer2 !== void 0 && _this$sceneViewer2.transformManager)) {
|
|
34401
|
+
console.warn('⚠️ Transform manager not initialized');
|
|
34402
|
+
return false;
|
|
34403
|
+
}
|
|
34404
|
+
var object = objectOrId;
|
|
34405
|
+
|
|
34406
|
+
// If a string UUID was provided, find the object in the scene
|
|
34407
|
+
if (typeof objectOrId === 'string') {
|
|
34408
|
+
object = this.sceneViewer.scene.getObjectByProperty('uuid', objectOrId);
|
|
34409
|
+
if (!object) {
|
|
34410
|
+
console.warn("\u26A0\uFE0F Object with UUID ".concat(objectOrId, " not found in scene"));
|
|
34411
|
+
return false;
|
|
34412
|
+
}
|
|
34413
|
+
}
|
|
34414
|
+
|
|
34415
|
+
// Check if object is immutable
|
|
34416
|
+
if (((_object2 = object) === null || _object2 === void 0 || (_object2 = _object2.userData) === null || _object2 === void 0 ? void 0 : _object2.immutable) === true) {
|
|
34417
|
+
console.warn("\u26A0\uFE0F Cannot toggle immutable object: ".concat(object.name || object.uuid));
|
|
34418
|
+
return false;
|
|
34419
|
+
}
|
|
34420
|
+
this.sceneViewer.transformManager.toggleObjectSelection(object);
|
|
34421
|
+
return true;
|
|
34422
|
+
}
|
|
34423
|
+
|
|
34424
|
+
/**
|
|
34425
|
+
* Deselect the currently selected object(s)
|
|
34426
|
+
* @returns {boolean} True if deselection was successful
|
|
34427
|
+
* @description Clears the current selection, hiding transform controls and bounding boxes.
|
|
34428
|
+
* @example
|
|
34429
|
+
* centralPlant.deselectObject();
|
|
34430
|
+
*
|
|
34431
|
+
* @since 0.1.37
|
|
34432
|
+
*/
|
|
34433
|
+
}, {
|
|
34434
|
+
key: "deselectObject",
|
|
34435
|
+
value: function deselectObject() {
|
|
34436
|
+
var _this$sceneViewer3;
|
|
34437
|
+
if (!((_this$sceneViewer3 = this.sceneViewer) !== null && _this$sceneViewer3 !== void 0 && _this$sceneViewer3.transformManager)) {
|
|
34438
|
+
console.warn('⚠️ Transform manager not initialized');
|
|
34439
|
+
return false;
|
|
34440
|
+
}
|
|
34441
|
+
this.sceneViewer.transformManager.deselectObject();
|
|
34442
|
+
return true;
|
|
34443
|
+
}
|
|
34444
|
+
|
|
34445
|
+
/**
|
|
34446
|
+
* Translate currently selected object(s)
|
|
34447
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
34448
|
+
* @param {number} value - The value to translate by (must be a multiple of 0.5)
|
|
34449
|
+
* @param {boolean} [skipPathUpdate=false] - If true, skip automatic path regeneration (for batch operations)
|
|
34450
|
+
* @returns {Object} Result object with success status and details
|
|
34451
|
+
* @returns {boolean} returns.success - True if all translations were successful
|
|
34452
|
+
* @returns {number} returns.translatedCount - Number of objects successfully translated
|
|
34453
|
+
* @returns {number} returns.totalCount - Total number of selected objects
|
|
34454
|
+
* @returns {Array} returns.errors - Array of error messages if any failures occurred
|
|
34455
|
+
* @description Translates all currently selected objects along the specified axis.
|
|
34456
|
+
* Automatically determines the object type (component/segment/gateway) and calls the
|
|
34457
|
+
* appropriate translation method for each. Useful for batch operations on selections.
|
|
34458
|
+
* @example
|
|
34459
|
+
* // Select objects first
|
|
34460
|
+
* centralPlant.selectObject('segment-1')
|
|
34461
|
+
* centralPlant.toggleObjectSelection('segment-2')
|
|
34462
|
+
* centralPlant.toggleObjectSelection('component-1')
|
|
34463
|
+
*
|
|
34464
|
+
* // Translate all selected objects 2 units along X axis
|
|
34465
|
+
* const result = centralPlant.translateSelectedObjects('x', 2.0)
|
|
34466
|
+
* console.log(`Translated ${result.translatedCount}/${result.totalCount} objects`)
|
|
34467
|
+
*
|
|
34468
|
+
* // Batch operation with path update disabled
|
|
34469
|
+
* centralPlant.translateSelectedObjects('x', 1.0, true)
|
|
34470
|
+
* centralPlant.translateSelectedObjects('y', 0.5, true)
|
|
34471
|
+
* centralPlant.updatePaths() // Update once at the end
|
|
34472
|
+
*
|
|
34473
|
+
* @since 0.1.37
|
|
34474
|
+
*/
|
|
34475
|
+
}, {
|
|
34476
|
+
key: "translateSelectedObjects",
|
|
34477
|
+
value: function translateSelectedObjects(axis, value) {
|
|
34478
|
+
var skipPathUpdate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
34479
|
+
return this.internals.translateSelectedObjects(axis, value, skipPathUpdate);
|
|
34480
|
+
}
|
|
34481
|
+
|
|
34482
|
+
/**
|
|
34483
|
+
* Get currently selected objects
|
|
34484
|
+
* @returns {Array<THREE.Object3D>} Array of currently selected Three.js objects
|
|
34485
|
+
* @description Returns the array of objects currently selected in the scene.
|
|
34486
|
+
* Useful for inspecting selection state or performing custom operations.
|
|
34487
|
+
* @example
|
|
34488
|
+
* const selected = centralPlant.getSelectedObjects()
|
|
34489
|
+
* console.log(`${selected.length} objects selected`)
|
|
34490
|
+
* selected.forEach(obj => {
|
|
34491
|
+
* console.log(`- ${obj.name} (${obj.userData.objectType}): ${obj.uuid}`)
|
|
34492
|
+
* })
|
|
34493
|
+
*
|
|
34494
|
+
* @since 0.1.37
|
|
34495
|
+
*/
|
|
34496
|
+
}, {
|
|
34497
|
+
key: "getSelectedObjects",
|
|
34498
|
+
value: function getSelectedObjects() {
|
|
34499
|
+
return this.internals.getSelectedObjects();
|
|
34500
|
+
}
|
|
34501
|
+
|
|
34163
34502
|
/**
|
|
34164
34503
|
* Translate a gateway by gatewayId
|
|
34165
34504
|
* @param {string} gatewayId - The UUID of the gateway to translate
|
|
@@ -34623,6 +34962,116 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
34623
34962
|
return componentIds;
|
|
34624
34963
|
}
|
|
34625
34964
|
|
|
34965
|
+
/**
|
|
34966
|
+
* Get object IDs from the scene by type
|
|
34967
|
+
* @param {string|Array<string>} objectTypes - Object type(s) to retrieve: 'components', 'segments', 'gateways', or array of types
|
|
34968
|
+
* @param {Object} [options={}] - Optional filtering options
|
|
34969
|
+
* @param {boolean} [options.isDeclared] - Filter by declared status (true for declared only, false for computed only, undefined for all)
|
|
34970
|
+
* @returns {Array<string>} Array of object UUID strings matching the specified type(s), or empty array if none exist
|
|
34971
|
+
* @description Retrieves UUIDs of objects currently in the 3D scene filtered by object type.
|
|
34972
|
+
* This traverses the Three.js scene graph to find objects with matching objectType in userData.
|
|
34973
|
+
* Supports single type as string or multiple types as array.
|
|
34974
|
+
* @example
|
|
34975
|
+
* // Get all component IDs
|
|
34976
|
+
* const componentIds = centralPlant.getObjectIds('components');
|
|
34977
|
+
* console.log(`Components: ${componentIds.length}`);
|
|
34978
|
+
*
|
|
34979
|
+
* // Get all segment IDs
|
|
34980
|
+
* const segmentIds = centralPlant.getObjectIds('segments');
|
|
34981
|
+
* console.log(`Segments: ${segmentIds.length}`);
|
|
34982
|
+
*
|
|
34983
|
+
* // Get all gateway IDs
|
|
34984
|
+
* const gatewayIds = centralPlant.getObjectIds('gateways');
|
|
34985
|
+
* console.log(`Gateways: ${gatewayIds.length}`);
|
|
34986
|
+
*
|
|
34987
|
+
* // Get multiple object types at once
|
|
34988
|
+
* const allIds = centralPlant.getObjectIds(['components', 'segments', 'gateways']);
|
|
34989
|
+
* console.log(`Total objects: ${allIds.length}`);
|
|
34990
|
+
*
|
|
34991
|
+
* // Get only declared segments
|
|
34992
|
+
* const declaredSegments = centralPlant.getObjectIds('segments', { isDeclared: true });
|
|
34993
|
+
* console.log(`Declared segments: ${declaredSegments.length}`);
|
|
34994
|
+
*
|
|
34995
|
+
* // Get only computed gateways
|
|
34996
|
+
* const computedGateways = centralPlant.getObjectIds('gateways', { isDeclared: false });
|
|
34997
|
+
* console.log(`Computed gateways: ${computedGateways.length}`);
|
|
34998
|
+
*
|
|
34999
|
+
* // Use for selection UI
|
|
35000
|
+
* const segments = centralPlant.getObjectIds('segments');
|
|
35001
|
+
* segments.forEach(id => {
|
|
35002
|
+
* console.log(`Segment: ${id}`);
|
|
35003
|
+
* });
|
|
35004
|
+
*/
|
|
35005
|
+
}, {
|
|
35006
|
+
key: "getObjectIds",
|
|
35007
|
+
value: function getObjectIds() {
|
|
35008
|
+
var objectTypes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['components', 'segments', 'gateways'];
|
|
35009
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
35010
|
+
if (!this.sceneViewer) {
|
|
35011
|
+
console.warn('⚠️ getObjectIds(): Scene viewer not available - centralPlant not fully initialized');
|
|
35012
|
+
return [];
|
|
35013
|
+
}
|
|
35014
|
+
if (!this.sceneViewer.scene) {
|
|
35015
|
+
console.warn('⚠️ getObjectIds(): Scene not available - scene viewer not fully initialized');
|
|
35016
|
+
return [];
|
|
35017
|
+
}
|
|
35018
|
+
if (!this.sceneViewer.isInitialized) {
|
|
35019
|
+
console.warn('⚠️ getObjectIds(): Scene viewer initialization not complete');
|
|
35020
|
+
return [];
|
|
35021
|
+
}
|
|
35022
|
+
|
|
35023
|
+
// Validate objectTypes parameter
|
|
35024
|
+
if (!objectTypes) {
|
|
35025
|
+
console.warn('⚠️ getObjectIds(): objectTypes parameter is required');
|
|
35026
|
+
return [];
|
|
35027
|
+
}
|
|
35028
|
+
|
|
35029
|
+
// Convert to array for consistent handling
|
|
35030
|
+
var typesArray = Array.isArray(objectTypes) ? objectTypes : [objectTypes];
|
|
35031
|
+
|
|
35032
|
+
// Map plural types to singular (internal userData uses singular)
|
|
35033
|
+
var typeMapping = {
|
|
35034
|
+
'components': 'component',
|
|
35035
|
+
'segments': 'segment',
|
|
35036
|
+
'gateways': 'gateway'
|
|
35037
|
+
};
|
|
35038
|
+
|
|
35039
|
+
// Validate each type and convert to internal format
|
|
35040
|
+
var validTypes = ['components', 'segments', 'gateways'];
|
|
35041
|
+
var invalidTypes = typesArray.filter(function (type) {
|
|
35042
|
+
return !validTypes.includes(type);
|
|
35043
|
+
});
|
|
35044
|
+
if (invalidTypes.length > 0) {
|
|
35045
|
+
console.warn("\u26A0\uFE0F getObjectIds(): Invalid object type(s): ".concat(invalidTypes.join(', '), ". Valid types are: ").concat(validTypes.join(', ')));
|
|
35046
|
+
return [];
|
|
35047
|
+
}
|
|
35048
|
+
|
|
35049
|
+
// Convert plural types to singular for internal lookup
|
|
35050
|
+
var internalTypes = typesArray.map(function (type) {
|
|
35051
|
+
return typeMapping[type];
|
|
35052
|
+
});
|
|
35053
|
+
var objectIds = [];
|
|
35054
|
+
|
|
35055
|
+
// Traverse the scene to find all objects matching the specified types
|
|
35056
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
35057
|
+
if (child.userData && child.userData.objectType && internalTypes.includes(child.userData.objectType)) {
|
|
35058
|
+
// Apply isDeclared filter if specified
|
|
35059
|
+
if (options.isDeclared !== undefined) {
|
|
35060
|
+
var childIsDeclared = child.userData.isDeclared === true;
|
|
35061
|
+
if (childIsDeclared !== options.isDeclared) {
|
|
35062
|
+
return; // Skip this object if it doesn't match the isDeclared filter
|
|
35063
|
+
}
|
|
35064
|
+
}
|
|
35065
|
+
var id = child.uuid || child.userData.originalUuid || child.name;
|
|
35066
|
+
if (id) {
|
|
35067
|
+
objectIds.push(id);
|
|
35068
|
+
}
|
|
35069
|
+
}
|
|
35070
|
+
});
|
|
35071
|
+
console.log("\uD83D\uDCCB getObjectIds(): Found ".concat(objectIds.length, " object IDs for type(s) [").concat(typesArray.join(', '), "]").concat(options.isDeclared !== undefined ? " (isDeclared: ".concat(options.isDeclared, ")") : '', ":"), objectIds);
|
|
35072
|
+
return objectIds;
|
|
35073
|
+
}
|
|
35074
|
+
|
|
34626
35075
|
/**
|
|
34627
35076
|
* Get components from the dictionary with detailed information and flexible filtering
|
|
34628
35077
|
* @param {Object} [options={}] - Configuration options for component listing
|