@2112-lab/central-plant 0.3.46 → 0.3.48
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 +624 -425
- package/dist/cjs/src/core/centralPlant.js +46 -46
- package/dist/cjs/src/core/centralPlantInternals.js +4 -2
- package/dist/cjs/src/core/sceneViewer.js +1 -2
- package/dist/cjs/src/managers/behaviors/IoBehaviorManager.js +1 -2
- package/dist/cjs/src/managers/components/componentDataManager.js +0 -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/componentDragManager.js +2 -7
- package/dist/cjs/src/managers/controls/transformControlsManager.js +83 -44
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +274 -192
- package/dist/cjs/src/managers/scene/collisionManager.js +1 -2
- package/dist/cjs/src/managers/scene/componentTooltipManager.js +2 -3
- package/dist/cjs/src/managers/scene/modelManager.js +33 -10
- package/dist/cjs/src/managers/scene/sceneExportManager.js +42 -12
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +26 -1
- package/dist/cjs/src/utils/behaviorDispatch.js +11 -42
- package/dist/cjs/src/utils/boundingBoxUtils.js +79 -36
- package/dist/cjs/src/utils/ioDeviceUtils.js +3 -9
- package/dist/esm/src/core/centralPlant.js +46 -46
- package/dist/esm/src/core/centralPlantInternals.js +4 -2
- package/dist/esm/src/core/sceneViewer.js +1 -2
- package/dist/esm/src/managers/behaviors/IoBehaviorManager.js +1 -2
- package/dist/esm/src/managers/components/componentDataManager.js +0 -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/componentDragManager.js +2 -7
- package/dist/esm/src/managers/controls/transformControlsManager.js +83 -44
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +276 -194
- package/dist/esm/src/managers/scene/collisionManager.js +1 -2
- package/dist/esm/src/managers/scene/componentTooltipManager.js +2 -3
- package/dist/esm/src/managers/scene/modelManager.js +33 -10
- package/dist/esm/src/managers/scene/sceneExportManager.js +41 -13
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +26 -1
- package/dist/esm/src/utils/behaviorDispatch.js +11 -42
- package/dist/esm/src/utils/boundingBoxUtils.js +80 -38
- package/dist/esm/src/utils/ioDeviceUtils.js +3 -9
- package/dist/index.d.ts +0 -6
- package/package.json +1 -1
|
@@ -482,8 +482,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
482
482
|
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'io-device') {
|
|
483
483
|
var attachmentId = child.userData.attachmentId || '';
|
|
484
484
|
|
|
485
|
-
// Use
|
|
486
|
-
// The static ioConfig.states[] snapshot on userData is intentionally ignored.
|
|
485
|
+
// Use data points from the animate window (behaviorConfig).
|
|
487
486
|
var dataPoints = behaviorDispatch.resolveDataPoints(parentUuid, attachmentId, child.userData, behaviorDispatch.getIoBehaviorManager(_this3.sceneViewer));
|
|
488
487
|
|
|
489
488
|
// When data points come from behaviorConfig they already carry direction:'input'.
|
|
@@ -696,7 +695,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
696
695
|
* Input / bidirectional → shows an interactive control.
|
|
697
696
|
*
|
|
698
697
|
* @param {string} scopedAttachmentId - Scoped attachment ID (parentUuid::attachmentId) for state isolation
|
|
699
|
-
* @param {Object} dp - data point definition
|
|
698
|
+
* @param {Object} dp - data point definition
|
|
700
699
|
* @param {string} [deviceDirection] - device-level direction ('input'|'output'), overrides dp.direction
|
|
701
700
|
* @param {string} [originalAttachmentId] - Original attachment ID for behavior triggering
|
|
702
701
|
* @returns {HTMLElement}
|
|
@@ -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
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
-
require('three');
|
|
6
|
+
var THREE = require('three');
|
|
7
7
|
var GLTFExporter = require('../../../node_modules/three/examples/jsm/exporters/GLTFExporter.js');
|
|
8
8
|
var nameUtils = require('../../utils/nameUtils.js');
|
|
9
9
|
|
|
@@ -25,6 +25,8 @@ function _interopNamespace(e) {
|
|
|
25
25
|
return Object.freeze(n);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
29
|
+
|
|
28
30
|
var SceneExportManager = /*#__PURE__*/function () {
|
|
29
31
|
function SceneExportManager(sceneViewer) {
|
|
30
32
|
_rollupPluginBabelHelpers.classCallCheck(this, SceneExportManager);
|
|
@@ -103,6 +105,11 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
103
105
|
// Helper function to convert Three.js object to minimal JSON format
|
|
104
106
|
var convertObjectToJson = function convertObjectToJson(threeObject) {
|
|
105
107
|
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;
|
|
108
|
+
// Ensure world matrices are updated for this subtree before exporting
|
|
109
|
+
if (threeObject.updateMatrixWorld) {
|
|
110
|
+
threeObject.updateMatrixWorld(true);
|
|
111
|
+
}
|
|
112
|
+
|
|
106
113
|
// Skip certain objects that shouldn't be exported
|
|
107
114
|
if (!threeObject || (_threeObject$name = threeObject.name) !== null && _threeObject$name !== void 0 && _threeObject$name.includes('Polyline') ||
|
|
108
115
|
// Skip pipe paths
|
|
@@ -241,11 +248,11 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
241
248
|
};
|
|
242
249
|
}
|
|
243
250
|
|
|
244
|
-
// For components:
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
// and would leave the pathfinder with connectors in incompatible local-position format.
|
|
251
|
+
// For components: only export child connectors if they were manually added/defined.
|
|
252
|
+
// Most connectors are injected from dictionary at import time, but some (like manually placed ones)
|
|
253
|
+
// need to be persisted to maintain connections in the exported scene.
|
|
248
254
|
if (threeObject.children && threeObject.children.length > 0) {
|
|
255
|
+
var _threeObject$userData11;
|
|
249
256
|
var exportableChildren = [];
|
|
250
257
|
if (isManualSegment) {
|
|
251
258
|
// For manual segments, export their connector children
|
|
@@ -259,6 +266,29 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
259
266
|
}
|
|
260
267
|
}
|
|
261
268
|
});
|
|
269
|
+
} else if (((_threeObject$userData11 = threeObject.userData) === null || _threeObject$userData11 === void 0 ? void 0 : _threeObject$userData11.objectType) === 'component') {
|
|
270
|
+
// For components, export all connectors (including deep children within GLFs)
|
|
271
|
+
threeObject.traverse(function (child) {
|
|
272
|
+
var _child$userData2;
|
|
273
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'connector') {
|
|
274
|
+
// Calculate position relative to component root
|
|
275
|
+
var componentMatrixWorldInverse = threeObject.matrixWorld.clone().invert();
|
|
276
|
+
var childWorldPos = new THREE__namespace.Vector3();
|
|
277
|
+
child.getWorldPosition(childWorldPos);
|
|
278
|
+
var relativePos = childWorldPos.applyMatrix4(componentMatrixWorldInverse);
|
|
279
|
+
exportableChildren.push({
|
|
280
|
+
uuid: child.uuid,
|
|
281
|
+
name: child.name,
|
|
282
|
+
type: 'Mesh',
|
|
283
|
+
position: {
|
|
284
|
+
x: roundIfClose(relativePos.x),
|
|
285
|
+
y: roundIfClose(relativePos.y),
|
|
286
|
+
z: roundIfClose(relativePos.z)
|
|
287
|
+
},
|
|
288
|
+
userData: _rollupPluginBabelHelpers.objectSpread2({}, child.userData)
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
});
|
|
262
292
|
}
|
|
263
293
|
if (exportableChildren.length > 0) {
|
|
264
294
|
jsonObject.children = exportableChildren;
|
|
@@ -273,9 +303,9 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
273
303
|
// Extract main scene objects (components and standalone connectors)
|
|
274
304
|
var sceneChildren = [];
|
|
275
305
|
this.sceneViewer.scene.children.forEach(function (child) {
|
|
276
|
-
var _child$
|
|
306
|
+
var _child$userData3;
|
|
277
307
|
// Only export components and connectors; skip segments, gateways, polylines, etc.
|
|
278
|
-
var objectType = (_child$
|
|
308
|
+
var objectType = (_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType;
|
|
279
309
|
if (objectType !== 'component' && objectType !== 'connector') {
|
|
280
310
|
return;
|
|
281
311
|
}
|
|
@@ -439,14 +469,14 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
439
469
|
BufferGeometryUtils = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
|
|
440
470
|
exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
|
|
441
471
|
shouldExport = function shouldExport(child) {
|
|
442
|
-
var _child$name, _child$
|
|
472
|
+
var _child$name, _child$userData4, _child$userData5, _child$userData6, _child$userData7;
|
|
443
473
|
if ((_child$name = child.name) !== null && _child$name !== void 0 && _child$name.includes('Polyline')) return false; // Will handle separately
|
|
444
474
|
if (child.name === 'fogPlane') return false; // Skip fog plane
|
|
445
|
-
if ((_child$
|
|
446
|
-
if ((_child$
|
|
447
|
-
if ((_child$
|
|
475
|
+
if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBrickWall) return false; // Skip environment
|
|
476
|
+
if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGround) return false; // Skip environment
|
|
477
|
+
if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isBaseGrid) return false; // Skip environment
|
|
448
478
|
if (child.isLight) return false; // Skip lights
|
|
449
|
-
if ((_child$
|
|
479
|
+
if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.isTransformControls) return false; // Skip transform controls
|
|
450
480
|
if (child.isTransformControls) return false; // Skip transform controls
|
|
451
481
|
if (child.type && child.type.includes('TransformControls')) return false;
|
|
452
482
|
if (child.type && child.type.includes('Helper')) return false; // Skip helpers
|
|
@@ -1344,9 +1344,34 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1344
1344
|
min: boundingBox.min.toArray(),
|
|
1345
1345
|
max: boundingBox.max.toArray()
|
|
1346
1346
|
}
|
|
1347
|
-
})
|
|
1347
|
+
}),
|
|
1348
|
+
children: [] // Initialize children array
|
|
1348
1349
|
};
|
|
1349
1350
|
|
|
1351
|
+
// Collect children that are connectors (using traverse to find deep children in models)
|
|
1352
|
+
componentModel.traverse(function (child) {
|
|
1353
|
+
if (child.userData && child.userData.objectType === 'connector') {
|
|
1354
|
+
// Calculate position relative to component root
|
|
1355
|
+
// This ensures that when we re-add it as a direct child of the component,
|
|
1356
|
+
// it maintains the same world position relative to the component.
|
|
1357
|
+
var componentMatrixWorldInverse = componentModel.matrixWorld.clone().invert();
|
|
1358
|
+
var childWorldPos = new THREE__namespace.Vector3();
|
|
1359
|
+
child.getWorldPosition(childWorldPos);
|
|
1360
|
+
var relativePos = childWorldPos.applyMatrix4(componentMatrixWorldInverse);
|
|
1361
|
+
componentSceneData.children.push({
|
|
1362
|
+
uuid: child.uuid,
|
|
1363
|
+
name: child.name,
|
|
1364
|
+
type: 'Mesh',
|
|
1365
|
+
position: {
|
|
1366
|
+
x: relativePos.x,
|
|
1367
|
+
y: relativePos.y,
|
|
1368
|
+
z: relativePos.z
|
|
1369
|
+
},
|
|
1370
|
+
userData: _rollupPluginBabelHelpers.objectSpread2({}, child.userData)
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1374
|
+
|
|
1350
1375
|
// Add the component to the scene data
|
|
1351
1376
|
if (!currentSceneData.scene.children) {
|
|
1352
1377
|
currentSceneData.scene.children = [];
|
|
@@ -30,11 +30,11 @@ function getIoBehaviorManager(sceneViewer) {
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Resolve tooltip/drag data points for an I/O device attachment.
|
|
33
|
-
* Prefers behaviorConfig-driven animation data points
|
|
33
|
+
* Prefers behaviorConfig-driven animation data points.
|
|
34
34
|
*
|
|
35
35
|
* @param {string} parentUuid
|
|
36
36
|
* @param {string} attachmentId
|
|
37
|
-
* @param {Object} userData - io-device userData
|
|
37
|
+
* @param {Object} userData - io-device userData
|
|
38
38
|
* @param {import('../managers/behaviors/IoBehaviorManager.js').IoBehaviorManager|null} ioBehaviorManager
|
|
39
39
|
* @param {THREE.Object3D|null} [hitMesh]
|
|
40
40
|
* @returns {Object[]}
|
|
@@ -42,21 +42,7 @@ function getIoBehaviorManager(sceneViewer) {
|
|
|
42
42
|
function resolveDataPoints(parentUuid, attachmentId, userData, ioBehaviorManager) {
|
|
43
43
|
var hitMesh = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
|
|
44
44
|
var fromAnimations = (ioBehaviorManager === null || ioBehaviorManager === void 0 ? void 0 : ioBehaviorManager.getAnimationDataPoints(parentUuid, attachmentId, hitMesh)) || [];
|
|
45
|
-
|
|
46
|
-
var legacy = (userData === null || userData === void 0 ? void 0 : userData.dataPoints) || [];
|
|
47
|
-
return legacy.map(function (dp) {
|
|
48
|
-
var _dp$defaultValue;
|
|
49
|
-
return {
|
|
50
|
-
id: dp.id || dp.name,
|
|
51
|
-
name: dp.name || dp.id,
|
|
52
|
-
stateType: dp.stateType || 'binary',
|
|
53
|
-
stateConfig: dp.stateConfig || {},
|
|
54
|
-
defaultValue: (_dp$defaultValue = dp.defaultValue) !== null && _dp$defaultValue !== void 0 ? _dp$defaultValue : null,
|
|
55
|
-
direction: dp.direction || (userData === null || userData === void 0 ? void 0 : userData.ioDirection) || 'output'
|
|
56
|
-
};
|
|
57
|
-
}).filter(function (dp) {
|
|
58
|
-
return dp.id;
|
|
59
|
-
});
|
|
45
|
+
return fromAnimations;
|
|
60
46
|
}
|
|
61
47
|
|
|
62
48
|
/**
|
|
@@ -87,35 +73,18 @@ function applyDefaultIoDeviceStates(centralPlant) {
|
|
|
87
73
|
if (seen.has(scopedKey)) return;
|
|
88
74
|
seen.add(scopedKey);
|
|
89
75
|
var dps = ioBehavMgr.getAnimationDataPoints(objParentUuid, objAttachmentId) || [];
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
_step;
|
|
93
|
-
try {
|
|
94
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
95
|
-
var dp = _step.value;
|
|
96
|
-
if (!(dp !== null && dp !== void 0 && dp.id) || dp.defaultValue === undefined || dp.defaultValue === null) continue;
|
|
97
|
-
centralPlant.setIoDeviceState(objAttachmentId, dp.id, dp.defaultValue, objParentUuid);
|
|
98
|
-
}
|
|
99
|
-
} catch (err) {
|
|
100
|
-
_iterator.e(err);
|
|
101
|
-
} finally {
|
|
102
|
-
_iterator.f();
|
|
103
|
-
}
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
var _iterator2 = _rollupPluginBabelHelpers.createForOfIteratorHelper(obj.userData.dataPoints || []),
|
|
107
|
-
_step2;
|
|
76
|
+
var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(dps),
|
|
77
|
+
_step;
|
|
108
78
|
try {
|
|
109
|
-
for (
|
|
110
|
-
var
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
centralPlant.setIoDeviceState(objAttachmentId, dpId, _dp.defaultValue, objParentUuid);
|
|
79
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
80
|
+
var dp = _step.value;
|
|
81
|
+
if (!(dp !== null && dp !== void 0 && dp.id) || dp.defaultValue === undefined || dp.defaultValue === null) continue;
|
|
82
|
+
centralPlant.setIoDeviceState(objAttachmentId, dp.id, dp.defaultValue, objParentUuid);
|
|
114
83
|
}
|
|
115
84
|
} catch (err) {
|
|
116
|
-
|
|
85
|
+
_iterator.e(err);
|
|
117
86
|
} finally {
|
|
118
|
-
|
|
87
|
+
_iterator.f();
|
|
119
88
|
}
|
|
120
89
|
});
|
|
121
90
|
}
|
|
@@ -179,35 +179,77 @@ 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
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
});
|
|
206
|
+
return results;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Computes individual world-space bounding boxes for each connector child
|
|
211
|
+
* of a component. Supports deep children (e.g. within GLB model hierarchy).
|
|
212
|
+
*
|
|
213
|
+
* @param {THREE.Object3D} componentObject - The component's Three.js object
|
|
214
|
+
* @returns {Array<{uuid: string, userData: Object, worldBoundingBox: {min: number[], max: number[]}}>}
|
|
215
|
+
* Array of connector bounding box descriptors ready for injection into scene data
|
|
216
|
+
*/
|
|
217
|
+
function computeConnectorBoundingBoxes(componentObject) {
|
|
218
|
+
var results = [];
|
|
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);
|
|
225
|
+
|
|
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));
|
|
238
|
+
}
|
|
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
|
+
});
|
|
211
253
|
return results;
|
|
212
254
|
}
|
|
213
255
|
|
|
@@ -269,8 +311,8 @@ function createSelectionBoxHelpers(object) {
|
|
|
269
311
|
|
|
270
312
|
// Check if this object has io-device children (smart component)
|
|
271
313
|
var hasIODevices = (_object$children = object.children) === null || _object$children === void 0 ? void 0 : _object$children.some(function (child) {
|
|
272
|
-
var _child$
|
|
273
|
-
return ((_child$
|
|
314
|
+
var _child$userData3;
|
|
315
|
+
return ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'io-device';
|
|
274
316
|
});
|
|
275
317
|
if (hasIODevices) {
|
|
276
318
|
// 1. Create filtered helper for the component body
|
|
@@ -307,11 +349,11 @@ function createSelectionBoxHelpers(object) {
|
|
|
307
349
|
* @param {THREE.Scene} scene - The scene (for finding objects by uuid)
|
|
308
350
|
*/
|
|
309
351
|
function updateSelectionBoxHelpers(helpers, selectedObjects, scene) {
|
|
310
|
-
var
|
|
311
|
-
|
|
352
|
+
var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(helpers),
|
|
353
|
+
_step;
|
|
312
354
|
try {
|
|
313
355
|
var _loop = function _loop() {
|
|
314
|
-
var helper =
|
|
356
|
+
var helper = _step.value;
|
|
315
357
|
var _helper$userData = helper.userData,
|
|
316
358
|
sourceObjectUuid = _helper$userData.sourceObjectUuid,
|
|
317
359
|
isFiltered = _helper$userData.isFiltered,
|
|
@@ -342,16 +384,17 @@ function updateSelectionBoxHelpers(helpers, selectedObjects, scene) {
|
|
|
342
384
|
helper.update();
|
|
343
385
|
}
|
|
344
386
|
};
|
|
345
|
-
for (
|
|
387
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
346
388
|
if (_loop()) continue;
|
|
347
389
|
}
|
|
348
390
|
} catch (err) {
|
|
349
|
-
|
|
391
|
+
_iterator.e(err);
|
|
350
392
|
} finally {
|
|
351
|
-
|
|
393
|
+
_iterator.f();
|
|
352
394
|
}
|
|
353
395
|
}
|
|
354
396
|
|
|
397
|
+
exports.computeConnectorBoundingBoxes = computeConnectorBoundingBoxes;
|
|
355
398
|
exports.computeFilteredBoundingBox = computeFilteredBoundingBox;
|
|
356
399
|
exports.computeFilteredBoundingBoxCached = computeFilteredBoundingBoxCached;
|
|
357
400
|
exports.computeIODeviceBoundingBoxes = computeIODeviceBoundingBoxes;
|
|
@@ -27,7 +27,7 @@ function attachIODevicesToComponent(_x, _x2, _x3, _x4) {
|
|
|
27
27
|
}
|
|
28
28
|
function _attachIODevicesToComponent() {
|
|
29
29
|
_attachIODevicesToComponent = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
30
|
-
var attachedDevices, _i, _Object$entries, _Object$entries$_i, attachmentId, attachment, _modelPreloader$compo,
|
|
30
|
+
var attachedDevices, _i, _Object$entries, _Object$entries$_i, attachmentId, attachment, _modelPreloader$compo, _attachment$attachmen, _attachment$attachmen2, deviceData, cachedDevice, _modelPreloader$loadi, deviceModel, pos, rot, deg2rad, _t, _t2;
|
|
31
31
|
return _rollupPluginBabelHelpers.regenerator().w(function (_context) {
|
|
32
32
|
while (1) switch (_context.n) {
|
|
33
33
|
case 0:
|
|
@@ -105,20 +105,14 @@ function _attachIODevicesToComponent() {
|
|
|
105
105
|
// Name the device model
|
|
106
106
|
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
107
107
|
|
|
108
|
-
// Set user data for identification
|
|
109
|
-
// component tooltip can render state displays without an extra lookup.
|
|
108
|
+
// Set user data for identification
|
|
110
109
|
deviceModel.userData = {
|
|
111
110
|
objectType: 'io-device',
|
|
112
111
|
deviceId: attachment.deviceId,
|
|
113
112
|
attachmentId: attachmentId,
|
|
114
113
|
attachmentLabel: attachment.attachmentLabel,
|
|
115
114
|
parentComponentId: parentComponentId,
|
|
116
|
-
deviceName: deviceData.name || ''
|
|
117
|
-
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
118
|
-
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
119
|
-
dataPoints: ((_deviceData$ioConfig = deviceData.ioConfig) === null || _deviceData$ioConfig === void 0 ? void 0 : _deviceData$ioConfig.states) || ((_deviceData$ioConfig2 = deviceData.ioConfig) === null || _deviceData$ioConfig2 === void 0 ? void 0 : _deviceData$ioConfig2.dataPoints) || [],
|
|
120
|
-
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
121
|
-
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output'
|
|
115
|
+
deviceName: deviceData.name || ''
|
|
122
116
|
};
|
|
123
117
|
|
|
124
118
|
// Position at the attachment point
|