@2112-lab/central-plant 0.1.49 → 0.1.51
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 +417 -609
- package/dist/cjs/src/core/centralPlant.js +3 -48
- package/dist/cjs/src/managers/components/transformOperationsManager.js +86 -123
- package/dist/cjs/src/managers/controls/keyboardControlsManager.js +0 -56
- package/dist/cjs/src/managers/controls/transformControlsManager.js +195 -144
- package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +36 -2
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +72 -93
- package/dist/cjs/src/managers/pathfinding/sceneDataManager.js +13 -0
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +12 -143
- package/dist/esm/src/core/centralPlant.js +3 -48
- package/dist/esm/src/managers/components/transformOperationsManager.js +86 -123
- package/dist/esm/src/managers/controls/keyboardControlsManager.js +0 -56
- package/dist/esm/src/managers/controls/transformControlsManager.js +196 -145
- package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +36 -2
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +73 -94
- package/dist/esm/src/managers/pathfinding/sceneDataManager.js +13 -0
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +12 -143
- package/package.json +2 -2
|
@@ -156,8 +156,30 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
156
156
|
value: function createPipePaths(paths, crosscubeTextureSet) {
|
|
157
157
|
var _this3 = this;
|
|
158
158
|
var sceneViewer = this.sceneViewer;
|
|
159
|
-
var globalSegmentIndex = 0; // Counter for globally unique segment indices
|
|
160
159
|
|
|
160
|
+
// Find the highest segment index currently in use (both computed SEGMENT-X and manual Segment-X)
|
|
161
|
+
var maxExistingIndex = -1;
|
|
162
|
+
sceneViewer.scene.traverse(function (obj) {
|
|
163
|
+
if (obj.uuid) {
|
|
164
|
+
// Check for computed segments: SEGMENT-123
|
|
165
|
+
var computedMatch = obj.uuid.match(/^SEGMENT-(\d+)$/);
|
|
166
|
+
if (computedMatch) {
|
|
167
|
+
var index = parseInt(computedMatch[1], 10);
|
|
168
|
+
maxExistingIndex = Math.max(maxExistingIndex, index);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Check for manual segments: Segment-123
|
|
172
|
+
var manualMatch = obj.uuid.match(/^Segment-(\d+)$/);
|
|
173
|
+
if (manualMatch) {
|
|
174
|
+
var _index = parseInt(manualMatch[1], 10);
|
|
175
|
+
maxExistingIndex = Math.max(maxExistingIndex, _index);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Start counter after the highest existing index to prevent UUID conflicts
|
|
181
|
+
var globalSegmentIndex = maxExistingIndex + 1;
|
|
182
|
+
console.log("\uD83D\uDD22 Starting segment index at ".concat(globalSegmentIndex, " (max existing: ").concat(maxExistingIndex, ")"));
|
|
161
183
|
var pipeRadius = 0.1;
|
|
162
184
|
var pipeMaterial = this.createPipeMaterial(crosscubeTextureSet);
|
|
163
185
|
paths.forEach(function (pathData, index) {
|
|
@@ -176,6 +198,10 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
176
198
|
}
|
|
177
199
|
});
|
|
178
200
|
|
|
201
|
+
// Check if endpoints are component connectors (from pathfinder result)
|
|
202
|
+
var fromIsComponentConnector = pathData.fromObjectType === 'component-connector';
|
|
203
|
+
var toIsComponentConnector = pathData.toObjectType === 'component-connector';
|
|
204
|
+
|
|
179
205
|
// Create one cylinder per segment (after colinear optimization, this should be minimal segments)
|
|
180
206
|
for (var j = 0; j < pathPoints.length - 1; j++) {
|
|
181
207
|
var start = pathPoints[j];
|
|
@@ -204,13 +230,19 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
204
230
|
// Make pipe segments selectable and add identifying data
|
|
205
231
|
var segmentId = cylinder.uuid;
|
|
206
232
|
|
|
233
|
+
// Determine if this segment should be immutable (first or last 0.5-unit segment connected to component)
|
|
234
|
+
var isFirstSegment = j === 0;
|
|
235
|
+
var isLastSegment = j === pathPoints.length - 2;
|
|
236
|
+
var isImmutable = fromIsComponentConnector && isFirstSegment || toIsComponentConnector && isLastSegment;
|
|
237
|
+
|
|
207
238
|
// Add userData to make pipe segments selectable and for tooltip display
|
|
208
239
|
cylinder.userData = {
|
|
209
240
|
objectType: 'segment',
|
|
210
241
|
segmentId: segmentId,
|
|
211
242
|
segmentIndex: globalSegmentIndex,
|
|
212
243
|
pathFrom: pathData.from,
|
|
213
|
-
pathTo: pathData.to
|
|
244
|
+
pathTo: pathData.to,
|
|
245
|
+
immutable: isImmutable // Mark segments connected to component connectors as immutable
|
|
214
246
|
};
|
|
215
247
|
|
|
216
248
|
// Increment global segment counter
|
|
@@ -275,6 +307,8 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
275
307
|
pathFrom: pathData.from,
|
|
276
308
|
pathTo: pathData.to,
|
|
277
309
|
angle: (angle * 180 / Math.PI).toFixed(1),
|
|
310
|
+
immutable: true,
|
|
311
|
+
// Mark computed elbows as immutable
|
|
278
312
|
// Add component data for tooltips
|
|
279
313
|
component: {
|
|
280
314
|
type: 'PipeElbow',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { inherits as _inherits, createClass as _createClass, superPropGet as _superPropGet, classCallCheck as _classCallCheck, callSuper as _callSuper, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator
|
|
1
|
+
import { inherits as _inherits, createClass as _createClass, superPropGet as _superPropGet, classCallCheck as _classCallCheck, callSuper as _callSuper, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
2
|
import 'three';
|
|
3
3
|
import { Pathfinder } from '@2112-lab/pathfinder';
|
|
4
4
|
import { BaseDisposable } from '../../core/baseDisposable.js';
|
|
@@ -123,13 +123,6 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
123
123
|
connectionsCopy,
|
|
124
124
|
simplifiedSceneData,
|
|
125
125
|
pathfindingResult,
|
|
126
|
-
intersectionCheck,
|
|
127
|
-
_this$sceneViewer,
|
|
128
|
-
operationHistoryManager,
|
|
129
|
-
lastOp,
|
|
130
|
-
undoSuccess,
|
|
131
|
-
correctedResult,
|
|
132
|
-
_this$sceneViewer2,
|
|
133
126
|
_args = arguments;
|
|
134
127
|
return _regenerator().w(function (_context) {
|
|
135
128
|
while (1) switch (_context.n) {
|
|
@@ -164,93 +157,79 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
164
157
|
console.log('Rewired connections:', JSON.parse(JSON.stringify(pathfindingResult.rewiredConnections)));
|
|
165
158
|
console.log("intersectionCheck input:", pathfindingResult.paths);
|
|
166
159
|
|
|
167
|
-
// Check for path intersections (including manual segments)
|
|
168
|
-
intersectionCheck = this.checkPathIntersections(pathfindingResult.paths, 0.2, true);
|
|
169
|
-
pathfindingResult.intersections = intersectionCheck;
|
|
170
|
-
|
|
171
|
-
console.log("intersectionCheck
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
160
|
+
// // Check for path intersections (including manual segments)
|
|
161
|
+
// const intersectionCheck = this.checkPathIntersections(pathfindingResult.paths, 0.2, true);
|
|
162
|
+
// pathfindingResult.intersections = intersectionCheck;
|
|
163
|
+
|
|
164
|
+
// console.log("intersectionCheck:", intersectionCheck);
|
|
165
|
+
// console.log("intersectionCheck.hasIntersections:", intersectionCheck.hasIntersections);
|
|
166
|
+
|
|
167
|
+
// // Handle intersection detection - undo last operation if intersections found
|
|
168
|
+
// // Skip this if we're already in the middle of an undo operation
|
|
169
|
+
// if (intersectionCheck.hasIntersections && !this.isUndoInProgress) {
|
|
170
|
+
// console.warn('⚠️ Path intersections detected! Attempting to undo last operation...');
|
|
171
|
+
|
|
172
|
+
// // Set flag to prevent recursive undo attempts
|
|
173
|
+
// this.isUndoInProgress = true;
|
|
174
|
+
|
|
175
|
+
// // Access operationHistoryManager through sceneViewer.managers.operationHistory
|
|
176
|
+
// const operationHistoryManager = this.sceneViewer?.managers?.operationHistory;
|
|
177
|
+
|
|
178
|
+
// if (operationHistoryManager) {
|
|
179
|
+
// const lastOp = operationHistoryManager.getLastOperation();
|
|
180
|
+
|
|
181
|
+
// if (lastOp) {
|
|
182
|
+
// console.warn(`⚠️ Intersection caused by operation: ${lastOp.operationName}`, lastOp.params);
|
|
183
|
+
|
|
184
|
+
// // Attempt to undo the operation FIRST (before removing computed objects)
|
|
185
|
+
// // This is important because undo needs to find the segment that was moved
|
|
186
|
+
// const undoSuccess = operationHistoryManager.undoLastOperation();
|
|
187
|
+
|
|
188
|
+
// if (undoSuccess) {
|
|
189
|
+
// console.log('✅ Successfully undid operation that caused intersection');
|
|
190
|
+
|
|
191
|
+
// // Now remove the buggy computed objects that were created with the invalid state
|
|
192
|
+
// console.log('🗑️ Removing buggy computed objects after undo...');
|
|
193
|
+
// this.removeComputedObjects();
|
|
194
|
+
|
|
195
|
+
// // Re-run pathfinding after undo to restore valid state
|
|
196
|
+
// console.log('🔄 Re-running pathfinding after undo to restore clean state...');
|
|
197
|
+
|
|
198
|
+
// // Recursively call _executePathfinding with the corrected scene state
|
|
199
|
+
// // This is safe because we've undone the operation, so we won't get into an infinite loop
|
|
200
|
+
// const correctedResult = await this._executePathfinding(
|
|
201
|
+
// sceneData,
|
|
202
|
+
// connections,
|
|
203
|
+
// { ...options, context: `${context} (After Undo)` }
|
|
204
|
+
// );
|
|
205
|
+
|
|
206
|
+
// // Mark that we performed an undo and return the corrected result
|
|
207
|
+
// correctedResult.undoPerformed = true;
|
|
208
|
+
// correctedResult.undoneOperation = lastOp;
|
|
209
|
+
|
|
210
|
+
// // Clear the undo flag before returning
|
|
211
|
+
// this.isUndoInProgress = false;
|
|
212
|
+
|
|
213
|
+
// return correctedResult;
|
|
214
|
+
// } else {
|
|
215
|
+
// console.error('❌ Failed to undo operation that caused intersection');
|
|
216
|
+
// pathfindingResult.undoFailed = true;
|
|
217
|
+
// // Clear the undo flag even on failure
|
|
218
|
+
// this.isUndoInProgress = false;
|
|
219
|
+
// }
|
|
220
|
+
// } else {
|
|
221
|
+
// console.warn('⚠️ No operation in history to undo');
|
|
222
|
+
// this.isUndoInProgress = false;
|
|
223
|
+
// }
|
|
224
|
+
// } else {
|
|
225
|
+
// console.error('❌ OperationHistoryManager not available for undo');
|
|
226
|
+
// console.error(' Available managers:', Object.keys(this.sceneViewer?.managers || {}));
|
|
227
|
+
// this.isUndoInProgress = false;
|
|
228
|
+
// }
|
|
229
|
+
// } else if (intersectionCheck.hasIntersections && this.isUndoInProgress) {
|
|
230
|
+
// console.log('⏭️ Skipping intersection handling - undo already in progress');
|
|
231
|
+
// }
|
|
205
232
|
|
|
206
|
-
// Now remove the buggy computed objects that were created with the invalid state
|
|
207
|
-
console.log('🗑️ Removing buggy computed objects after undo...');
|
|
208
|
-
this.removeComputedObjects();
|
|
209
|
-
|
|
210
|
-
// Re-run pathfinding after undo to restore valid state
|
|
211
|
-
console.log('🔄 Re-running pathfinding after undo to restore clean state...');
|
|
212
|
-
|
|
213
|
-
// Recursively call _executePathfinding with the corrected scene state
|
|
214
|
-
// This is safe because we've undone the operation, so we won't get into an infinite loop
|
|
215
|
-
_context.n = 1;
|
|
216
|
-
return this._executePathfinding(sceneData, connections, _objectSpread2(_objectSpread2({}, options), {}, {
|
|
217
|
-
context: "".concat(context, " (After Undo)")
|
|
218
|
-
}));
|
|
219
|
-
case 1:
|
|
220
|
-
correctedResult = _context.v;
|
|
221
|
-
// Mark that we performed an undo and return the corrected result
|
|
222
|
-
correctedResult.undoPerformed = true;
|
|
223
|
-
correctedResult.undoneOperation = lastOp;
|
|
224
|
-
|
|
225
|
-
// Clear the undo flag before returning
|
|
226
|
-
this.isUndoInProgress = false;
|
|
227
|
-
return _context.a(2, correctedResult);
|
|
228
|
-
case 2:
|
|
229
|
-
console.error('❌ Failed to undo operation that caused intersection');
|
|
230
|
-
pathfindingResult.undoFailed = true;
|
|
231
|
-
// Clear the undo flag even on failure
|
|
232
|
-
this.isUndoInProgress = false;
|
|
233
|
-
case 3:
|
|
234
|
-
_context.n = 5;
|
|
235
|
-
break;
|
|
236
|
-
case 4:
|
|
237
|
-
console.warn('⚠️ No operation in history to undo');
|
|
238
|
-
this.isUndoInProgress = false;
|
|
239
|
-
case 5:
|
|
240
|
-
_context.n = 7;
|
|
241
|
-
break;
|
|
242
|
-
case 6:
|
|
243
|
-
console.error('❌ OperationHistoryManager not available for undo');
|
|
244
|
-
console.error(' Available managers:', Object.keys(((_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.managers) || {}));
|
|
245
|
-
this.isUndoInProgress = false;
|
|
246
|
-
case 7:
|
|
247
|
-
_context.n = 9;
|
|
248
|
-
break;
|
|
249
|
-
case 8:
|
|
250
|
-
if (intersectionCheck.hasIntersections && this.isUndoInProgress) {
|
|
251
|
-
console.log('⏭️ Skipping intersection handling - undo already in progress');
|
|
252
|
-
}
|
|
253
|
-
case 9:
|
|
254
233
|
// Create gateways in the scene if requested
|
|
255
234
|
if (options.createGateways && pathfindingResult.gateways) {
|
|
256
235
|
this.renderingManager.createGateways(pathfindingResult);
|
|
@@ -95,10 +95,23 @@ var SceneDataManager = /*#__PURE__*/function () {
|
|
|
95
95
|
worldBoundingBox: worldBoundingBox
|
|
96
96
|
})
|
|
97
97
|
};
|
|
98
|
+
|
|
99
|
+
// For connectors and gateways, add world position
|
|
98
100
|
if (obj.userData.objectType.includes('connector') || obj.userData.objectType === 'gateway') {
|
|
99
101
|
var worldPosition = new THREE.Vector3();
|
|
100
102
|
obj.getWorldPosition(worldPosition);
|
|
101
103
|
results.userData.position = [worldPosition.x, worldPosition.y, worldPosition.z];
|
|
104
|
+
|
|
105
|
+
// Differentiate component connectors from segment connectors for pathfinder
|
|
106
|
+
// Component connectors are children of components
|
|
107
|
+
if (obj.userData.objectType === 'connector') {
|
|
108
|
+
var _parent$userData;
|
|
109
|
+
// Check if parent is a component (not a segment)
|
|
110
|
+
var parent = obj.parent;
|
|
111
|
+
if (parent && ((_parent$userData = parent.userData) === null || _parent$userData === void 0 ? void 0 : _parent$userData.objectType) === 'component') {
|
|
112
|
+
results.userData.objectType = 'component-connector';
|
|
113
|
+
}
|
|
114
|
+
}
|
|
102
115
|
}
|
|
103
116
|
return results;
|
|
104
117
|
});
|
|
@@ -1328,7 +1328,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1328
1328
|
}, {
|
|
1329
1329
|
key: "manualizeSegment",
|
|
1330
1330
|
value: function manualizeSegment(segment, currentSceneData) {
|
|
1331
|
-
var _segment$userData, _this$sceneViewer$man;
|
|
1331
|
+
var _segment$userData, _segment$material$use, _this$sceneViewer$man;
|
|
1332
1332
|
if (!segment || !((_segment$userData = segment.userData) !== null && _segment$userData !== void 0 && _segment$userData.objectType) === 'segment') {
|
|
1333
1333
|
console.log('❌ Object is not a pipe segment:', {
|
|
1334
1334
|
isObject: !!segment,
|
|
@@ -1345,6 +1345,16 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1345
1345
|
return;
|
|
1346
1346
|
}
|
|
1347
1347
|
|
|
1348
|
+
// CRITICAL: Clone the material BEFORE changing its color
|
|
1349
|
+
// This prevents the color change from affecting other segments that share the same material instance
|
|
1350
|
+
if (segment.material && !((_segment$material$use = segment.material.userData) !== null && _segment$material$use !== void 0 && _segment$material$use.isCloned)) {
|
|
1351
|
+
var originalMaterial = segment.material;
|
|
1352
|
+
segment.material = originalMaterial.clone();
|
|
1353
|
+
segment.material.userData = segment.material.userData || {};
|
|
1354
|
+
segment.material.userData.isCloned = true;
|
|
1355
|
+
console.log('📋 Cloned segment material to prevent shared material mutation');
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1348
1358
|
// Override material color to blue in dev mode
|
|
1349
1359
|
var isDev = false;
|
|
1350
1360
|
if (typeof window !== 'undefined') {
|
|
@@ -1369,7 +1379,7 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1369
1379
|
// Change from "SEGMENT-X" to "Segment-X" (capital S to lowercase s)
|
|
1370
1380
|
var segmentIndex = segment.userData.segmentIndex;
|
|
1371
1381
|
var oldUuid = segment.uuid;
|
|
1372
|
-
segment.uuid = "
|
|
1382
|
+
segment.uuid = "SEGMENT-".concat(segmentIndex);
|
|
1373
1383
|
console.log("\uD83D\uDD27 Renamed segment UUID from ".concat(oldUuid, " to: ").concat(segment.uuid));
|
|
1374
1384
|
|
|
1375
1385
|
// Calculate segment endpoints in world coordinates
|
|
@@ -1626,147 +1636,6 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1626
1636
|
}
|
|
1627
1637
|
console.log("\u2705 Gateway ".concat(gateway.uuid, " successfully converted to manual (declared)"));
|
|
1628
1638
|
}
|
|
1629
|
-
|
|
1630
|
-
/**
|
|
1631
|
-
* Split a segment by manualizing it and shortening it by 0.5 units
|
|
1632
|
-
* The segment gets converted to a declared (manual) segment with connectors,
|
|
1633
|
-
* and is shortened from the end that has a component connector (or the end if no connectors)
|
|
1634
|
-
* @param {string|THREE.Object3D} segmentIdOrObject - The UUID or Three.js object of the segment to split
|
|
1635
|
-
* @param {Object} currentSceneData - Current scene data with connections
|
|
1636
|
-
* @returns {THREE.Object3D|null} The shortened manual segment or null on failure
|
|
1637
|
-
*/
|
|
1638
|
-
}, {
|
|
1639
|
-
key: "splitSegment",
|
|
1640
|
-
value: function splitSegment(segmentIdOrObject, currentSceneData) {
|
|
1641
|
-
var _segment$userData3,
|
|
1642
|
-
_this6 = this;
|
|
1643
|
-
console.log('✂️ splitSegment started:', segmentIdOrObject);
|
|
1644
|
-
|
|
1645
|
-
// Find the segment object
|
|
1646
|
-
var segment = null;
|
|
1647
|
-
if (typeof segmentIdOrObject === 'string') {
|
|
1648
|
-
this.sceneViewer.scene.traverse(function (child) {
|
|
1649
|
-
var _child$userData10;
|
|
1650
|
-
if (child.uuid === segmentIdOrObject || ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.originalUuid) === segmentIdOrObject) {
|
|
1651
|
-
segment = child;
|
|
1652
|
-
}
|
|
1653
|
-
});
|
|
1654
|
-
} else if (segmentIdOrObject && segmentIdOrObject.isObject3D) {
|
|
1655
|
-
segment = segmentIdOrObject;
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
// Validate segment
|
|
1659
|
-
if (!segment || ((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.objectType) !== 'segment') {
|
|
1660
|
-
console.error('❌ splitSegment(): Invalid segment or not found');
|
|
1661
|
-
return null;
|
|
1662
|
-
}
|
|
1663
|
-
if (!currentSceneData) {
|
|
1664
|
-
console.error('❌ splitSegment(): currentSceneData is required');
|
|
1665
|
-
return null;
|
|
1666
|
-
}
|
|
1667
|
-
console.log('✂️ Splitting/shortening segment:', segment.uuid);
|
|
1668
|
-
|
|
1669
|
-
// Get segment geometry to calculate endpoints
|
|
1670
|
-
var geometry = segment.geometry;
|
|
1671
|
-
if (!geometry || !geometry.parameters) {
|
|
1672
|
-
console.error('❌ splitSegment(): Segment has invalid geometry');
|
|
1673
|
-
return null;
|
|
1674
|
-
}
|
|
1675
|
-
var segmentLength = geometry.parameters.height || 1;
|
|
1676
|
-
var segmentRadius = geometry.parameters.radiusTop || 0.1;
|
|
1677
|
-
var shortenAmount = 0.5;
|
|
1678
|
-
var newLength = segmentLength - shortenAmount;
|
|
1679
|
-
if (newLength <= 0) {
|
|
1680
|
-
console.error('❌ splitSegment(): Segment too short to shorten by 0.5');
|
|
1681
|
-
return null;
|
|
1682
|
-
}
|
|
1683
|
-
|
|
1684
|
-
// Calculate segment direction vector
|
|
1685
|
-
var direction = new THREE.Vector3(0, 1, 0);
|
|
1686
|
-
direction.applyQuaternion(segment.quaternion);
|
|
1687
|
-
direction.normalize();
|
|
1688
|
-
|
|
1689
|
-
// Calculate original segment endpoints
|
|
1690
|
-
var startPoint = new THREE.Vector3();
|
|
1691
|
-
startPoint.copy(segment.position).sub(direction.clone().multiplyScalar(segmentLength / 2));
|
|
1692
|
-
var endPoint = new THREE.Vector3();
|
|
1693
|
-
endPoint.copy(segment.position).add(direction.clone().multiplyScalar(segmentLength / 2));
|
|
1694
|
-
|
|
1695
|
-
// Check for component connectors at endpoints
|
|
1696
|
-
var findConnectorsAtPosition = function findConnectorsAtPosition(position) {
|
|
1697
|
-
var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.15;
|
|
1698
|
-
var connectors = [];
|
|
1699
|
-
_this6.sceneViewer.scene.traverse(function (child) {
|
|
1700
|
-
var _child$userData11;
|
|
1701
|
-
if (((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType) === 'connector') {
|
|
1702
|
-
var connectorWorldPos = new THREE.Vector3();
|
|
1703
|
-
child.getWorldPosition(connectorWorldPos);
|
|
1704
|
-
var distance = connectorWorldPos.distanceTo(position);
|
|
1705
|
-
if (distance <= tolerance) {
|
|
1706
|
-
connectors.push(child);
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
});
|
|
1710
|
-
return connectors.filter(function (c) {
|
|
1711
|
-
var _c$userData;
|
|
1712
|
-
return ((_c$userData = c.userData) === null || _c$userData === void 0 ? void 0 : _c$userData.objectType) !== 'segment-connector';
|
|
1713
|
-
});
|
|
1714
|
-
};
|
|
1715
|
-
var startConnectors = findConnectorsAtPosition(startPoint);
|
|
1716
|
-
var endConnectors = findConnectorsAtPosition(endPoint);
|
|
1717
|
-
|
|
1718
|
-
// Determine which end to shorten from
|
|
1719
|
-
var newStartPoint, newEndPoint;
|
|
1720
|
-
if (endConnectors.length > 0) {
|
|
1721
|
-
// Component connector at end - shorten from end
|
|
1722
|
-
newStartPoint = startPoint.clone();
|
|
1723
|
-
newEndPoint = endPoint.clone().sub(direction.clone().multiplyScalar(shortenAmount));
|
|
1724
|
-
console.log("\uD83D\uDCCD Component connector at END - shortening from end by ".concat(shortenAmount));
|
|
1725
|
-
} else if (startConnectors.length > 0) {
|
|
1726
|
-
// Component connector at start - shorten from start
|
|
1727
|
-
newStartPoint = startPoint.clone().add(direction.clone().multiplyScalar(shortenAmount));
|
|
1728
|
-
newEndPoint = endPoint.clone();
|
|
1729
|
-
console.log("\uD83D\uDCCD Component connector at START - shortening from start by ".concat(shortenAmount));
|
|
1730
|
-
} else {
|
|
1731
|
-
// No component connectors - shorten from end (default)
|
|
1732
|
-
newStartPoint = startPoint.clone();
|
|
1733
|
-
newEndPoint = endPoint.clone().sub(direction.clone().multiplyScalar(shortenAmount));
|
|
1734
|
-
console.log("\uD83D\uDCCD No component connectors - shortening from end by ".concat(shortenAmount));
|
|
1735
|
-
}
|
|
1736
|
-
console.log('📍 Segment shortening:', {
|
|
1737
|
-
originalStart: startPoint.toArray(),
|
|
1738
|
-
originalEnd: endPoint.toArray(),
|
|
1739
|
-
newStart: newStartPoint.toArray(),
|
|
1740
|
-
newEnd: newEndPoint.toArray(),
|
|
1741
|
-
originalLength: segmentLength,
|
|
1742
|
-
newLength: newLength,
|
|
1743
|
-
shortenAmount: shortenAmount
|
|
1744
|
-
});
|
|
1745
|
-
|
|
1746
|
-
// Get material from existing segment
|
|
1747
|
-
segment.material;
|
|
1748
|
-
|
|
1749
|
-
// Dispose old geometry and create new shortened geometry
|
|
1750
|
-
if (segment.geometry) {
|
|
1751
|
-
segment.geometry.dispose();
|
|
1752
|
-
}
|
|
1753
|
-
var newGeometry = new THREE.CylinderGeometry(segmentRadius, segmentRadius, newLength, 16, 1, false);
|
|
1754
|
-
segment.geometry = newGeometry;
|
|
1755
|
-
|
|
1756
|
-
// Reposition the segment to the new center
|
|
1757
|
-
var newPosition = new THREE.Vector3();
|
|
1758
|
-
newPosition.lerpVectors(newStartPoint, newEndPoint, 0.5);
|
|
1759
|
-
segment.position.copy(newPosition);
|
|
1760
|
-
// Quaternion stays the same
|
|
1761
|
-
|
|
1762
|
-
console.log('✅ Segment geometry updated and repositioned');
|
|
1763
|
-
|
|
1764
|
-
// Now manualize the shortened segment
|
|
1765
|
-
console.log('🔧 Manualizing the shortened segment...');
|
|
1766
|
-
this.manualizeSegment(segment, currentSceneData);
|
|
1767
|
-
console.log('✅ Segment split completed successfully - segment shortened and manualized');
|
|
1768
|
-
return segment;
|
|
1769
|
-
}
|
|
1770
1639
|
}]);
|
|
1771
1640
|
}();
|
|
1772
1641
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2112-lab/central-plant",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.51",
|
|
4
4
|
"description": "Utility modules for the Central Plant Application",
|
|
5
5
|
"main": "dist/bundle/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"author": "CentralPlant Team",
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@2112-lab/pathfinder": "1.0.
|
|
33
|
+
"@2112-lab/pathfinder": "1.0.32",
|
|
34
34
|
"stats.js": "^0.17.0",
|
|
35
35
|
"three": "^0.177.0"
|
|
36
36
|
},
|