@2112-lab/central-plant 0.3.47 → 0.3.49
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 +591 -476
- package/dist/cjs/src/core/centralPlant.js +44 -43
- package/dist/cjs/src/core/centralPlantInternals.js +4 -2
- package/dist/cjs/src/core/sceneViewer.js +1 -1
- package/dist/cjs/src/managers/components/componentManager.js +11 -3
- package/dist/cjs/src/managers/components/transformOperationsManager.js +9 -11
- package/dist/cjs/src/managers/controls/transformControlsManager.js +83 -44
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +272 -244
- package/dist/cjs/src/managers/scene/modelManager.js +33 -10
- package/dist/cjs/src/managers/scene/sceneExportManager.js +23 -30
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +48 -21
- package/dist/cjs/src/utils/boundingBoxUtils.js +62 -65
- package/dist/esm/src/core/centralPlant.js +44 -43
- package/dist/esm/src/core/centralPlantInternals.js +4 -2
- package/dist/esm/src/core/sceneViewer.js +1 -1
- package/dist/esm/src/managers/components/componentManager.js +11 -3
- package/dist/esm/src/managers/components/transformOperationsManager.js +9 -11
- package/dist/esm/src/managers/controls/transformControlsManager.js +83 -44
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +274 -246
- package/dist/esm/src/managers/scene/modelManager.js +33 -10
- package/dist/esm/src/managers/scene/sceneExportManager.js +24 -31
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +48 -21
- package/dist/esm/src/utils/boundingBoxUtils.js +62 -65
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
6
|
var THREE = require('three');
|
|
7
|
+
var nameUtils = require('../../utils/nameUtils.js');
|
|
7
8
|
var ioDeviceUtils = require('../../utils/ioDeviceUtils.js');
|
|
8
9
|
var behaviorRegistration = require('../../utils/behaviorRegistration.js');
|
|
9
10
|
var modelPreloader = require('../../rendering/modelPreloader.js');
|
|
@@ -162,36 +163,58 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
162
163
|
* @param {THREE.Object3D} targetMesh - The mesh whose connectors to preserve
|
|
163
164
|
* @param {string} parentUuid - The UUID of the parent component
|
|
164
165
|
*/
|
|
166
|
+
/**
|
|
167
|
+
* Identifies all connector objects within a model hierarchy and prepares them
|
|
168
|
+
* to be preserved when the model is replaced or modified.
|
|
169
|
+
* Uses traverse() to find connectors at any depth in the hierarchy.
|
|
170
|
+
* @param {THREE.Object3D} targetMesh - The root of the model to search
|
|
171
|
+
* @param {string} parentUuid - The UUID of the parent component
|
|
172
|
+
* @returns {Array<THREE.Object3D>} Array of cloned and prepared connector objects
|
|
173
|
+
*/
|
|
165
174
|
}, {
|
|
166
175
|
key: "_preserveConnectorChildren",
|
|
167
176
|
value: function _preserveConnectorChildren(targetMesh, parentUuid) {
|
|
168
177
|
var _this = this;
|
|
169
178
|
var connectorChildren = [];
|
|
170
|
-
|
|
179
|
+
var connectorIndex = 0;
|
|
180
|
+
|
|
181
|
+
// Use traverse to find connectors at ANY depth in the hierarchy
|
|
182
|
+
targetMesh.traverse(function (child) {
|
|
171
183
|
var _child$userData;
|
|
172
184
|
var isConnectorGeometry = child.geometry && (child.geometry.uuid === 'CONNECTOR-GEO' || child.geometry.type === 'SphereGeometry' && child.geometry.parameters);
|
|
173
185
|
var isConnectorByName = child.name && child.name.toLowerCase().includes('connector');
|
|
174
|
-
// Also recognise connectors declared via userData (e.g. inline connectors from SAMPLE_1.json
|
|
175
|
-
// whose geometry may be a fallback BufferGeometry rather than a SphereGeometry).
|
|
176
186
|
var isConnectorByUserData = ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector';
|
|
177
187
|
if (isConnectorGeometry && isConnectorByName || isConnectorByUserData) {
|
|
188
|
+
connectorIndex++;
|
|
189
|
+
|
|
178
190
|
// Ensure userData exists and has worldBoundingBox
|
|
179
191
|
if (!child.userData) child.userData = {};
|
|
180
192
|
if (!child.userData.worldBoundingBox) {
|
|
181
193
|
child.userData.worldBoundingBox = _this._calculateWorldBoundingBox(child);
|
|
182
194
|
}
|
|
183
195
|
|
|
184
|
-
// Clone
|
|
196
|
+
// Clone the connector
|
|
185
197
|
var clonedConnector = child.clone();
|
|
186
198
|
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
var
|
|
199
|
+
// CRITICAL: Convert nested world position to root-relative position
|
|
200
|
+
// This ensures the connector stays in the same place when re-added as a direct child of targetMesh
|
|
201
|
+
var targetInverse = targetMesh.matrixWorld.clone().invert();
|
|
202
|
+
var worldPos = new THREE__namespace.Vector3();
|
|
203
|
+
child.getWorldPosition(worldPos);
|
|
204
|
+
clonedConnector.position.copy(worldPos.applyMatrix4(targetInverse));
|
|
205
|
+
|
|
206
|
+
// Get hardcoded UUID if it exists (e.g. from JSON mesh placeholder)
|
|
207
|
+
// This ensures compatibility with existing scene JSON naming conventions
|
|
208
|
+
var existingUuid = nameUtils.getHardcodedUuid(child);
|
|
209
|
+
|
|
210
|
+
// Generate fallback UUID only if existing one isn't already parent-prefixed
|
|
211
|
+
// Format: COMPONENT-UUID-CONNECTOR-INDEX (stable fallback)
|
|
212
|
+
var connectorUuid = existingUuid && existingUuid.includes(parentUuid) ? existingUuid : "".concat(parentUuid, "-CONNECTOR-").concat(connectorIndex);
|
|
190
213
|
clonedConnector.uuid = connectorUuid;
|
|
191
214
|
if (child.userData) {
|
|
192
215
|
clonedConnector.userData = _rollupPluginBabelHelpers.objectSpread2({}, child.userData);
|
|
193
216
|
|
|
194
|
-
// Deep copy critical data
|
|
217
|
+
// Deep copy critical data
|
|
195
218
|
if (child.userData.worldBoundingBox) {
|
|
196
219
|
var wbb = child.userData.worldBoundingBox;
|
|
197
220
|
clonedConnector.userData.worldBoundingBox = {
|
|
@@ -200,7 +223,6 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
200
223
|
};
|
|
201
224
|
}
|
|
202
225
|
if (child.userData.direction) {
|
|
203
|
-
// Handle both array [x,y,z] and object {x,y,z} formats
|
|
204
226
|
if (Array.isArray(child.userData.direction)) {
|
|
205
227
|
clonedConnector.userData.direction = _rollupPluginBabelHelpers.toConsumableArray(child.userData.direction);
|
|
206
228
|
} else if (_rollupPluginBabelHelpers["typeof"](child.userData.direction) === 'object') {
|
|
@@ -212,11 +234,12 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
212
234
|
|
|
213
235
|
// Set originalUuid to match the actual uuid (maintains consistency)
|
|
214
236
|
clonedConnector.userData.originalUuid = connectorUuid;
|
|
215
|
-
clonedConnector.userData.objectType = child.userData.objectType ||
|
|
237
|
+
clonedConnector.userData.objectType = child.userData.objectType || 'connector';
|
|
216
238
|
}
|
|
217
239
|
connectorChildren.push(clonedConnector);
|
|
218
240
|
}
|
|
219
241
|
});
|
|
242
|
+
console.log("\uD83D\uDEE1\uFE0F Preserved ".concat(connectorChildren.length, " connector(s) for component ").concat(parentUuid));
|
|
220
243
|
return connectorChildren;
|
|
221
244
|
}
|
|
222
245
|
|
|
@@ -103,6 +103,11 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
103
103
|
// Helper function to convert Three.js object to minimal JSON format
|
|
104
104
|
var convertObjectToJson = function convertObjectToJson(threeObject) {
|
|
105
105
|
var _threeObject$name, _threeObject$userData, _threeObject$userData2, _threeObject$userData3, _threeObject$userData4, _threeObject$userData5, _threeObject$userData6, _threeObject$userData7, _threeObject$userData8, _threeObject$userData9, _threeObject$userData0, _threeObject$userData1, _threeObject$userData10;
|
|
106
|
+
// Ensure world matrices are updated for this subtree before exporting
|
|
107
|
+
if (threeObject.updateMatrixWorld) {
|
|
108
|
+
threeObject.updateMatrixWorld(true);
|
|
109
|
+
}
|
|
110
|
+
|
|
106
111
|
// Skip certain objects that shouldn't be exported
|
|
107
112
|
if (!threeObject || (_threeObject$name = threeObject.name) !== null && _threeObject$name !== void 0 && _threeObject$name.includes('Polyline') ||
|
|
108
113
|
// Skip pipe paths
|
|
@@ -241,11 +246,10 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
241
246
|
};
|
|
242
247
|
}
|
|
243
248
|
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
249
|
+
// Only manual segments persist their connector children here.
|
|
250
|
+
// Component connectors are NOT exported — they are regenerated from the
|
|
251
|
+
// component dictionary on load (see note below), keeping the scene JSON minimal.
|
|
247
252
|
if (threeObject.children && threeObject.children.length > 0) {
|
|
248
|
-
var _threeObject$userData11;
|
|
249
253
|
var exportableChildren = [];
|
|
250
254
|
if (isManualSegment) {
|
|
251
255
|
// For manual segments, export their connector children
|
|
@@ -259,26 +263,15 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
259
263
|
}
|
|
260
264
|
}
|
|
261
265
|
});
|
|
262
|
-
} else if (((_threeObject$userData11 = threeObject.userData) === null || _threeObject$userData11 === void 0 ? void 0 : _threeObject$userData11.objectType) === 'component') {
|
|
263
|
-
// For components, only export connectors that have objectType='connector'
|
|
264
|
-
// Standard dictionary-injected connectors should be exported so connections work on re-import
|
|
265
|
-
threeObject.children.forEach(function (child) {
|
|
266
|
-
var _child$userData2;
|
|
267
|
-
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'connector') {
|
|
268
|
-
exportableChildren.push({
|
|
269
|
-
uuid: child.uuid,
|
|
270
|
-
name: child.name,
|
|
271
|
-
type: 'Mesh',
|
|
272
|
-
position: {
|
|
273
|
-
x: roundIfClose(child.position.x),
|
|
274
|
-
y: roundIfClose(child.position.y),
|
|
275
|
-
z: roundIfClose(child.position.z)
|
|
276
|
-
},
|
|
277
|
-
userData: _rollupPluginBabelHelpers.objectSpread2({}, child.userData)
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
266
|
}
|
|
267
|
+
// NOTE: Component connectors are intentionally NOT exported.
|
|
268
|
+
// They are defined in the component dictionary and regenerated on load by
|
|
269
|
+
// sceneOperationsManager._injectConnectorChildrenFromDictionary using the
|
|
270
|
+
// matching uuid scheme (`${componentUuid}_${dictConnectorUuid}`), and the
|
|
271
|
+
// pathfinder rebuilds their world positions/bounding boxes on every run
|
|
272
|
+
// (computeConnectorBoundingBoxes). Connections still resolve because the
|
|
273
|
+
// regenerated connector uuids match the connection endpoints.
|
|
274
|
+
|
|
282
275
|
if (exportableChildren.length > 0) {
|
|
283
276
|
jsonObject.children = exportableChildren;
|
|
284
277
|
}
|
|
@@ -292,9 +285,9 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
292
285
|
// Extract main scene objects (components and standalone connectors)
|
|
293
286
|
var sceneChildren = [];
|
|
294
287
|
this.sceneViewer.scene.children.forEach(function (child) {
|
|
295
|
-
var _child$
|
|
288
|
+
var _child$userData2;
|
|
296
289
|
// Only export components and connectors; skip segments, gateways, polylines, etc.
|
|
297
|
-
var objectType = (_child$
|
|
290
|
+
var objectType = (_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType;
|
|
298
291
|
if (objectType !== 'component' && objectType !== 'connector') {
|
|
299
292
|
return;
|
|
300
293
|
}
|
|
@@ -458,14 +451,14 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
458
451
|
BufferGeometryUtils = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
|
|
459
452
|
exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
|
|
460
453
|
shouldExport = function shouldExport(child) {
|
|
461
|
-
var _child$name, _child$
|
|
454
|
+
var _child$name, _child$userData3, _child$userData4, _child$userData5, _child$userData6;
|
|
462
455
|
if ((_child$name = child.name) !== null && _child$name !== void 0 && _child$name.includes('Polyline')) return false; // Will handle separately
|
|
463
456
|
if (child.name === 'fogPlane') return false; // Skip fog plane
|
|
464
|
-
if ((_child$
|
|
465
|
-
if ((_child$
|
|
466
|
-
if ((_child$
|
|
457
|
+
if ((_child$userData3 = child.userData) !== null && _child$userData3 !== void 0 && _child$userData3.isBrickWall) return false; // Skip environment
|
|
458
|
+
if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBaseGround) return false; // Skip environment
|
|
459
|
+
if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGrid) return false; // Skip environment
|
|
467
460
|
if (child.isLight) return false; // Skip lights
|
|
468
|
-
if ((_child$
|
|
461
|
+
if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isTransformControls) return false; // Skip transform controls
|
|
469
462
|
if (child.isTransformControls) return false; // Skip transform controls
|
|
470
463
|
if (child.type && child.type.includes('TransformControls')) return false;
|
|
471
464
|
if (child.type && child.type.includes('Helper')) return false; // Skip helpers
|
|
@@ -890,6 +890,19 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
890
890
|
if (!(data !== null && data !== void 0 && (_data$scene2 = data.scene) !== null && _data$scene2 !== void 0 && _data$scene2.children) || !componentDictionary) {
|
|
891
891
|
return;
|
|
892
892
|
}
|
|
893
|
+
|
|
894
|
+
// Collect every connector uuid referenced by the scene's connections so we
|
|
895
|
+
// can inject connectors under the SAME uuid scheme the scene actually uses.
|
|
896
|
+
// Two schemes exist in the wild:
|
|
897
|
+
// - Preferred (runtime add path + minimal export): `${componentUuid}_${dictConnectorUuid}`
|
|
898
|
+
// - Legacy (older hand-authored scenes): `${componentUuid}-CONNECTOR-${index+1}`
|
|
899
|
+
var connectionEndpoints = new Set();
|
|
900
|
+
if (Array.isArray(data.connections)) {
|
|
901
|
+
data.connections.forEach(function (conn) {
|
|
902
|
+
if (conn !== null && conn !== void 0 && conn.from) connectionEndpoints.add(conn.from);
|
|
903
|
+
if (conn !== null && conn !== void 0 && conn.to) connectionEndpoints.add(conn.to);
|
|
904
|
+
});
|
|
905
|
+
}
|
|
893
906
|
var componentsProcessed = 0;
|
|
894
907
|
var connectorsInjected = 0;
|
|
895
908
|
data.scene.children.forEach(function (child) {
|
|
@@ -912,9 +925,18 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
912
925
|
|
|
913
926
|
// Deep clone the connector children from the dictionary
|
|
914
927
|
child.children = dictEntry.children.map(function (connector, index) {
|
|
915
|
-
//
|
|
916
|
-
//
|
|
917
|
-
|
|
928
|
+
// Choose the connector uuid that matches the scheme the scene's
|
|
929
|
+
// connections reference. Prefer `${componentUuid}_${dictConnectorUuid}`
|
|
930
|
+
// (sandbox add path + minimal export); fall back to the legacy
|
|
931
|
+
// index-based scheme `${componentUuid}-CONNECTOR-${index+1}` when the
|
|
932
|
+
// connections reference that form. If neither is referenced (e.g. an
|
|
933
|
+
// unconnected connector), default to the preferred scheme.
|
|
934
|
+
var legacyUuid = "".concat(child.uuid, "-CONNECTOR-").concat(index + 1);
|
|
935
|
+
var preferredUuid = connector.uuid ? "".concat(child.uuid, "_").concat(connector.uuid) : legacyUuid;
|
|
936
|
+
var connectorUuid = preferredUuid;
|
|
937
|
+
if (!connectionEndpoints.has(preferredUuid) && connectionEndpoints.has(legacyUuid)) {
|
|
938
|
+
connectorUuid = legacyUuid;
|
|
939
|
+
}
|
|
918
940
|
|
|
919
941
|
// Clone connector with deep copy of userData
|
|
920
942
|
var clonedConnector = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, connector), {}, {
|
|
@@ -1348,24 +1370,29 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1348
1370
|
children: [] // Initialize children array
|
|
1349
1371
|
};
|
|
1350
1372
|
|
|
1351
|
-
// Collect children that are connectors
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1373
|
+
// Collect children that are connectors (using traverse to find deep children in models)
|
|
1374
|
+
componentModel.traverse(function (child) {
|
|
1375
|
+
if (child.userData && child.userData.objectType === 'connector') {
|
|
1376
|
+
// Calculate position relative to component root
|
|
1377
|
+
// This ensures that when we re-add it as a direct child of the component,
|
|
1378
|
+
// it maintains the same world position relative to the component.
|
|
1379
|
+
var componentMatrixWorldInverse = componentModel.matrixWorld.clone().invert();
|
|
1380
|
+
var childWorldPos = new THREE__namespace.Vector3();
|
|
1381
|
+
child.getWorldPosition(childWorldPos);
|
|
1382
|
+
var relativePos = childWorldPos.applyMatrix4(componentMatrixWorldInverse);
|
|
1383
|
+
componentSceneData.children.push({
|
|
1384
|
+
uuid: child.uuid,
|
|
1385
|
+
name: child.name,
|
|
1386
|
+
type: 'Mesh',
|
|
1387
|
+
position: {
|
|
1388
|
+
x: relativePos.x,
|
|
1389
|
+
y: relativePos.y,
|
|
1390
|
+
z: relativePos.z
|
|
1391
|
+
},
|
|
1392
|
+
userData: _rollupPluginBabelHelpers.objectSpread2({}, child.userData)
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1369
1396
|
|
|
1370
1397
|
// Add the component to the scene data
|
|
1371
1398
|
if (!currentSceneData.scene.children) {
|
|
@@ -179,41 +179,36 @@ function computeFilteredBoundingBox(object) {
|
|
|
179
179
|
*/
|
|
180
180
|
function computeIODeviceBoundingBoxes(componentObject) {
|
|
181
181
|
var results = [];
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
182
|
+
componentObject.traverse(function (child) {
|
|
183
|
+
var _child$userData;
|
|
184
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) !== 'io-device') return;
|
|
185
|
+
var bbox = new THREE__namespace.Box3().setFromObject(child);
|
|
186
|
+
var worldPos = new THREE__namespace.Vector3();
|
|
187
|
+
child.getWorldPosition(worldPos);
|
|
188
|
+
if (!bbox.isEmpty()) {
|
|
189
|
+
results.push({
|
|
190
|
+
uuid: child.uuid,
|
|
191
|
+
userData: {
|
|
192
|
+
objectType: 'io-device',
|
|
193
|
+
deviceId: child.userData.deviceId || null,
|
|
194
|
+
attachmentId: child.userData.attachmentId || null,
|
|
195
|
+
parentComponentId: child.userData.parentComponentId || componentObject.uuid,
|
|
196
|
+
// Sync position for pathfinder
|
|
197
|
+
position: [worldPos.x, worldPos.y, worldPos.z]
|
|
198
|
+
},
|
|
199
|
+
worldBoundingBox: {
|
|
200
|
+
min: [bbox.min.x, bbox.min.y, bbox.min.z],
|
|
201
|
+
max: [bbox.max.x, bbox.max.y, bbox.max.z]
|
|
202
|
+
}
|
|
203
|
+
});
|
|
205
204
|
}
|
|
206
|
-
}
|
|
207
|
-
_iterator.e(err);
|
|
208
|
-
} finally {
|
|
209
|
-
_iterator.f();
|
|
210
|
-
}
|
|
205
|
+
});
|
|
211
206
|
return results;
|
|
212
207
|
}
|
|
213
208
|
|
|
214
209
|
/**
|
|
215
210
|
* Computes individual world-space bounding boxes for each connector child
|
|
216
|
-
* of a component.
|
|
211
|
+
* of a component. Supports deep children (e.g. within GLB model hierarchy).
|
|
217
212
|
*
|
|
218
213
|
* @param {THREE.Object3D} componentObject - The component's Three.js object
|
|
219
214
|
* @returns {Array<{uuid: string, userData: Object, worldBoundingBox: {min: number[], max: number[]}}>}
|
|
@@ -221,38 +216,40 @@ function computeIODeviceBoundingBoxes(componentObject) {
|
|
|
221
216
|
*/
|
|
222
217
|
function computeConnectorBoundingBoxes(componentObject) {
|
|
223
218
|
var results = [];
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) !== 'connector') continue;
|
|
231
|
-
var bbox = new THREE__namespace.Box3().setFromObject(child);
|
|
219
|
+
componentObject.traverse(function (child) {
|
|
220
|
+
var _child$userData2;
|
|
221
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) !== 'connector') return;
|
|
222
|
+
var bbox = new THREE__namespace.Box3().setFromObject(child);
|
|
223
|
+
var worldPos = new THREE__namespace.Vector3();
|
|
224
|
+
child.getWorldPosition(worldPos);
|
|
232
225
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
worldBoundingBox: {
|
|
246
|
-
min: [bbox.min.x, bbox.min.y, bbox.min.z],
|
|
247
|
-
max: [bbox.max.x, bbox.max.y, bbox.max.z]
|
|
248
|
-
}
|
|
249
|
-
});
|
|
226
|
+
// Compute world-space direction vector (Crucial for rotation-aware pathfinding)
|
|
227
|
+
// Default to [0, 0, 1] if not specified (Standard for our coordinate system)
|
|
228
|
+
var localDirData = child.userData && Array.isArray(child.userData.direction) ? child.userData.direction : [0, 0, 1];
|
|
229
|
+
var localDir = new THREE__namespace.Vector3(localDirData[0], localDirData[1], localDirData[2]);
|
|
230
|
+
var worldQuat = new THREE__namespace.Quaternion();
|
|
231
|
+
child.getWorldQuaternion(worldQuat);
|
|
232
|
+
var worldDir = localDir.clone().applyQuaternion(worldQuat).normalize();
|
|
233
|
+
|
|
234
|
+
// Fallback if mesh is too small or empty (sometimes connectors are just points)
|
|
235
|
+
if (bbox.isEmpty() || bbox.getSize(new THREE__namespace.Vector3()).length() < 0.01) {
|
|
236
|
+
var size = 0.1;
|
|
237
|
+
bbox.setFromCenterAndSize(worldPos, new THREE__namespace.Vector3(size, size, size));
|
|
250
238
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
239
|
+
results.push({
|
|
240
|
+
uuid: child.uuid,
|
|
241
|
+
userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
|
|
242
|
+
objectType: 'connector',
|
|
243
|
+
// Update both position AND direction for pathfinder
|
|
244
|
+
position: [worldPos.x, worldPos.y, worldPos.z],
|
|
245
|
+
direction: [worldDir.x, worldDir.y, worldDir.z]
|
|
246
|
+
}),
|
|
247
|
+
worldBoundingBox: {
|
|
248
|
+
min: [bbox.min.x, bbox.min.y, bbox.min.z],
|
|
249
|
+
max: [bbox.max.x, bbox.max.y, bbox.max.z]
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
});
|
|
256
253
|
return results;
|
|
257
254
|
}
|
|
258
255
|
|
|
@@ -352,11 +349,11 @@ function createSelectionBoxHelpers(object) {
|
|
|
352
349
|
* @param {THREE.Scene} scene - The scene (for finding objects by uuid)
|
|
353
350
|
*/
|
|
354
351
|
function updateSelectionBoxHelpers(helpers, selectedObjects, scene) {
|
|
355
|
-
var
|
|
356
|
-
|
|
352
|
+
var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(helpers),
|
|
353
|
+
_step;
|
|
357
354
|
try {
|
|
358
355
|
var _loop = function _loop() {
|
|
359
|
-
var helper =
|
|
356
|
+
var helper = _step.value;
|
|
360
357
|
var _helper$userData = helper.userData,
|
|
361
358
|
sourceObjectUuid = _helper$userData.sourceObjectUuid,
|
|
362
359
|
isFiltered = _helper$userData.isFiltered,
|
|
@@ -387,13 +384,13 @@ function updateSelectionBoxHelpers(helpers, selectedObjects, scene) {
|
|
|
387
384
|
helper.update();
|
|
388
385
|
}
|
|
389
386
|
};
|
|
390
|
-
for (
|
|
387
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
391
388
|
if (_loop()) continue;
|
|
392
389
|
}
|
|
393
390
|
} catch (err) {
|
|
394
|
-
|
|
391
|
+
_iterator.e(err);
|
|
395
392
|
} finally {
|
|
396
|
-
|
|
393
|
+
_iterator.f();
|
|
397
394
|
}
|
|
398
395
|
}
|
|
399
396
|
|
|
@@ -33,7 +33,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
33
33
|
* Initialize the CentralPlant manager
|
|
34
34
|
*
|
|
35
35
|
* @constructor
|
|
36
|
-
* @version 0.3.
|
|
36
|
+
* @version 0.3.49
|
|
37
37
|
* @updated 2025-10-22
|
|
38
38
|
*
|
|
39
39
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -363,7 +363,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
363
363
|
}, {
|
|
364
364
|
key: "translate",
|
|
365
365
|
value: function translate(componentId, axis, value) {
|
|
366
|
-
|
|
366
|
+
var skipPathUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
367
|
+
return this.internals.translateComponent(componentId, axis, value, skipPathUpdate);
|
|
367
368
|
}
|
|
368
369
|
|
|
369
370
|
/**
|
|
@@ -1061,18 +1062,19 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1061
1062
|
return [];
|
|
1062
1063
|
}
|
|
1063
1064
|
|
|
1064
|
-
//
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1065
|
+
// Recursive search for connector IDs
|
|
1066
|
+
var _findConnectorIds = function findConnectorIds(nodes) {
|
|
1067
|
+
if (!nodes || !Array.isArray(nodes)) return;
|
|
1068
|
+
nodes.forEach(function (node) {
|
|
1069
|
+
if (node.userData && node.userData.objectType === 'connector' && node.uuid) {
|
|
1070
|
+
allConnectorIds.push(node.uuid);
|
|
1071
|
+
}
|
|
1072
|
+
if (node.children && Array.isArray(node.children)) {
|
|
1073
|
+
_findConnectorIds(node.children);
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
};
|
|
1077
|
+
_findConnectorIds(sceneData.scene.children);
|
|
1076
1078
|
|
|
1077
1079
|
// Get existing connections
|
|
1078
1080
|
var existingConnections = this.getConnections();
|
|
@@ -1102,28 +1104,28 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1102
1104
|
* const infos = centralPlant.getAvailableConnectionsInfo()
|
|
1103
1105
|
* // [{ id: 'PUMP-1-CONNECTOR-1', flow: 'out' }, ...]
|
|
1104
1106
|
*/
|
|
1107
|
+
/**
|
|
1108
|
+
* Get all connectors in the scene that are currently available (not used in a connection).
|
|
1109
|
+
* Searches the active Three.js scene directly for the most accurate results.
|
|
1110
|
+
* @returns {Array<{id: string, flow: string}>} Array of connector info objects
|
|
1111
|
+
* @since 0.1.72 (Updated to search Three.js scene directly)
|
|
1112
|
+
*/
|
|
1105
1113
|
}, {
|
|
1106
1114
|
key: "getAvailableConnectionsInfo",
|
|
1107
1115
|
value: function getAvailableConnectionsInfo() {
|
|
1108
|
-
if (!this.sceneViewer || !this.sceneViewer.
|
|
1109
|
-
console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or
|
|
1110
|
-
return [];
|
|
1111
|
-
}
|
|
1112
|
-
var sceneData = this.sceneViewer.currentSceneData;
|
|
1113
|
-
if (!sceneData.scene || !sceneData.scene.children) {
|
|
1114
|
-
console.warn('⚠️ getAvailableConnectionsInfo(): Invalid scene data structure');
|
|
1116
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
1117
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or scene not available');
|
|
1115
1118
|
return [];
|
|
1116
1119
|
}
|
|
1117
1120
|
var allConnectorInfos = [];
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
}
|
|
1121
|
+
|
|
1122
|
+
// Search the Three.js scene directly for connectors
|
|
1123
|
+
// This is more reliable than searching currentSceneData which might be stale
|
|
1124
|
+
this.sceneViewer.scene.traverse(function (node) {
|
|
1125
|
+
if (node.userData && node.userData.objectType === 'connector' && node.uuid) {
|
|
1126
|
+
allConnectorInfos.push({
|
|
1127
|
+
id: node.uuid,
|
|
1128
|
+
flow: node.userData.flow || 'bi'
|
|
1127
1129
|
});
|
|
1128
1130
|
}
|
|
1129
1131
|
});
|
|
@@ -1145,30 +1147,29 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
1145
1147
|
* const result = centralPlant.validateConnections()
|
|
1146
1148
|
* result.invalid.forEach(({ connection, reason }) => console.warn(reason, connection))
|
|
1147
1149
|
*/
|
|
1150
|
+
/**
|
|
1151
|
+
* Validate all connections in the current scene for flow direction compatibility.
|
|
1152
|
+
* Searches the active Three.js scene for connector flow markers.
|
|
1153
|
+
* @returns {{ valid: Array<Object>, invalid: Array<{connection: Object, reason: string}> }}
|
|
1154
|
+
* @since 0.1.72 (Updated to search Three.js scene directly)
|
|
1155
|
+
*/
|
|
1148
1156
|
}, {
|
|
1149
1157
|
key: "validateConnections",
|
|
1150
1158
|
value: function validateConnections() {
|
|
1151
|
-
if (!this.sceneViewer || !this.sceneViewer.
|
|
1152
|
-
console.warn('⚠️ validateConnections(): Scene viewer or
|
|
1159
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
1160
|
+
console.warn('⚠️ validateConnections(): Scene viewer or scene not available');
|
|
1153
1161
|
return {
|
|
1154
1162
|
valid: [],
|
|
1155
1163
|
invalid: []
|
|
1156
1164
|
};
|
|
1157
1165
|
}
|
|
1158
1166
|
var connections = this.getConnections();
|
|
1159
|
-
var sceneData = this.sceneViewer.currentSceneData;
|
|
1160
1167
|
|
|
1161
|
-
// Build lookup map: connectorId → flow
|
|
1168
|
+
// Build lookup map: connectorId → flow from the Three.js scene
|
|
1162
1169
|
var flowMap = {};
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
if (component.children && Array.isArray(component.children)) {
|
|
1167
|
-
component.children.forEach(function (child) {
|
|
1168
|
-
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
1169
|
-
flowMap[child.uuid] = child.userData.flow || 'bi';
|
|
1170
|
-
}
|
|
1171
|
-
});
|
|
1170
|
+
this.sceneViewer.scene.traverse(function (node) {
|
|
1171
|
+
if (node.userData && node.userData.objectType === 'connector' && node.uuid) {
|
|
1172
|
+
flowMap[node.uuid] = node.userData.flow || 'bi';
|
|
1172
1173
|
}
|
|
1173
1174
|
});
|
|
1174
1175
|
var valid = [];
|
|
@@ -450,17 +450,19 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
450
450
|
* @param {string} componentId - The UUID of the component to translate
|
|
451
451
|
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
452
452
|
* @param {number} value - The value to translate by
|
|
453
|
+
* @param {boolean} [skipPathUpdate=false] - Whether to skip triggering pathfinding
|
|
453
454
|
* @returns {boolean} True if translation was successful, false otherwise
|
|
454
455
|
*/
|
|
455
456
|
}, {
|
|
456
457
|
key: "translateComponent",
|
|
457
458
|
value: function translateComponent(componentId, axis, value) {
|
|
458
459
|
var _this$centralPlant$ma;
|
|
460
|
+
var skipPathUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
459
461
|
if (!((_this$centralPlant$ma = this.centralPlant.managers) !== null && _this$centralPlant$ma !== void 0 && _this$centralPlant$ma.transformOperationsManager)) {
|
|
460
462
|
console.error('❌ translateComponent(): TransformOperationsManager not available');
|
|
461
463
|
return false;
|
|
462
464
|
}
|
|
463
|
-
return this.centralPlant.managers.transformOperationsManager.translateComponent(componentId, axis, value);
|
|
465
|
+
return this.centralPlant.managers.transformOperationsManager.translateComponent(componentId, axis, value, skipPathUpdate);
|
|
464
466
|
}
|
|
465
467
|
|
|
466
468
|
/**
|
|
@@ -552,7 +554,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
552
554
|
} else if (objectType === 'gateway') {
|
|
553
555
|
success = this.translateGateway(objectId, axis, value);
|
|
554
556
|
} else if (objectType === 'component') {
|
|
555
|
-
success = this.translateComponent(objectId, axis, value);
|
|
557
|
+
success = this.translateComponent(objectId, axis, value, skipPathUpdate);
|
|
556
558
|
} else {
|
|
557
559
|
result.errors.push("Unknown object type: ".concat(objectType, " (").concat(objectId, ")"));
|
|
558
560
|
console.warn("\u26A0\uFE0F Unknown object type: ".concat(objectType, " for ").concat(objectId));
|
|
@@ -98,7 +98,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
98
98
|
this.centralPlant.attachToComponent();
|
|
99
99
|
|
|
100
100
|
// Sync our managers tracking object after attachment
|
|
101
|
-
managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'pathFlowManager', 'ioBehaviorManager', 'ioOutlineManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
|
|
101
|
+
managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'transformOperationsManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'pathFlowManager', 'ioBehaviorManager', 'ioOutlineManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
|
|
102
102
|
managerKeys.forEach(function (key) {
|
|
103
103
|
if (_this2[key]) {
|
|
104
104
|
_this2.managers[key] = _this2[key];
|