@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
|
@@ -40,8 +40,7 @@ var CollisionManager = /*#__PURE__*/function () {
|
|
|
40
40
|
if (child === object || _this._isDescendantOf(object, child)) return;
|
|
41
41
|
|
|
42
42
|
// Filter by CP object types at the root level (skip internal meshes during traverse)
|
|
43
|
-
var isCPRootObject = ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'component' || ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment' || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'gateway' || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.objectType) === 'connector' || ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.
|
|
44
|
-
|
|
43
|
+
var isCPRootObject = ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'component' || ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'segment' || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'gateway' || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.objectType) === 'connector' || ((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType) === 'io-device';
|
|
45
44
|
if (isCPRootObject && !_this._shouldExclude(child, excludeTypes)) {
|
|
46
45
|
// Use cached worldBoundingBox if available, otherwise compute it (and cache it)
|
|
47
46
|
var childBBox;
|
|
@@ -458,8 +458,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
458
458
|
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'io-device') {
|
|
459
459
|
var attachmentId = child.userData.attachmentId || '';
|
|
460
460
|
|
|
461
|
-
// Use
|
|
462
|
-
// The static ioConfig.states[] snapshot on userData is intentionally ignored.
|
|
461
|
+
// Use data points from the animate window (behaviorConfig).
|
|
463
462
|
var dataPoints = resolveDataPoints(parentUuid, attachmentId, child.userData, getIoBehaviorManager(_this3.sceneViewer));
|
|
464
463
|
|
|
465
464
|
// When data points come from behaviorConfig they already carry direction:'input'.
|
|
@@ -672,7 +671,7 @@ var ComponentTooltipManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
672
671
|
* Input / bidirectional → shows an interactive control.
|
|
673
672
|
*
|
|
674
673
|
* @param {string} scopedAttachmentId - Scoped attachment ID (parentUuid::attachmentId) for state isolation
|
|
675
|
-
* @param {Object} dp - data point definition
|
|
674
|
+
* @param {Object} dp - data point definition
|
|
676
675
|
* @param {string} [deviceDirection] - device-level direction ('input'|'output'), overrides dp.direction
|
|
677
676
|
* @param {string} [originalAttachmentId] - Original attachment ID for behavior triggering
|
|
678
677
|
* @returns {HTMLElement}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createClass as _createClass, objectSpread2 as _objectSpread2, toConsumableArray as _toConsumableArray, typeof as _typeof, classCallCheck as _classCallCheck, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator, createForOfIteratorHelper as _createForOfIteratorHelper } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
|
+
import { getHardcodedUuid } from '../../utils/nameUtils.js';
|
|
3
4
|
import { attachIODevicesToComponent } from '../../utils/ioDeviceUtils.js';
|
|
4
5
|
import { registerBehaviorsForComponent } from '../../utils/behaviorRegistration.js';
|
|
5
6
|
import modelPreloader from '../../rendering/modelPreloader.js';
|
|
@@ -138,36 +139,58 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
138
139
|
* @param {THREE.Object3D} targetMesh - The mesh whose connectors to preserve
|
|
139
140
|
* @param {string} parentUuid - The UUID of the parent component
|
|
140
141
|
*/
|
|
142
|
+
/**
|
|
143
|
+
* Identifies all connector objects within a model hierarchy and prepares them
|
|
144
|
+
* to be preserved when the model is replaced or modified.
|
|
145
|
+
* Uses traverse() to find connectors at any depth in the hierarchy.
|
|
146
|
+
* @param {THREE.Object3D} targetMesh - The root of the model to search
|
|
147
|
+
* @param {string} parentUuid - The UUID of the parent component
|
|
148
|
+
* @returns {Array<THREE.Object3D>} Array of cloned and prepared connector objects
|
|
149
|
+
*/
|
|
141
150
|
}, {
|
|
142
151
|
key: "_preserveConnectorChildren",
|
|
143
152
|
value: function _preserveConnectorChildren(targetMesh, parentUuid) {
|
|
144
153
|
var _this = this;
|
|
145
154
|
var connectorChildren = [];
|
|
146
|
-
|
|
155
|
+
var connectorIndex = 0;
|
|
156
|
+
|
|
157
|
+
// Use traverse to find connectors at ANY depth in the hierarchy
|
|
158
|
+
targetMesh.traverse(function (child) {
|
|
147
159
|
var _child$userData;
|
|
148
160
|
var isConnectorGeometry = child.geometry && (child.geometry.uuid === 'CONNECTOR-GEO' || child.geometry.type === 'SphereGeometry' && child.geometry.parameters);
|
|
149
161
|
var isConnectorByName = child.name && child.name.toLowerCase().includes('connector');
|
|
150
|
-
// Also recognise connectors declared via userData (e.g. inline connectors from SAMPLE_1.json
|
|
151
|
-
// whose geometry may be a fallback BufferGeometry rather than a SphereGeometry).
|
|
152
162
|
var isConnectorByUserData = ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector';
|
|
153
163
|
if (isConnectorGeometry && isConnectorByName || isConnectorByUserData) {
|
|
164
|
+
connectorIndex++;
|
|
165
|
+
|
|
154
166
|
// Ensure userData exists and has worldBoundingBox
|
|
155
167
|
if (!child.userData) child.userData = {};
|
|
156
168
|
if (!child.userData.worldBoundingBox) {
|
|
157
169
|
child.userData.worldBoundingBox = _this._calculateWorldBoundingBox(child);
|
|
158
170
|
}
|
|
159
171
|
|
|
160
|
-
// Clone
|
|
172
|
+
// Clone the connector
|
|
161
173
|
var clonedConnector = child.clone();
|
|
162
174
|
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
var
|
|
175
|
+
// CRITICAL: Convert nested world position to root-relative position
|
|
176
|
+
// This ensures the connector stays in the same place when re-added as a direct child of targetMesh
|
|
177
|
+
var targetInverse = targetMesh.matrixWorld.clone().invert();
|
|
178
|
+
var worldPos = new THREE.Vector3();
|
|
179
|
+
child.getWorldPosition(worldPos);
|
|
180
|
+
clonedConnector.position.copy(worldPos.applyMatrix4(targetInverse));
|
|
181
|
+
|
|
182
|
+
// Get hardcoded UUID if it exists (e.g. from JSON mesh placeholder)
|
|
183
|
+
// This ensures compatibility with existing scene JSON naming conventions
|
|
184
|
+
var existingUuid = getHardcodedUuid(child);
|
|
185
|
+
|
|
186
|
+
// Generate fallback UUID only if existing one isn't already parent-prefixed
|
|
187
|
+
// Format: COMPONENT-UUID-CONNECTOR-INDEX (stable fallback)
|
|
188
|
+
var connectorUuid = existingUuid && existingUuid.includes(parentUuid) ? existingUuid : "".concat(parentUuid, "-CONNECTOR-").concat(connectorIndex);
|
|
166
189
|
clonedConnector.uuid = connectorUuid;
|
|
167
190
|
if (child.userData) {
|
|
168
191
|
clonedConnector.userData = _objectSpread2({}, child.userData);
|
|
169
192
|
|
|
170
|
-
// Deep copy critical data
|
|
193
|
+
// Deep copy critical data
|
|
171
194
|
if (child.userData.worldBoundingBox) {
|
|
172
195
|
var wbb = child.userData.worldBoundingBox;
|
|
173
196
|
clonedConnector.userData.worldBoundingBox = {
|
|
@@ -176,7 +199,6 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
176
199
|
};
|
|
177
200
|
}
|
|
178
201
|
if (child.userData.direction) {
|
|
179
|
-
// Handle both array [x,y,z] and object {x,y,z} formats
|
|
180
202
|
if (Array.isArray(child.userData.direction)) {
|
|
181
203
|
clonedConnector.userData.direction = _toConsumableArray(child.userData.direction);
|
|
182
204
|
} else if (_typeof(child.userData.direction) === 'object') {
|
|
@@ -188,11 +210,12 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
188
210
|
|
|
189
211
|
// Set originalUuid to match the actual uuid (maintains consistency)
|
|
190
212
|
clonedConnector.userData.originalUuid = connectorUuid;
|
|
191
|
-
clonedConnector.userData.objectType = child.userData.objectType ||
|
|
213
|
+
clonedConnector.userData.objectType = child.userData.objectType || 'connector';
|
|
192
214
|
}
|
|
193
215
|
connectorChildren.push(clonedConnector);
|
|
194
216
|
}
|
|
195
217
|
});
|
|
218
|
+
console.log("\uD83D\uDEE1\uFE0F Preserved ".concat(connectorChildren.length, " connector(s) for component ").concat(parentUuid));
|
|
196
219
|
return connectorChildren;
|
|
197
220
|
}
|
|
198
221
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createClass as _createClass, classCallCheck as _classCallCheck, toConsumableArray as _toConsumableArray, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
-
import 'three';
|
|
1
|
+
import { createClass as _createClass, classCallCheck as _classCallCheck, toConsumableArray as _toConsumableArray, objectSpread2 as _objectSpread2, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
3
|
import { GLTFExporter } from '../../../node_modules/three/examples/jsm/exporters/GLTFExporter.js';
|
|
4
4
|
import { getHardcodedUuid } from '../../utils/nameUtils.js';
|
|
5
5
|
|
|
@@ -81,6 +81,11 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
81
81
|
// Helper function to convert Three.js object to minimal JSON format
|
|
82
82
|
var convertObjectToJson = function convertObjectToJson(threeObject) {
|
|
83
83
|
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;
|
|
84
|
+
// Ensure world matrices are updated for this subtree before exporting
|
|
85
|
+
if (threeObject.updateMatrixWorld) {
|
|
86
|
+
threeObject.updateMatrixWorld(true);
|
|
87
|
+
}
|
|
88
|
+
|
|
84
89
|
// Skip certain objects that shouldn't be exported
|
|
85
90
|
if (!threeObject || (_threeObject$name = threeObject.name) !== null && _threeObject$name !== void 0 && _threeObject$name.includes('Polyline') ||
|
|
86
91
|
// Skip pipe paths
|
|
@@ -219,11 +224,11 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
219
224
|
};
|
|
220
225
|
}
|
|
221
226
|
|
|
222
|
-
// For components:
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
// and would leave the pathfinder with connectors in incompatible local-position format.
|
|
227
|
+
// For components: only export child connectors if they were manually added/defined.
|
|
228
|
+
// Most connectors are injected from dictionary at import time, but some (like manually placed ones)
|
|
229
|
+
// need to be persisted to maintain connections in the exported scene.
|
|
226
230
|
if (threeObject.children && threeObject.children.length > 0) {
|
|
231
|
+
var _threeObject$userData11;
|
|
227
232
|
var exportableChildren = [];
|
|
228
233
|
if (isManualSegment) {
|
|
229
234
|
// For manual segments, export their connector children
|
|
@@ -237,6 +242,29 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
237
242
|
}
|
|
238
243
|
}
|
|
239
244
|
});
|
|
245
|
+
} else if (((_threeObject$userData11 = threeObject.userData) === null || _threeObject$userData11 === void 0 ? void 0 : _threeObject$userData11.objectType) === 'component') {
|
|
246
|
+
// For components, export all connectors (including deep children within GLFs)
|
|
247
|
+
threeObject.traverse(function (child) {
|
|
248
|
+
var _child$userData2;
|
|
249
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'connector') {
|
|
250
|
+
// Calculate position relative to component root
|
|
251
|
+
var componentMatrixWorldInverse = threeObject.matrixWorld.clone().invert();
|
|
252
|
+
var childWorldPos = new THREE.Vector3();
|
|
253
|
+
child.getWorldPosition(childWorldPos);
|
|
254
|
+
var relativePos = childWorldPos.applyMatrix4(componentMatrixWorldInverse);
|
|
255
|
+
exportableChildren.push({
|
|
256
|
+
uuid: child.uuid,
|
|
257
|
+
name: child.name,
|
|
258
|
+
type: 'Mesh',
|
|
259
|
+
position: {
|
|
260
|
+
x: roundIfClose(relativePos.x),
|
|
261
|
+
y: roundIfClose(relativePos.y),
|
|
262
|
+
z: roundIfClose(relativePos.z)
|
|
263
|
+
},
|
|
264
|
+
userData: _objectSpread2({}, child.userData)
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
});
|
|
240
268
|
}
|
|
241
269
|
if (exportableChildren.length > 0) {
|
|
242
270
|
jsonObject.children = exportableChildren;
|
|
@@ -251,9 +279,9 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
251
279
|
// Extract main scene objects (components and standalone connectors)
|
|
252
280
|
var sceneChildren = [];
|
|
253
281
|
this.sceneViewer.scene.children.forEach(function (child) {
|
|
254
|
-
var _child$
|
|
282
|
+
var _child$userData3;
|
|
255
283
|
// Only export components and connectors; skip segments, gateways, polylines, etc.
|
|
256
|
-
var objectType = (_child$
|
|
284
|
+
var objectType = (_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType;
|
|
257
285
|
if (objectType !== 'component' && objectType !== 'connector') {
|
|
258
286
|
return;
|
|
259
287
|
}
|
|
@@ -417,14 +445,14 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
417
445
|
BufferGeometryUtils = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
|
|
418
446
|
exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
|
|
419
447
|
shouldExport = function shouldExport(child) {
|
|
420
|
-
var _child$name, _child$
|
|
448
|
+
var _child$name, _child$userData4, _child$userData5, _child$userData6, _child$userData7;
|
|
421
449
|
if ((_child$name = child.name) !== null && _child$name !== void 0 && _child$name.includes('Polyline')) return false; // Will handle separately
|
|
422
450
|
if (child.name === 'fogPlane') return false; // Skip fog plane
|
|
423
|
-
if ((_child$
|
|
424
|
-
if ((_child$
|
|
425
|
-
if ((_child$
|
|
451
|
+
if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBrickWall) return false; // Skip environment
|
|
452
|
+
if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGround) return false; // Skip environment
|
|
453
|
+
if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isBaseGrid) return false; // Skip environment
|
|
426
454
|
if (child.isLight) return false; // Skip lights
|
|
427
|
-
if ((_child$
|
|
455
|
+
if ((_child$userData7 = child.userData) !== null && _child$userData7 !== void 0 && _child$userData7.isTransformControls) return false; // Skip transform controls
|
|
428
456
|
if (child.isTransformControls) return false; // Skip transform controls
|
|
429
457
|
if (child.type && child.type.includes('TransformControls')) return false;
|
|
430
458
|
if (child.type && child.type.includes('Helper')) return false; // Skip helpers
|
|
@@ -1320,9 +1320,34 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
1320
1320
|
min: boundingBox.min.toArray(),
|
|
1321
1321
|
max: boundingBox.max.toArray()
|
|
1322
1322
|
}
|
|
1323
|
-
})
|
|
1323
|
+
}),
|
|
1324
|
+
children: [] // Initialize children array
|
|
1324
1325
|
};
|
|
1325
1326
|
|
|
1327
|
+
// Collect children that are connectors (using traverse to find deep children in models)
|
|
1328
|
+
componentModel.traverse(function (child) {
|
|
1329
|
+
if (child.userData && child.userData.objectType === 'connector') {
|
|
1330
|
+
// Calculate position relative to component root
|
|
1331
|
+
// This ensures that when we re-add it as a direct child of the component,
|
|
1332
|
+
// it maintains the same world position relative to the component.
|
|
1333
|
+
var componentMatrixWorldInverse = componentModel.matrixWorld.clone().invert();
|
|
1334
|
+
var childWorldPos = new THREE.Vector3();
|
|
1335
|
+
child.getWorldPosition(childWorldPos);
|
|
1336
|
+
var relativePos = childWorldPos.applyMatrix4(componentMatrixWorldInverse);
|
|
1337
|
+
componentSceneData.children.push({
|
|
1338
|
+
uuid: child.uuid,
|
|
1339
|
+
name: child.name,
|
|
1340
|
+
type: 'Mesh',
|
|
1341
|
+
position: {
|
|
1342
|
+
x: relativePos.x,
|
|
1343
|
+
y: relativePos.y,
|
|
1344
|
+
z: relativePos.z
|
|
1345
|
+
},
|
|
1346
|
+
userData: _objectSpread2({}, child.userData)
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1350
|
+
|
|
1326
1351
|
// Add the component to the scene data
|
|
1327
1352
|
if (!currentSceneData.scene.children) {
|
|
1328
1353
|
currentSceneData.scene.children = [];
|
|
@@ -26,11 +26,11 @@ function getIoBehaviorManager(sceneViewer) {
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Resolve tooltip/drag data points for an I/O device attachment.
|
|
29
|
-
* Prefers behaviorConfig-driven animation data points
|
|
29
|
+
* Prefers behaviorConfig-driven animation data points.
|
|
30
30
|
*
|
|
31
31
|
* @param {string} parentUuid
|
|
32
32
|
* @param {string} attachmentId
|
|
33
|
-
* @param {Object} userData - io-device userData
|
|
33
|
+
* @param {Object} userData - io-device userData
|
|
34
34
|
* @param {import('../managers/behaviors/IoBehaviorManager.js').IoBehaviorManager|null} ioBehaviorManager
|
|
35
35
|
* @param {THREE.Object3D|null} [hitMesh]
|
|
36
36
|
* @returns {Object[]}
|
|
@@ -38,21 +38,7 @@ function getIoBehaviorManager(sceneViewer) {
|
|
|
38
38
|
function resolveDataPoints(parentUuid, attachmentId, userData, ioBehaviorManager) {
|
|
39
39
|
var hitMesh = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
|
|
40
40
|
var fromAnimations = (ioBehaviorManager === null || ioBehaviorManager === void 0 ? void 0 : ioBehaviorManager.getAnimationDataPoints(parentUuid, attachmentId, hitMesh)) || [];
|
|
41
|
-
|
|
42
|
-
var legacy = (userData === null || userData === void 0 ? void 0 : userData.dataPoints) || [];
|
|
43
|
-
return legacy.map(function (dp) {
|
|
44
|
-
var _dp$defaultValue;
|
|
45
|
-
return {
|
|
46
|
-
id: dp.id || dp.name,
|
|
47
|
-
name: dp.name || dp.id,
|
|
48
|
-
stateType: dp.stateType || 'binary',
|
|
49
|
-
stateConfig: dp.stateConfig || {},
|
|
50
|
-
defaultValue: (_dp$defaultValue = dp.defaultValue) !== null && _dp$defaultValue !== void 0 ? _dp$defaultValue : null,
|
|
51
|
-
direction: dp.direction || (userData === null || userData === void 0 ? void 0 : userData.ioDirection) || 'output'
|
|
52
|
-
};
|
|
53
|
-
}).filter(function (dp) {
|
|
54
|
-
return dp.id;
|
|
55
|
-
});
|
|
41
|
+
return fromAnimations;
|
|
56
42
|
}
|
|
57
43
|
|
|
58
44
|
/**
|
|
@@ -83,35 +69,18 @@ function applyDefaultIoDeviceStates(centralPlant) {
|
|
|
83
69
|
if (seen.has(scopedKey)) return;
|
|
84
70
|
seen.add(scopedKey);
|
|
85
71
|
var dps = ioBehavMgr.getAnimationDataPoints(objParentUuid, objAttachmentId) || [];
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
_step;
|
|
89
|
-
try {
|
|
90
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
91
|
-
var dp = _step.value;
|
|
92
|
-
if (!(dp !== null && dp !== void 0 && dp.id) || dp.defaultValue === undefined || dp.defaultValue === null) continue;
|
|
93
|
-
centralPlant.setIoDeviceState(objAttachmentId, dp.id, dp.defaultValue, objParentUuid);
|
|
94
|
-
}
|
|
95
|
-
} catch (err) {
|
|
96
|
-
_iterator.e(err);
|
|
97
|
-
} finally {
|
|
98
|
-
_iterator.f();
|
|
99
|
-
}
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
var _iterator2 = _createForOfIteratorHelper(obj.userData.dataPoints || []),
|
|
103
|
-
_step2;
|
|
72
|
+
var _iterator = _createForOfIteratorHelper(dps),
|
|
73
|
+
_step;
|
|
104
74
|
try {
|
|
105
|
-
for (
|
|
106
|
-
var
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
centralPlant.setIoDeviceState(objAttachmentId, dpId, _dp.defaultValue, objParentUuid);
|
|
75
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
76
|
+
var dp = _step.value;
|
|
77
|
+
if (!(dp !== null && dp !== void 0 && dp.id) || dp.defaultValue === undefined || dp.defaultValue === null) continue;
|
|
78
|
+
centralPlant.setIoDeviceState(objAttachmentId, dp.id, dp.defaultValue, objParentUuid);
|
|
110
79
|
}
|
|
111
80
|
} catch (err) {
|
|
112
|
-
|
|
81
|
+
_iterator.e(err);
|
|
113
82
|
} finally {
|
|
114
|
-
|
|
83
|
+
_iterator.f();
|
|
115
84
|
}
|
|
116
85
|
});
|
|
117
86
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createForOfIteratorHelper as _createForOfIteratorHelper, construct as _construct, toConsumableArray as _toConsumableArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
1
|
+
import { createForOfIteratorHelper as _createForOfIteratorHelper, objectSpread2 as _objectSpread2, construct as _construct, toConsumableArray as _toConsumableArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -155,35 +155,77 @@ function computeFilteredBoundingBox(object) {
|
|
|
155
155
|
*/
|
|
156
156
|
function computeIODeviceBoundingBoxes(componentObject) {
|
|
157
157
|
var results = [];
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
158
|
+
componentObject.traverse(function (child) {
|
|
159
|
+
var _child$userData;
|
|
160
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) !== 'io-device') return;
|
|
161
|
+
var bbox = new THREE.Box3().setFromObject(child);
|
|
162
|
+
var worldPos = new THREE.Vector3();
|
|
163
|
+
child.getWorldPosition(worldPos);
|
|
164
|
+
if (!bbox.isEmpty()) {
|
|
165
|
+
results.push({
|
|
166
|
+
uuid: child.uuid,
|
|
167
|
+
userData: {
|
|
168
|
+
objectType: 'io-device',
|
|
169
|
+
deviceId: child.userData.deviceId || null,
|
|
170
|
+
attachmentId: child.userData.attachmentId || null,
|
|
171
|
+
parentComponentId: child.userData.parentComponentId || componentObject.uuid,
|
|
172
|
+
// Sync position for pathfinder
|
|
173
|
+
position: [worldPos.x, worldPos.y, worldPos.z]
|
|
174
|
+
},
|
|
175
|
+
worldBoundingBox: {
|
|
176
|
+
min: [bbox.min.x, bbox.min.y, bbox.min.z],
|
|
177
|
+
max: [bbox.max.x, bbox.max.y, bbox.max.z]
|
|
178
|
+
}
|
|
179
|
+
});
|
|
181
180
|
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
181
|
+
});
|
|
182
|
+
return results;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Computes individual world-space bounding boxes for each connector child
|
|
187
|
+
* of a component. Supports deep children (e.g. within GLB model hierarchy).
|
|
188
|
+
*
|
|
189
|
+
* @param {THREE.Object3D} componentObject - The component's Three.js object
|
|
190
|
+
* @returns {Array<{uuid: string, userData: Object, worldBoundingBox: {min: number[], max: number[]}}>}
|
|
191
|
+
* Array of connector bounding box descriptors ready for injection into scene data
|
|
192
|
+
*/
|
|
193
|
+
function computeConnectorBoundingBoxes(componentObject) {
|
|
194
|
+
var results = [];
|
|
195
|
+
componentObject.traverse(function (child) {
|
|
196
|
+
var _child$userData2;
|
|
197
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) !== 'connector') return;
|
|
198
|
+
var bbox = new THREE.Box3().setFromObject(child);
|
|
199
|
+
var worldPos = new THREE.Vector3();
|
|
200
|
+
child.getWorldPosition(worldPos);
|
|
201
|
+
|
|
202
|
+
// Compute world-space direction vector (Crucial for rotation-aware pathfinding)
|
|
203
|
+
// Default to [0, 0, 1] if not specified (Standard for our coordinate system)
|
|
204
|
+
var localDirData = child.userData && Array.isArray(child.userData.direction) ? child.userData.direction : [0, 0, 1];
|
|
205
|
+
var localDir = new THREE.Vector3(localDirData[0], localDirData[1], localDirData[2]);
|
|
206
|
+
var worldQuat = new THREE.Quaternion();
|
|
207
|
+
child.getWorldQuaternion(worldQuat);
|
|
208
|
+
var worldDir = localDir.clone().applyQuaternion(worldQuat).normalize();
|
|
209
|
+
|
|
210
|
+
// Fallback if mesh is too small or empty (sometimes connectors are just points)
|
|
211
|
+
if (bbox.isEmpty() || bbox.getSize(new THREE.Vector3()).length() < 0.01) {
|
|
212
|
+
var size = 0.1;
|
|
213
|
+
bbox.setFromCenterAndSize(worldPos, new THREE.Vector3(size, size, size));
|
|
214
|
+
}
|
|
215
|
+
results.push({
|
|
216
|
+
uuid: child.uuid,
|
|
217
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
218
|
+
objectType: 'connector',
|
|
219
|
+
// Update both position AND direction for pathfinder
|
|
220
|
+
position: [worldPos.x, worldPos.y, worldPos.z],
|
|
221
|
+
direction: [worldDir.x, worldDir.y, worldDir.z]
|
|
222
|
+
}),
|
|
223
|
+
worldBoundingBox: {
|
|
224
|
+
min: [bbox.min.x, bbox.min.y, bbox.min.z],
|
|
225
|
+
max: [bbox.max.x, bbox.max.y, bbox.max.z]
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
});
|
|
187
229
|
return results;
|
|
188
230
|
}
|
|
189
231
|
|
|
@@ -245,8 +287,8 @@ function createSelectionBoxHelpers(object) {
|
|
|
245
287
|
|
|
246
288
|
// Check if this object has io-device children (smart component)
|
|
247
289
|
var hasIODevices = (_object$children = object.children) === null || _object$children === void 0 ? void 0 : _object$children.some(function (child) {
|
|
248
|
-
var _child$
|
|
249
|
-
return ((_child$
|
|
290
|
+
var _child$userData3;
|
|
291
|
+
return ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'io-device';
|
|
250
292
|
});
|
|
251
293
|
if (hasIODevices) {
|
|
252
294
|
// 1. Create filtered helper for the component body
|
|
@@ -283,11 +325,11 @@ function createSelectionBoxHelpers(object) {
|
|
|
283
325
|
* @param {THREE.Scene} scene - The scene (for finding objects by uuid)
|
|
284
326
|
*/
|
|
285
327
|
function updateSelectionBoxHelpers(helpers, selectedObjects, scene) {
|
|
286
|
-
var
|
|
287
|
-
|
|
328
|
+
var _iterator = _createForOfIteratorHelper(helpers),
|
|
329
|
+
_step;
|
|
288
330
|
try {
|
|
289
331
|
var _loop = function _loop() {
|
|
290
|
-
var helper =
|
|
332
|
+
var helper = _step.value;
|
|
291
333
|
var _helper$userData = helper.userData,
|
|
292
334
|
sourceObjectUuid = _helper$userData.sourceObjectUuid,
|
|
293
335
|
isFiltered = _helper$userData.isFiltered,
|
|
@@ -318,14 +360,14 @@ function updateSelectionBoxHelpers(helpers, selectedObjects, scene) {
|
|
|
318
360
|
helper.update();
|
|
319
361
|
}
|
|
320
362
|
};
|
|
321
|
-
for (
|
|
363
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
322
364
|
if (_loop()) continue;
|
|
323
365
|
}
|
|
324
366
|
} catch (err) {
|
|
325
|
-
|
|
367
|
+
_iterator.e(err);
|
|
326
368
|
} finally {
|
|
327
|
-
|
|
369
|
+
_iterator.f();
|
|
328
370
|
}
|
|
329
371
|
}
|
|
330
372
|
|
|
331
|
-
export { computeFilteredBoundingBox, computeFilteredBoundingBoxCached, computeIODeviceBoundingBoxes, createSelectionBoxHelpers, updateSelectionBoxHelpers };
|
|
373
|
+
export { computeConnectorBoundingBoxes, computeFilteredBoundingBox, computeFilteredBoundingBoxCached, computeIODeviceBoundingBoxes, createSelectionBoxHelpers, updateSelectionBoxHelpers };
|
|
@@ -23,7 +23,7 @@ function attachIODevicesToComponent(_x, _x2, _x3, _x4) {
|
|
|
23
23
|
}
|
|
24
24
|
function _attachIODevicesToComponent() {
|
|
25
25
|
_attachIODevicesToComponent = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(componentModel, componentData, modelPreloader, parentComponentId) {
|
|
26
|
-
var attachedDevices, _i, _Object$entries, _Object$entries$_i, attachmentId, attachment, _modelPreloader$compo,
|
|
26
|
+
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;
|
|
27
27
|
return _regenerator().w(function (_context) {
|
|
28
28
|
while (1) switch (_context.n) {
|
|
29
29
|
case 0:
|
|
@@ -101,20 +101,14 @@ function _attachIODevicesToComponent() {
|
|
|
101
101
|
// Name the device model
|
|
102
102
|
deviceModel.name = "".concat(attachment.attachmentLabel || 'IO Device', " (").concat(attachmentId, ")");
|
|
103
103
|
|
|
104
|
-
// Set user data for identification
|
|
105
|
-
// component tooltip can render state displays without an extra lookup.
|
|
104
|
+
// Set user data for identification
|
|
106
105
|
deviceModel.userData = {
|
|
107
106
|
objectType: 'io-device',
|
|
108
107
|
deviceId: attachment.deviceId,
|
|
109
108
|
attachmentId: attachmentId,
|
|
110
109
|
attachmentLabel: attachment.attachmentLabel,
|
|
111
110
|
parentComponentId: parentComponentId,
|
|
112
|
-
deviceName: deviceData.name || ''
|
|
113
|
-
// Snapshot of the device's data point definitions (stateType, stateConfig, direction, etc.)
|
|
114
|
-
// ioConfig can use either 'states' (preferred) or legacy 'dataPoints' as the array key
|
|
115
|
-
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) || [],
|
|
116
|
-
// Device-level I/O direction: 'input' means the user can write state via the tooltip
|
|
117
|
-
ioDirection: ((_deviceData$ioConfig3 = deviceData.ioConfig) === null || _deviceData$ioConfig3 === void 0 ? void 0 : _deviceData$ioConfig3.direction) || 'output'
|
|
111
|
+
deviceName: deviceData.name || ''
|
|
118
112
|
};
|
|
119
113
|
|
|
120
114
|
// Position at the attachment point
|
package/dist/index.d.ts
CHANGED
|
@@ -35,11 +35,6 @@ export interface IoDeviceState {
|
|
|
35
35
|
direction?: 'input' | 'output'
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export interface IoDeviceConfig {
|
|
39
|
-
direction: 'input' | 'output'
|
|
40
|
-
states: IoDeviceState[]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
38
|
export interface BehaviorMapping {
|
|
44
39
|
stateValue: any
|
|
45
40
|
transform?: { x?: number; y?: number; z?: number }
|
|
@@ -91,7 +86,6 @@ export interface IoDeviceAsset {
|
|
|
91
86
|
uuid: string
|
|
92
87
|
name: string
|
|
93
88
|
assetType: 'I/O Device'
|
|
94
|
-
ioConfig: IoDeviceConfig
|
|
95
89
|
behaviorConfig?: BehaviorEntry[]
|
|
96
90
|
meshNameMap?: Record<string, string>
|
|
97
91
|
}
|