@2112-lab/central-plant 0.1.77 → 0.1.78
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 +438 -43
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/controls/transformControlsManager.js +22 -30
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +52 -8
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +41 -4
- package/dist/cjs/src/utils/boundingBoxUtils.js +356 -0
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/managers/controls/transformControlsManager.js +22 -30
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +52 -8
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +41 -4
- package/dist/esm/src/utils/boundingBoxUtils.js +329 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import * as THREE from 'three';
|
|
|
3
3
|
import { loadTextureSet } from '../environment/textureConfig.js';
|
|
4
4
|
import { ModelManager } from './modelManager.js';
|
|
5
5
|
import { SceneClearingUtility } from '../../utils/sceneClearingUtility.js';
|
|
6
|
+
import { computeFilteredBoundingBox, computeIODeviceBoundingBoxes } from '../../utils/boundingBoxUtils.js';
|
|
6
7
|
|
|
7
8
|
var _excluded = ["direction"],
|
|
8
9
|
_excluded2 = ["direction"];
|
|
@@ -618,6 +619,8 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
618
619
|
|
|
619
620
|
/**
|
|
620
621
|
* Helper function to compute world bounding boxes
|
|
622
|
+
* For components: uses filtered bbox (excludes io-device and connector subtrees)
|
|
623
|
+
* For io-devices: computes separate bounding boxes and injects them as children
|
|
621
624
|
*/
|
|
622
625
|
}, {
|
|
623
626
|
key: "computeWorldBoundingBoxes",
|
|
@@ -656,12 +659,46 @@ var SceneOperationsManager = /*#__PURE__*/function () {
|
|
|
656
659
|
};
|
|
657
660
|
jsonObject = _findJsonObject(data.scene.children);
|
|
658
661
|
if (jsonObject) {
|
|
659
|
-
// Compute world bounding box
|
|
660
|
-
var boundingBox = new THREE.Box3().setFromObject(object);
|
|
661
|
-
|
|
662
662
|
// Store in JSON userData for pathfinder (skip for gateways - they're just routing points)
|
|
663
663
|
if (!jsonObject.userData) jsonObject.userData = {};
|
|
664
|
-
if (jsonObject.userData.objectType
|
|
664
|
+
if (jsonObject.userData.objectType === 'component') {
|
|
665
|
+
// For components: compute filtered bounding box (excludes io-device and connector subtrees)
|
|
666
|
+
var filteredBBox = computeFilteredBoundingBox(object, ['io-device', 'connector']);
|
|
667
|
+
jsonObject.userData.worldBoundingBox = {
|
|
668
|
+
min: filteredBBox.min.toArray(),
|
|
669
|
+
max: filteredBBox.max.toArray()
|
|
670
|
+
};
|
|
671
|
+
console.log("Added filtered world bounding box for component:", jsonObject.userData.worldBoundingBox);
|
|
672
|
+
|
|
673
|
+
// Compute and inject separate io-device bounding boxes as children
|
|
674
|
+
var ioDeviceBBoxes = computeIODeviceBoundingBoxes(object);
|
|
675
|
+
if (ioDeviceBBoxes.length > 0) {
|
|
676
|
+
if (!jsonObject.children) jsonObject.children = [];
|
|
677
|
+
ioDeviceBBoxes.forEach(function (deviceBBox) {
|
|
678
|
+
var existingIndex = jsonObject.children.findIndex(function (c) {
|
|
679
|
+
return c.uuid === deviceBBox.uuid;
|
|
680
|
+
});
|
|
681
|
+
if (existingIndex >= 0) {
|
|
682
|
+
// Update existing entry
|
|
683
|
+
if (!jsonObject.children[existingIndex].userData) jsonObject.children[existingIndex].userData = {};
|
|
684
|
+
jsonObject.children[existingIndex].userData.objectType = 'io-device';
|
|
685
|
+
jsonObject.children[existingIndex].userData.worldBoundingBox = deviceBBox.worldBoundingBox;
|
|
686
|
+
} else {
|
|
687
|
+
// Create new entry
|
|
688
|
+
jsonObject.children.push({
|
|
689
|
+
uuid: deviceBBox.uuid,
|
|
690
|
+
userData: _objectSpread2(_objectSpread2({}, deviceBBox.userData), {}, {
|
|
691
|
+
worldBoundingBox: deviceBBox.worldBoundingBox
|
|
692
|
+
}),
|
|
693
|
+
children: []
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
console.log("\uD83D\uDCE6 Injected ".concat(ioDeviceBBoxes.length, " io-device bbox(es) for component ").concat(jsonObject.uuid));
|
|
698
|
+
}
|
|
699
|
+
} else if (jsonObject.userData.objectType !== 'gateway') {
|
|
700
|
+
// For non-component, non-gateway objects: standard bounding box
|
|
701
|
+
var boundingBox = new THREE.Box3().setFromObject(object);
|
|
665
702
|
jsonObject.userData.worldBoundingBox = {
|
|
666
703
|
min: boundingBox.min.toArray(),
|
|
667
704
|
max: boundingBox.max.toArray()
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { createForOfIteratorHelper as _createForOfIteratorHelper } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a wireframe box helper (LineSegments) from a Box3, visually identical
|
|
6
|
+
* to THREE.BoxHelper but driven by an explicit Box3 instead of setFromObject().
|
|
7
|
+
*
|
|
8
|
+
* @param {THREE.Box3} box3 - The bounding box to visualize
|
|
9
|
+
* @param {number} color - Line color (hex)
|
|
10
|
+
* @returns {THREE.LineSegments} A wireframe box matching BoxHelper's visual style
|
|
11
|
+
* @private
|
|
12
|
+
*/
|
|
13
|
+
function _createBoxHelperFromBox3(box3, color) {
|
|
14
|
+
var indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]);
|
|
15
|
+
var positions = new Float32Array(8 * 3);
|
|
16
|
+
var geometry = new THREE.BufferGeometry();
|
|
17
|
+
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
|
|
18
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
|
19
|
+
var helper = new THREE.LineSegments(geometry, new THREE.LineBasicMaterial({
|
|
20
|
+
color: color,
|
|
21
|
+
toneMapped: false
|
|
22
|
+
}));
|
|
23
|
+
helper.matrixAutoUpdate = false;
|
|
24
|
+
|
|
25
|
+
// Populate positions from box3
|
|
26
|
+
_updateBoxHelperPositions(helper, box3);
|
|
27
|
+
return helper;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Updates a box helper's geometry positions from a Box3.
|
|
32
|
+
* Matches the vertex layout used by THREE.BoxHelper.
|
|
33
|
+
*
|
|
34
|
+
* @param {THREE.LineSegments} helper - The wireframe helper to update
|
|
35
|
+
* @param {THREE.Box3} box3 - The bounding box
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
function _updateBoxHelperPositions(helper, box3) {
|
|
39
|
+
if (box3.isEmpty()) return;
|
|
40
|
+
var min = box3.min;
|
|
41
|
+
var max = box3.max;
|
|
42
|
+
var position = helper.geometry.attributes.position;
|
|
43
|
+
var array = position.array;
|
|
44
|
+
|
|
45
|
+
// Same vertex layout as THREE.BoxHelper
|
|
46
|
+
array[0] = max.x;
|
|
47
|
+
array[1] = max.y;
|
|
48
|
+
array[2] = max.z;
|
|
49
|
+
array[3] = min.x;
|
|
50
|
+
array[4] = max.y;
|
|
51
|
+
array[5] = max.z;
|
|
52
|
+
array[6] = min.x;
|
|
53
|
+
array[7] = min.y;
|
|
54
|
+
array[8] = max.z;
|
|
55
|
+
array[9] = max.x;
|
|
56
|
+
array[10] = min.y;
|
|
57
|
+
array[11] = max.z;
|
|
58
|
+
array[12] = max.x;
|
|
59
|
+
array[13] = max.y;
|
|
60
|
+
array[14] = min.z;
|
|
61
|
+
array[15] = min.x;
|
|
62
|
+
array[16] = max.y;
|
|
63
|
+
array[17] = min.z;
|
|
64
|
+
array[18] = min.x;
|
|
65
|
+
array[19] = min.y;
|
|
66
|
+
array[20] = min.z;
|
|
67
|
+
array[21] = max.x;
|
|
68
|
+
array[22] = min.y;
|
|
69
|
+
array[23] = min.z;
|
|
70
|
+
position.needsUpdate = true;
|
|
71
|
+
helper.geometry.computeBoundingSphere();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Computes a bounding box for a Three.js object, excluding descendant meshes
|
|
76
|
+
* that belong to subtrees rooted at objects with excluded objectTypes.
|
|
77
|
+
*
|
|
78
|
+
* This mirrors what THREE.Box3.expandByObject() does internally, but with a
|
|
79
|
+
* filter predicate that skips meshes whose ancestry (up to the root object)
|
|
80
|
+
* includes any excluded objectType.
|
|
81
|
+
*
|
|
82
|
+
* @param {THREE.Object3D} object - The root object to compute bbox for
|
|
83
|
+
* @param {string[]} excludeTypes - userData.objectType values to exclude (e.g., ['io-device', 'connector'])
|
|
84
|
+
* @returns {THREE.Box3} The filtered bounding box in world space
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* // Compute bbox for pump body only, excluding io-devices and connectors
|
|
88
|
+
* const pumpBodyBBox = computeFilteredBoundingBox(pumpModel, ['io-device', 'connector'])
|
|
89
|
+
*/
|
|
90
|
+
function computeFilteredBoundingBox(object) {
|
|
91
|
+
var excludeTypes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
92
|
+
var box = new THREE.Box3();
|
|
93
|
+
var tempBox = new THREE.Box3();
|
|
94
|
+
var hasGeometry = false;
|
|
95
|
+
|
|
96
|
+
// Build a Set for O(1) lookups
|
|
97
|
+
var excludeSet = new Set(excludeTypes);
|
|
98
|
+
object.updateWorldMatrix(false, true);
|
|
99
|
+
object.traverse(function (child) {
|
|
100
|
+
// Only process nodes with geometry (Mesh, SkinnedMesh, etc.)
|
|
101
|
+
if (!child.geometry) return;
|
|
102
|
+
|
|
103
|
+
// Walk up the ancestry from child to root object, checking for excluded types.
|
|
104
|
+
// If any ancestor (excluding the root object itself) has an excluded objectType,
|
|
105
|
+
// this mesh belongs to an excluded subtree — skip it.
|
|
106
|
+
var ancestor = child;
|
|
107
|
+
while (ancestor && ancestor !== object) {
|
|
108
|
+
var _ancestor$userData;
|
|
109
|
+
if ((_ancestor$userData = ancestor.userData) !== null && _ancestor$userData !== void 0 && _ancestor$userData.objectType && excludeSet.has(ancestor.userData.objectType)) {
|
|
110
|
+
return; // Skip — this mesh belongs to an excluded subtree
|
|
111
|
+
}
|
|
112
|
+
ancestor = ancestor.parent;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Include this mesh's geometry in the bounding box
|
|
116
|
+
child.geometry.computeBoundingBox();
|
|
117
|
+
if (child.geometry.boundingBox) {
|
|
118
|
+
tempBox.copy(child.geometry.boundingBox);
|
|
119
|
+
tempBox.applyMatrix4(child.matrixWorld);
|
|
120
|
+
if (!hasGeometry) {
|
|
121
|
+
box.copy(tempBox);
|
|
122
|
+
hasGeometry = true;
|
|
123
|
+
} else {
|
|
124
|
+
box.union(tempBox);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
if (!hasGeometry) {
|
|
129
|
+
// Fallback: return a zero-size box at the object's world position
|
|
130
|
+
var position = new THREE.Vector3();
|
|
131
|
+
object.getWorldPosition(position);
|
|
132
|
+
box.setFromCenterAndSize(position, new THREE.Vector3(0, 0, 0));
|
|
133
|
+
console.warn("[boundingBoxUtils] computeFilteredBoundingBox: No geometry found for ".concat(object.uuid, ", returning empty box"));
|
|
134
|
+
}
|
|
135
|
+
return box;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Computes individual world-space bounding boxes for each io-device child
|
|
140
|
+
* of a component. Uses standard THREE.Box3.setFromObject() on each io-device
|
|
141
|
+
* since io-devices don't have their own sub-devices that need filtering.
|
|
142
|
+
*
|
|
143
|
+
* @param {THREE.Object3D} componentObject - The component's Three.js object
|
|
144
|
+
* @returns {Array<{uuid: string, userData: Object, worldBoundingBox: {min: number[], max: number[]}}>}
|
|
145
|
+
* Array of io-device bounding box descriptors ready for injection into scene data
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* const ioDeviceBBoxes = computeIODeviceBoundingBoxes(pumpModel)
|
|
149
|
+
* // Returns: [{ uuid: 'signal-light-1', userData: {...}, worldBoundingBox: { min: [...], max: [...] } }]
|
|
150
|
+
*/
|
|
151
|
+
function computeIODeviceBoundingBoxes(componentObject) {
|
|
152
|
+
var results = [];
|
|
153
|
+
var _iterator = _createForOfIteratorHelper(componentObject.children),
|
|
154
|
+
_step;
|
|
155
|
+
try {
|
|
156
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
157
|
+
var _child$userData;
|
|
158
|
+
var child = _step.value;
|
|
159
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) !== 'io-device') continue;
|
|
160
|
+
var bbox = new THREE.Box3().setFromObject(child);
|
|
161
|
+
if (!bbox.isEmpty()) {
|
|
162
|
+
results.push({
|
|
163
|
+
uuid: child.uuid,
|
|
164
|
+
userData: {
|
|
165
|
+
objectType: 'io-device',
|
|
166
|
+
deviceId: child.userData.deviceId || null,
|
|
167
|
+
attachmentId: child.userData.attachmentId || null,
|
|
168
|
+
parentComponentId: child.userData.parentComponentId || componentObject.uuid
|
|
169
|
+
},
|
|
170
|
+
worldBoundingBox: {
|
|
171
|
+
min: [bbox.min.x, bbox.min.y, bbox.min.z],
|
|
172
|
+
max: [bbox.max.x, bbox.max.y, bbox.max.z]
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
_iterator.e(err);
|
|
179
|
+
} finally {
|
|
180
|
+
_iterator.f();
|
|
181
|
+
}
|
|
182
|
+
return results;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Creates bounding box helpers for a selected object. For smart components
|
|
187
|
+
* (components with io-device children), this produces:
|
|
188
|
+
* - One filtered helper for the component body (excluding io-devices and connectors)
|
|
189
|
+
* - One helper per io-device child
|
|
190
|
+
*
|
|
191
|
+
* For non-smart components and other objects, produces a single standard BoxHelper.
|
|
192
|
+
*
|
|
193
|
+
* Each helper is tagged with metadata in userData for update tracking:
|
|
194
|
+
* - `isBoundingBox: true`
|
|
195
|
+
* - `sourceObjectUuid: string` — the object this helper represents
|
|
196
|
+
* - `isFiltered: boolean` — whether filtered computation was used
|
|
197
|
+
* - `excludeTypes: string[]` — types excluded (for recomputation)
|
|
198
|
+
*
|
|
199
|
+
* @param {THREE.Object3D} object - The selected scene object
|
|
200
|
+
* @param {number} color - Line color (hex), default green
|
|
201
|
+
* @returns {THREE.LineSegments[]} Array of box helpers to add to the scene
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* const helpers = createSelectionBoxHelpers(pumpModel, 0x00ff00)
|
|
205
|
+
* helpers.forEach(h => scene.add(h))
|
|
206
|
+
*/
|
|
207
|
+
function createSelectionBoxHelpers(object) {
|
|
208
|
+
var _object$children;
|
|
209
|
+
var color = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0x00ff00;
|
|
210
|
+
var helpers = [];
|
|
211
|
+
var excludeTypes = ['io-device', 'connector'];
|
|
212
|
+
|
|
213
|
+
// Check if this object has io-device children (smart component)
|
|
214
|
+
var hasIODevices = (_object$children = object.children) === null || _object$children === void 0 ? void 0 : _object$children.some(function (child) {
|
|
215
|
+
var _child$userData2;
|
|
216
|
+
return ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'io-device';
|
|
217
|
+
});
|
|
218
|
+
if (hasIODevices) {
|
|
219
|
+
// 1. Create filtered helper for the component body
|
|
220
|
+
var filteredBox = computeFilteredBoundingBox(object, excludeTypes);
|
|
221
|
+
var componentHelper = _createBoxHelperFromBox3(filteredBox, color);
|
|
222
|
+
componentHelper.isHelper = true;
|
|
223
|
+
componentHelper.userData = {
|
|
224
|
+
isBoundingBox: true,
|
|
225
|
+
sourceObjectUuid: object.uuid,
|
|
226
|
+
isFiltered: true,
|
|
227
|
+
excludeTypes: excludeTypes
|
|
228
|
+
};
|
|
229
|
+
helpers.push(componentHelper);
|
|
230
|
+
|
|
231
|
+
// 2. Create individual helpers for each io-device
|
|
232
|
+
var _iterator2 = _createForOfIteratorHelper(object.children),
|
|
233
|
+
_step2;
|
|
234
|
+
try {
|
|
235
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
236
|
+
var _child$userData3;
|
|
237
|
+
var child = _step2.value;
|
|
238
|
+
if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) !== 'io-device') continue;
|
|
239
|
+
var deviceBox = new THREE.Box3().setFromObject(child);
|
|
240
|
+
if (deviceBox.isEmpty()) continue;
|
|
241
|
+
var deviceHelper = _createBoxHelperFromBox3(deviceBox, color);
|
|
242
|
+
deviceHelper.isHelper = true;
|
|
243
|
+
deviceHelper.userData = {
|
|
244
|
+
isBoundingBox: true,
|
|
245
|
+
sourceObjectUuid: child.uuid,
|
|
246
|
+
isFiltered: false,
|
|
247
|
+
isIODevice: true,
|
|
248
|
+
parentComponentUuid: object.uuid
|
|
249
|
+
};
|
|
250
|
+
helpers.push(deviceHelper);
|
|
251
|
+
}
|
|
252
|
+
} catch (err) {
|
|
253
|
+
_iterator2.e(err);
|
|
254
|
+
} finally {
|
|
255
|
+
_iterator2.f();
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
// Standard BoxHelper for non-smart objects
|
|
259
|
+
var boxHelper = new THREE.BoxHelper(object, color);
|
|
260
|
+
boxHelper.isHelper = true;
|
|
261
|
+
boxHelper.userData = {
|
|
262
|
+
isBoundingBox: true,
|
|
263
|
+
sourceObjectUuid: object.uuid,
|
|
264
|
+
isFiltered: false
|
|
265
|
+
};
|
|
266
|
+
helpers.push(boxHelper);
|
|
267
|
+
}
|
|
268
|
+
return helpers;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Updates a set of bounding box helpers to reflect current object transforms.
|
|
273
|
+
* Handles both standard BoxHelpers and filtered/io-device helpers.
|
|
274
|
+
*
|
|
275
|
+
* @param {THREE.LineSegments[]} helpers - Array of box helpers
|
|
276
|
+
* @param {THREE.Object3D[]} selectedObjects - The selected scene objects
|
|
277
|
+
* @param {THREE.Scene} scene - The scene (for finding objects by uuid)
|
|
278
|
+
*/
|
|
279
|
+
function updateSelectionBoxHelpers(helpers, selectedObjects, scene) {
|
|
280
|
+
var _iterator3 = _createForOfIteratorHelper(helpers),
|
|
281
|
+
_step3;
|
|
282
|
+
try {
|
|
283
|
+
var _loop = function _loop() {
|
|
284
|
+
var helper = _step3.value;
|
|
285
|
+
var _helper$userData = helper.userData,
|
|
286
|
+
sourceObjectUuid = _helper$userData.sourceObjectUuid,
|
|
287
|
+
isFiltered = _helper$userData.isFiltered,
|
|
288
|
+
excludeTypes = _helper$userData.excludeTypes,
|
|
289
|
+
isIODevice = _helper$userData.isIODevice,
|
|
290
|
+
parentComponentUuid = _helper$userData.parentComponentUuid;
|
|
291
|
+
var sourceObject;
|
|
292
|
+
if (isIODevice && parentComponentUuid) {
|
|
293
|
+
var _parent$children;
|
|
294
|
+
// Find the parent component first, then the io-device child
|
|
295
|
+
var parent = scene.getObjectByProperty('uuid', parentComponentUuid);
|
|
296
|
+
sourceObject = parent === null || parent === void 0 || (_parent$children = parent.children) === null || _parent$children === void 0 ? void 0 : _parent$children.find(function (c) {
|
|
297
|
+
return c.uuid === sourceObjectUuid;
|
|
298
|
+
});
|
|
299
|
+
} else {
|
|
300
|
+
sourceObject = selectedObjects.find(function (obj) {
|
|
301
|
+
return obj.uuid === sourceObjectUuid;
|
|
302
|
+
}) || scene.getObjectByProperty('uuid', sourceObjectUuid);
|
|
303
|
+
}
|
|
304
|
+
if (!sourceObject) return 1; // continue
|
|
305
|
+
sourceObject.updateMatrixWorld(true);
|
|
306
|
+
if (isFiltered && excludeTypes) {
|
|
307
|
+
// Recompute filtered bbox
|
|
308
|
+
var box = computeFilteredBoundingBox(sourceObject, excludeTypes);
|
|
309
|
+
_updateBoxHelperPositions(helper, box);
|
|
310
|
+
} else if (isIODevice) {
|
|
311
|
+
// Recompute io-device bbox
|
|
312
|
+
var _box = new THREE.Box3().setFromObject(sourceObject);
|
|
313
|
+
_updateBoxHelperPositions(helper, _box);
|
|
314
|
+
} else if (helper.update) {
|
|
315
|
+
// Standard BoxHelper — use built-in update
|
|
316
|
+
helper.update();
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
320
|
+
if (_loop()) continue;
|
|
321
|
+
}
|
|
322
|
+
} catch (err) {
|
|
323
|
+
_iterator3.e(err);
|
|
324
|
+
} finally {
|
|
325
|
+
_iterator3.f();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export { computeFilteredBoundingBox, computeIODeviceBoundingBoxes, createSelectionBoxHelpers, updateSelectionBoxHelpers };
|