@2112-lab/central-plant 0.3.2 → 0.3.5
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 +168 -178
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/scene/modelManager.js +18 -6
- package/dist/cjs/src/managers/scene/sceneExportManager.js +25 -68
- package/dist/cjs/src/managers/scene/viewport2DManager.js +128 -102
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/managers/scene/modelManager.js +18 -6
- package/dist/esm/src/managers/scene/sceneExportManager.js +25 -68
- package/dist/esm/src/managers/scene/viewport2DManager.js +127 -103
- package/package.json +1 -1
|
@@ -237,40 +237,17 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
237
237
|
};
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
// For components:
|
|
241
|
-
//
|
|
242
|
-
//
|
|
240
|
+
// For components: no children exported — connector positions are defined in the component
|
|
241
|
+
// dictionary GLB and will be re-injected at import time via _injectConnectorChildrenFromDictionary.
|
|
242
|
+
// Exporting them here would prevent that injection (it skips if children already exist)
|
|
243
|
+
// and would leave the pathfinder with connectors in incompatible local-position format.
|
|
243
244
|
if (threeObject.children && threeObject.children.length > 0) {
|
|
244
245
|
var exportableChildren = [];
|
|
245
|
-
if (
|
|
246
|
-
// Export connector children (skip mesh geometry - it lives in the component dictionary GLB)
|
|
247
|
-
threeObject.children.forEach(function (child) {
|
|
248
|
-
var _child$userData;
|
|
249
|
-
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector') {
|
|
250
|
-
var connectorJson = {
|
|
251
|
-
// Use the raw Three.js UUID — connections in currentSceneData reference this exact value
|
|
252
|
-
uuid: child.uuid,
|
|
253
|
-
userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({
|
|
254
|
-
objectType: 'connector'
|
|
255
|
-
}, child.userData.direction ? {
|
|
256
|
-
direction: child.userData.direction
|
|
257
|
-
} : {}), child.userData.group ? {
|
|
258
|
-
group: child.userData.group
|
|
259
|
-
} : {}),
|
|
260
|
-
position: {
|
|
261
|
-
x: roundIfClose(child.position.x),
|
|
262
|
-
y: roundIfClose(child.position.y),
|
|
263
|
-
z: roundIfClose(child.position.z)
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
exportableChildren.push(connectorJson);
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
} else if (isManualSegment) {
|
|
246
|
+
if (isManualSegment) {
|
|
270
247
|
// For manual segments, export their connector children
|
|
271
248
|
threeObject.children.forEach(function (child) {
|
|
272
|
-
var _child$
|
|
273
|
-
if (((_child$
|
|
249
|
+
var _child$userData;
|
|
250
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'segment-connector') {
|
|
274
251
|
// Call the class method using bound reference
|
|
275
252
|
var connectorJson = convertSegmentConnectorToJson(child, threeObject);
|
|
276
253
|
if (connectorJson) {
|
|
@@ -289,38 +266,18 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
289
266
|
// Bind the convertSegmentConnectorToJson method for use in nested function
|
|
290
267
|
var convertSegmentConnectorToJson = this.convertSegmentConnectorToJson.bind(this);
|
|
291
268
|
|
|
292
|
-
// Extract main scene objects (components and standalone connectors
|
|
269
|
+
// Extract main scene objects (components and standalone connectors)
|
|
293
270
|
var sceneChildren = [];
|
|
294
|
-
|
|
295
|
-
// Helper to recursively find manual segments within polylines
|
|
296
|
-
var findManualSegments = function findManualSegments(object) {
|
|
297
|
-
var manualSegments = [];
|
|
298
|
-
object.traverse(function (child) {
|
|
299
|
-
var _child$userData3;
|
|
300
|
-
// Check if this is a manual segment
|
|
301
|
-
if (((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.objectType) === 'segment') {
|
|
302
|
-
manualSegments.push(child);
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
return manualSegments;
|
|
306
|
-
};
|
|
307
271
|
this.sceneViewer.scene.children.forEach(function (child) {
|
|
308
|
-
var _child$
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
});
|
|
318
|
-
} else {
|
|
319
|
-
// Regular scene object export
|
|
320
|
-
var jsonChild = convertObjectToJson(child);
|
|
321
|
-
if (jsonChild) {
|
|
322
|
-
sceneChildren.push(jsonChild);
|
|
323
|
-
}
|
|
272
|
+
var _child$userData2;
|
|
273
|
+
// Only export components and connectors; skip segments, gateways, polylines, etc.
|
|
274
|
+
var objectType = (_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType;
|
|
275
|
+
if (objectType !== 'component' && objectType !== 'connector') {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
var jsonChild = convertObjectToJson(child);
|
|
279
|
+
if (jsonChild) {
|
|
280
|
+
sceneChildren.push(jsonChild);
|
|
324
281
|
}
|
|
325
282
|
});
|
|
326
283
|
|
|
@@ -498,14 +455,14 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
498
455
|
BufferGeometryUtils = BufferGeometryUtilsModule.BufferGeometryUtils || BufferGeometryUtilsModule.default || BufferGeometryUtilsModule; // Create a new scene for export instead of cloning
|
|
499
456
|
exportScene = new _THREE.Scene(); // Helper function to check if an object should be exported
|
|
500
457
|
shouldExport = function shouldExport(child) {
|
|
501
|
-
var _child$
|
|
502
|
-
if ((_child$
|
|
458
|
+
var _child$name, _child$userData3, _child$userData4, _child$userData5, _child$userData6;
|
|
459
|
+
if ((_child$name = child.name) !== null && _child$name !== void 0 && _child$name.includes('Polyline')) return false; // Will handle separately
|
|
503
460
|
if (child.name === 'fogPlane') return false; // Skip fog plane
|
|
504
|
-
if ((_child$
|
|
505
|
-
if ((_child$
|
|
506
|
-
if ((_child$
|
|
461
|
+
if ((_child$userData3 = child.userData) !== null && _child$userData3 !== void 0 && _child$userData3.isBrickWall) return false; // Skip environment
|
|
462
|
+
if ((_child$userData4 = child.userData) !== null && _child$userData4 !== void 0 && _child$userData4.isBaseGround) return false; // Skip environment
|
|
463
|
+
if ((_child$userData5 = child.userData) !== null && _child$userData5 !== void 0 && _child$userData5.isBaseGrid) return false; // Skip environment
|
|
507
464
|
if (child.isLight) return false; // Skip lights
|
|
508
|
-
if ((_child$
|
|
465
|
+
if ((_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.isTransformControls) return false; // Skip transform controls
|
|
509
466
|
if (child.isTransformControls) return false; // Skip transform controls
|
|
510
467
|
if (child.type && child.type.includes('TransformControls')) return false;
|
|
511
468
|
if (child.type && child.type.includes('Helper')) return false; // Skip helpers
|
|
@@ -514,8 +471,8 @@ var SceneExportManager = /*#__PURE__*/function () {
|
|
|
514
471
|
pipeGeometries = [];
|
|
515
472
|
pipeMaterial = null;
|
|
516
473
|
this.sceneViewer.scene.children.forEach(function (child) {
|
|
517
|
-
var _child$
|
|
518
|
-
if ((_child$
|
|
474
|
+
var _child$name2;
|
|
475
|
+
if ((_child$name2 = child.name) !== null && _child$name2 !== void 0 && _child$name2.includes('Polyline')) {
|
|
519
476
|
// Traverse the polyline to collect all mesh geometries
|
|
520
477
|
child.traverse(function (obj) {
|
|
521
478
|
if (obj.isMesh && obj.geometry) {
|
|
@@ -4,6 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
6
|
var baseDisposable = require('../../core/baseDisposable.js');
|
|
7
|
+
var THREE = require('three');
|
|
8
|
+
var boundingBoxUtils = require('../../utils/boundingBoxUtils.js');
|
|
7
9
|
|
|
8
10
|
function _interopNamespace(e) {
|
|
9
11
|
if (e && e.__esModule) return e;
|
|
@@ -23,6 +25,8 @@ function _interopNamespace(e) {
|
|
|
23
25
|
return Object.freeze(n);
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
29
|
+
|
|
26
30
|
/**
|
|
27
31
|
* Viewport2DInstance
|
|
28
32
|
* Represents a single 2D viewport with its own Konva stage and configuration
|
|
@@ -550,32 +554,20 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
550
554
|
}, {
|
|
551
555
|
key: "renderComponent",
|
|
552
556
|
value: function renderComponent(viewport, component, centerX, centerY, scale) {
|
|
553
|
-
|
|
554
|
-
// Get component position and rotation
|
|
555
|
-
var pos3D = {
|
|
556
|
-
x: (_component$position$x = (_component$position = component.position) === null || _component$position === void 0 ? void 0 : _component$position.x) !== null && _component$position$x !== void 0 ? _component$position$x : 0,
|
|
557
|
-
y: (_component$position$y = (_component$position2 = component.position) === null || _component$position2 === void 0 ? void 0 : _component$position2.y) !== null && _component$position$y !== void 0 ? _component$position$y : 0,
|
|
558
|
-
z: (_component$position$z = (_component$position3 = component.position) === null || _component$position3 === void 0 ? void 0 : _component$position3.z) !== null && _component$position$z !== void 0 ? _component$position$z : 0
|
|
559
|
-
};
|
|
560
|
-
var rot3D = {
|
|
561
|
-
x: (_component$rotation$x = (_component$rotation = component.rotation) === null || _component$rotation === void 0 ? void 0 : _component$rotation.x) !== null && _component$rotation$x !== void 0 ? _component$rotation$x : 0,
|
|
562
|
-
y: (_component$rotation$y = (_component$rotation2 = component.rotation) === null || _component$rotation2 === void 0 ? void 0 : _component$rotation2.y) !== null && _component$rotation$y !== void 0 ? _component$rotation$y : 0,
|
|
563
|
-
z: (_component$rotation$z = (_component$rotation3 = component.rotation) === null || _component$rotation3 === void 0 ? void 0 : _component$rotation3.z) !== null && _component$rotation$z !== void 0 ? _component$rotation$z : 0
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
// Get bounding box dimensions
|
|
557
|
+
// Get world-space bounding box dimensions and center
|
|
567
558
|
var _this$getComponentDim = this.getComponentDimensions(component),
|
|
568
559
|
worldWidth = _this$getComponentDim.worldWidth,
|
|
569
560
|
worldDepth = _this$getComponentDim.worldDepth,
|
|
570
|
-
worldHeight = _this$getComponentDim.worldHeight
|
|
561
|
+
worldHeight = _this$getComponentDim.worldHeight,
|
|
562
|
+
bboxCenter = _this$getComponentDim.bboxCenter;
|
|
563
|
+
console.log("[2D] ".concat(component.name, " | w=").concat(worldWidth.toFixed(3), " d=").concat(worldDepth.toFixed(3), " h=").concat(worldHeight.toFixed(3), " | center=(").concat(bboxCenter.x.toFixed(2), ",").concat(bboxCenter.y.toFixed(2), ",").concat(bboxCenter.z.toFixed(2), ")"));
|
|
571
564
|
|
|
572
|
-
// Project 3D
|
|
573
|
-
var _this$project3DTo2D = this.project3DTo2D(viewport,
|
|
565
|
+
// Project 3D bbox center to 2D based on view type
|
|
566
|
+
var _this$project3DTo2D = this.project3DTo2D(viewport, bboxCenter, worldWidth, worldDepth, worldHeight),
|
|
574
567
|
posX = _this$project3DTo2D.posX,
|
|
575
568
|
posY = _this$project3DTo2D.posY,
|
|
576
569
|
rectWidth = _this$project3DTo2D.rectWidth,
|
|
577
570
|
rectHeight = _this$project3DTo2D.rectHeight;
|
|
578
|
-
_this$project3DTo2D.rotationDegrees;
|
|
579
571
|
var screenX = centerX + posX * scale;
|
|
580
572
|
var screenY = centerY - posY * scale; // Flip Y for screen coords
|
|
581
573
|
|
|
@@ -619,105 +611,131 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
619
611
|
});
|
|
620
612
|
|
|
621
613
|
// Add mouse event handlers
|
|
622
|
-
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight);
|
|
614
|
+
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter);
|
|
623
615
|
componentGroup.add(rect);
|
|
624
616
|
componentGroup.add(label);
|
|
625
617
|
viewport.componentLayer.add(componentGroup);
|
|
626
618
|
}
|
|
627
619
|
|
|
628
620
|
/**
|
|
629
|
-
*
|
|
621
|
+
* Compute worldBoundingBox for a live Three.js Object3D using the same
|
|
622
|
+
* vertex-accurate approach as computeFilteredBoundingBox (explicitly calls
|
|
623
|
+
* geometry.computeBoundingBox() on each mesh before measuring).
|
|
624
|
+
* @param {THREE.Object3D} object
|
|
625
|
+
* @returns {{min: number[], max: number[]}}
|
|
626
|
+
*/
|
|
627
|
+
}, {
|
|
628
|
+
key: "_getOrComputeWorldBoundingBox",
|
|
629
|
+
value: function _getOrComputeWorldBoundingBox(object) {
|
|
630
|
+
// computeFilteredBoundingBox with no exclusions = full object bbox
|
|
631
|
+
var box = boundingBoxUtils.computeFilteredBoundingBox(object, []);
|
|
632
|
+
if (box.isEmpty()) {
|
|
633
|
+
// Object has no geometry; fall back to a point at world position
|
|
634
|
+
var wp = new THREE__namespace.Vector3();
|
|
635
|
+
object.getWorldPosition(wp);
|
|
636
|
+
return {
|
|
637
|
+
min: [wp.x, wp.y, wp.z],
|
|
638
|
+
max: [wp.x, wp.y, wp.z]
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
return {
|
|
642
|
+
min: [box.min.x, box.min.y, box.min.z],
|
|
643
|
+
max: [box.max.x, box.max.y, box.max.z]
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Get component dimensions and world-space center from worldBoundingBox
|
|
630
649
|
*/
|
|
631
650
|
}, {
|
|
632
651
|
key: "getComponentDimensions",
|
|
633
652
|
value: function getComponentDimensions(component) {
|
|
634
|
-
var _component$userData, _component$
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
653
|
+
var _component$userData$w, _component$userData, _component$getWorldPo;
|
|
654
|
+
// Prefer worldBoundingBox already stored on the object — set after GLB loading
|
|
655
|
+
// by modelManager.replaceWithGLBModels using computeFilteredBoundingBox.
|
|
656
|
+
// Fall back to computing live if not yet available (e.g. first render before GLB load).
|
|
657
|
+
var wbb = (_component$userData$w = (_component$userData = component.userData) === null || _component$userData === void 0 ? void 0 : _component$userData.worldBoundingBox) !== null && _component$userData$w !== void 0 ? _component$userData$w : this._getOrComputeWorldBoundingBox(component);
|
|
658
|
+
if (wbb !== null && wbb !== void 0 && wbb.min && wbb !== null && wbb !== void 0 && wbb.max) {
|
|
659
|
+
var _wbb$min = _rollupPluginBabelHelpers.slicedToArray(wbb.min, 3),
|
|
660
|
+
minX = _wbb$min[0],
|
|
661
|
+
minY = _wbb$min[1],
|
|
662
|
+
minZ = _wbb$min[2];
|
|
663
|
+
var _wbb$max = _rollupPluginBabelHelpers.slicedToArray(wbb.max, 3),
|
|
664
|
+
maxX = _wbb$max[0],
|
|
665
|
+
maxY = _wbb$max[1],
|
|
666
|
+
maxZ = _wbb$max[2];
|
|
667
|
+
var cx = (minX + maxX) / 2;
|
|
668
|
+
var cy = (minY + maxY) / 2;
|
|
669
|
+
var cz = (minZ + maxZ) / 2;
|
|
670
|
+
// Guard against Infinity/NaN from empty or degenerate boxes
|
|
671
|
+
if (isFinite(cx) && isFinite(cy) && isFinite(cz)) {
|
|
672
|
+
return {
|
|
673
|
+
worldWidth: Math.max(maxX - minX, 0.01),
|
|
674
|
+
worldDepth: Math.max(maxY - minY, 0.01),
|
|
675
|
+
worldHeight: Math.max(maxZ - minZ, 0.01),
|
|
676
|
+
bboxCenter: {
|
|
677
|
+
x: cx,
|
|
678
|
+
y: cy,
|
|
679
|
+
z: cz
|
|
680
|
+
}
|
|
681
|
+
};
|
|
646
682
|
}
|
|
647
683
|
}
|
|
648
|
-
// Fallback
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
worldWidth = Math.abs(dims.x);
|
|
652
|
-
worldDepth = Math.abs(dims.y);
|
|
653
|
-
worldHeight = Math.abs(dims.z);
|
|
654
|
-
}
|
|
655
|
-
// Last resort: geometry bounding box
|
|
656
|
-
else if ((_component$geometry = component.geometry) !== null && _component$geometry !== void 0 && _component$geometry.boundingBox) {
|
|
657
|
-
var _bbox = component.geometry.boundingBox;
|
|
658
|
-
worldWidth = Math.abs(_bbox.max.x - _bbox.min.x);
|
|
659
|
-
worldDepth = Math.abs(_bbox.max.y - _bbox.min.y);
|
|
660
|
-
worldHeight = Math.abs(_bbox.max.z - _bbox.min.z);
|
|
661
|
-
}
|
|
684
|
+
// Fallback: world position of the object, unit dimensions
|
|
685
|
+
var wp = new THREE__namespace.Vector3();
|
|
686
|
+
(_component$getWorldPo = component.getWorldPosition) === null || _component$getWorldPo === void 0 || _component$getWorldPo.call(component, wp);
|
|
662
687
|
return {
|
|
663
|
-
worldWidth:
|
|
664
|
-
worldDepth:
|
|
665
|
-
worldHeight:
|
|
688
|
+
worldWidth: 1,
|
|
689
|
+
worldDepth: 1,
|
|
690
|
+
worldHeight: 1,
|
|
691
|
+
bboxCenter: {
|
|
692
|
+
x: wp.x,
|
|
693
|
+
y: wp.y,
|
|
694
|
+
z: wp.z
|
|
695
|
+
}
|
|
666
696
|
};
|
|
667
697
|
}
|
|
668
698
|
|
|
669
699
|
/**
|
|
670
|
-
* Project
|
|
700
|
+
* Project world-space bbox center to 2D based on view type.
|
|
701
|
+
* worldBoundingBox is an AABB so rotation is already encoded in the extents —
|
|
702
|
+
* no separate rotation correction is needed.
|
|
671
703
|
* @param {Viewport2DInstance} viewport - The viewport instance
|
|
704
|
+
* @param {Object} bboxCenter - World-space center {x, y, z}
|
|
705
|
+
* @param {number} worldWidth - X extent (max[0] - min[0])
|
|
706
|
+
* @param {number} worldDepth - Y extent (max[1] - min[1])
|
|
707
|
+
* @param {number} worldHeight - Z extent (max[2] - min[2])
|
|
672
708
|
*/
|
|
673
709
|
}, {
|
|
674
710
|
key: "project3DTo2D",
|
|
675
|
-
value: function project3DTo2D(viewport,
|
|
676
|
-
var posX, posY, rectWidth, rectHeight;
|
|
677
|
-
var rotationAngle = rot3D.z;
|
|
678
|
-
var rotationDegrees = rotationAngle * 180 / Math.PI;
|
|
711
|
+
value: function project3DTo2D(viewport, bboxCenter, worldWidth, worldDepth, worldHeight) {
|
|
679
712
|
var scale = viewport.PIXELS_PER_UNIT;
|
|
713
|
+
var posX, posY, rectWidth, rectHeight;
|
|
680
714
|
switch (viewport.viewType) {
|
|
681
715
|
case 'top':
|
|
682
|
-
//
|
|
683
|
-
posX =
|
|
684
|
-
posY =
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
if (Math.abs(rotationDegrees) === 90 || Math.abs(rotationDegrees) === 270) {
|
|
688
|
-
rectWidth = worldDepth * scale;
|
|
689
|
-
rectHeight = worldWidth * scale;
|
|
690
|
-
} else {
|
|
691
|
-
rectWidth = worldWidth * scale;
|
|
692
|
-
rectHeight = worldDepth * scale;
|
|
693
|
-
}
|
|
716
|
+
// Looking down Z-axis — X/Y plane
|
|
717
|
+
posX = bboxCenter.x;
|
|
718
|
+
posY = bboxCenter.y;
|
|
719
|
+
rectWidth = worldWidth * scale;
|
|
720
|
+
rectHeight = worldDepth * scale;
|
|
694
721
|
break;
|
|
695
722
|
case 'front':
|
|
696
|
-
//
|
|
697
|
-
posX =
|
|
698
|
-
posY =
|
|
699
|
-
|
|
700
|
-
if (Math.abs(rotationDegrees) === 90 || Math.abs(rotationDegrees) === 270) {
|
|
701
|
-
rectWidth = worldDepth * scale;
|
|
702
|
-
} else {
|
|
703
|
-
rectWidth = worldWidth * scale;
|
|
704
|
-
}
|
|
723
|
+
// Looking along Y-axis — X/Z plane
|
|
724
|
+
posX = bboxCenter.x;
|
|
725
|
+
posY = bboxCenter.z;
|
|
726
|
+
rectWidth = worldWidth * scale;
|
|
705
727
|
rectHeight = worldHeight * scale;
|
|
706
728
|
break;
|
|
707
729
|
case 'side':
|
|
708
|
-
//
|
|
709
|
-
posX = -
|
|
710
|
-
posY =
|
|
711
|
-
|
|
712
|
-
rectWidth = worldWidth * scale;
|
|
713
|
-
} else {
|
|
714
|
-
rectWidth = worldDepth * scale;
|
|
715
|
-
}
|
|
730
|
+
// Looking along X-axis — Y/Z plane (Y negated for left-right orientation)
|
|
731
|
+
posX = -bboxCenter.y;
|
|
732
|
+
posY = bboxCenter.z;
|
|
733
|
+
rectWidth = worldDepth * scale;
|
|
716
734
|
rectHeight = worldHeight * scale;
|
|
717
735
|
break;
|
|
718
736
|
default:
|
|
719
|
-
posX =
|
|
720
|
-
posY =
|
|
737
|
+
posX = bboxCenter.x;
|
|
738
|
+
posY = bboxCenter.y;
|
|
721
739
|
rectWidth = worldWidth * scale;
|
|
722
740
|
rectHeight = worldDepth * scale;
|
|
723
741
|
}
|
|
@@ -725,8 +743,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
725
743
|
posX: posX,
|
|
726
744
|
posY: posY,
|
|
727
745
|
rectWidth: rectWidth,
|
|
728
|
-
rectHeight: rectHeight
|
|
729
|
-
rotationDegrees: rotationDegrees
|
|
746
|
+
rectHeight: rectHeight
|
|
730
747
|
};
|
|
731
748
|
}
|
|
732
749
|
|
|
@@ -736,7 +753,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
736
753
|
*/
|
|
737
754
|
}, {
|
|
738
755
|
key: "addComponentInteractions",
|
|
739
|
-
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight) {
|
|
756
|
+
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter) {
|
|
740
757
|
var _this6 = this;
|
|
741
758
|
if (!this.Konva) return;
|
|
742
759
|
var colors = this.generateComponentColor(component.id);
|
|
@@ -819,9 +836,9 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
819
836
|
// Convert screen to world coordinates
|
|
820
837
|
var worldCoords = _this6.screenToWorldCoords(viewport, finalPos.x, finalPos.y, scale, worldOriginX, worldOriginY);
|
|
821
838
|
|
|
822
|
-
// Calculate new position
|
|
839
|
+
// Calculate new position: delta from old bbox center to new bbox center
|
|
823
840
|
var currentPos = component.position;
|
|
824
|
-
var newPosition = _this6.worldCoordsToObjectPosition(viewport, worldCoords, currentPos,
|
|
841
|
+
var newPosition = _this6.worldCoordsToObjectPosition(viewport, worldCoords, currentPos, bboxCenter);
|
|
825
842
|
|
|
826
843
|
// Apply translation via centralPlant API
|
|
827
844
|
var deltaX = newPosition.x - currentPos.x;
|
|
@@ -924,37 +941,45 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
924
941
|
}
|
|
925
942
|
|
|
926
943
|
/**
|
|
927
|
-
* Convert world coordinates to 3D object position
|
|
944
|
+
* Convert dragged 2D world coordinates to a new 3D object position.
|
|
945
|
+
* coord1/coord2 represent where the bbox CENTER should be in the view's 2D plane;
|
|
946
|
+
* we compute the delta from the old bbox center and apply it to the pivot position.
|
|
928
947
|
* @param {Viewport2DInstance} viewport - The viewport instance
|
|
948
|
+
* @param {{coord1, coord2}} worldCoords - Projected world coordinates from screen
|
|
949
|
+
* @param {{x,y,z}} currentPosition - Current Three.js object position (pivot)
|
|
950
|
+
* @param {{x,y,z}} bboxCenter - Old world-space bbox center
|
|
929
951
|
*/
|
|
930
952
|
}, {
|
|
931
953
|
key: "worldCoordsToObjectPosition",
|
|
932
|
-
value: function worldCoordsToObjectPosition(viewport, worldCoords, currentPosition,
|
|
954
|
+
value: function worldCoordsToObjectPosition(viewport, worldCoords, currentPosition, bboxCenter) {
|
|
933
955
|
var coord1 = worldCoords.coord1,
|
|
934
956
|
coord2 = worldCoords.coord2;
|
|
935
957
|
switch (viewport.viewType) {
|
|
936
958
|
case 'top':
|
|
959
|
+
// coord1=X, coord2=Y in world space
|
|
937
960
|
return {
|
|
938
|
-
x: coord1,
|
|
939
|
-
y: coord2,
|
|
961
|
+
x: currentPosition.x + (coord1 - bboxCenter.x),
|
|
962
|
+
y: currentPosition.y + (coord2 - bboxCenter.y),
|
|
940
963
|
z: currentPosition.z
|
|
941
964
|
};
|
|
942
965
|
case 'front':
|
|
966
|
+
// coord1=X, coord2=Z in world space
|
|
943
967
|
return {
|
|
944
|
-
x: coord1,
|
|
968
|
+
x: currentPosition.x + (coord1 - bboxCenter.x),
|
|
945
969
|
y: currentPosition.y,
|
|
946
|
-
z: coord2 -
|
|
970
|
+
z: currentPosition.z + (coord2 - bboxCenter.z)
|
|
947
971
|
};
|
|
948
972
|
case 'side':
|
|
973
|
+
// coord1=-Y (negated), coord2=Z in world space
|
|
949
974
|
return {
|
|
950
975
|
x: currentPosition.x,
|
|
951
|
-
y: -coord1,
|
|
952
|
-
z: coord2 -
|
|
976
|
+
y: currentPosition.y + (-coord1 - bboxCenter.y),
|
|
977
|
+
z: currentPosition.z + (coord2 - bboxCenter.z)
|
|
953
978
|
};
|
|
954
979
|
default:
|
|
955
980
|
return {
|
|
956
|
-
x: coord1,
|
|
957
|
-
y: coord2,
|
|
981
|
+
x: currentPosition.x + (coord1 - bboxCenter.x),
|
|
982
|
+
y: currentPosition.y + (coord2 - bboxCenter.y),
|
|
958
983
|
z: currentPosition.z
|
|
959
984
|
};
|
|
960
985
|
}
|
|
@@ -972,8 +997,9 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
972
997
|
var components = [];
|
|
973
998
|
this.sceneViewer.scene.traverse(function (object) {
|
|
974
999
|
var _object$userData, _object$userData2;
|
|
975
|
-
|
|
976
|
-
|
|
1000
|
+
// Only match the ROOT component object — must have both objectType:'component'
|
|
1001
|
+
// AND libraryId (inner GLB mesh nodes don't have libraryId)
|
|
1002
|
+
if (((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === 'component' && (_object$userData2 = object.userData) !== null && _object$userData2 !== void 0 && _object$userData2.libraryId) {
|
|
977
1003
|
components.push(object);
|
|
978
1004
|
}
|
|
979
1005
|
});
|
|
@@ -31,7 +31,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
31
31
|
* Initialize the CentralPlant manager
|
|
32
32
|
*
|
|
33
33
|
* @constructor
|
|
34
|
-
* @version 0.3.
|
|
34
|
+
* @version 0.3.5
|
|
35
35
|
* @updated 2025-10-22
|
|
36
36
|
*
|
|
37
37
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -2,6 +2,7 @@ import { createClass as _createClass, objectSpread2 as _objectSpread2, toConsuma
|
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
import { attachIODevicesToComponent } from '../../utils/ioDeviceUtils.js';
|
|
4
4
|
import modelPreloader from '../../rendering/modelPreloader.js';
|
|
5
|
+
import { computeFilteredBoundingBox } from '../../utils/boundingBoxUtils.js';
|
|
5
6
|
|
|
6
7
|
var ModelManager = /*#__PURE__*/function () {
|
|
7
8
|
function ModelManager(sceneViewer) {
|
|
@@ -286,6 +287,11 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
286
287
|
if (!libraryModel.userData) libraryModel.userData = {};
|
|
287
288
|
Object.assign(libraryModel.userData, jsonEntry.userData);
|
|
288
289
|
|
|
290
|
+
// Preserve the original hardcoded UUID so getHardcodedUuid() can find it during export.
|
|
291
|
+
// jsonEntry is the raw JSON object (no originalUuid), so we must set it explicitly from
|
|
292
|
+
// originalProps.uuid (which equals the uuid string from the scene JSON, e.g. "PUMP-1").
|
|
293
|
+
libraryModel.userData.originalUuid = originalProps.uuid;
|
|
294
|
+
|
|
289
295
|
// Apply bounding box configurations
|
|
290
296
|
if (componentData.boundingBox) {
|
|
291
297
|
libraryModel.userData.boundingBox = componentData.boundingBox;
|
|
@@ -550,15 +556,21 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
550
556
|
_context5.n = 2;
|
|
551
557
|
return Promise.all(glbLoadingPromises);
|
|
552
558
|
case 2:
|
|
553
|
-
// Update world bounding boxes for loaded models
|
|
559
|
+
// Update world bounding boxes for loaded models and propagate to the live Three.js objects
|
|
554
560
|
libraryObjectsToReplace.forEach(function (_ref2) {
|
|
555
|
-
var _jsonData$userData2;
|
|
556
561
|
var jsonData = _ref2.jsonData,
|
|
557
562
|
glbModel = _ref2.glbModel;
|
|
558
|
-
if (glbModel
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
563
|
+
if (!glbModel) return;
|
|
564
|
+
// Use filtered bbox (excludes connectors + io-devices) so it matches
|
|
565
|
+
// what pathfindingManager._enrichSceneDataWithBoundingBoxes produces
|
|
566
|
+
var filteredBox = computeFilteredBoundingBox(glbModel, ['io-device', 'connector']);
|
|
567
|
+
var worldBoundingBox = filteredBox.isEmpty() ? _this3._calculateWorldBoundingBox(glbModel) : {
|
|
568
|
+
min: [filteredBox.min.x, filteredBox.min.y, filteredBox.min.z],
|
|
569
|
+
max: [filteredBox.max.x, filteredBox.max.y, filteredBox.max.z]
|
|
570
|
+
};
|
|
571
|
+
// Update both the JSON data object AND the live scene object
|
|
572
|
+
jsonData.userData.worldBoundingBox = worldBoundingBox;
|
|
573
|
+
glbModel.userData.worldBoundingBox = worldBoundingBox;
|
|
562
574
|
});
|
|
563
575
|
|
|
564
576
|
// Dispatch completion event
|