@2112-lab/central-plant 0.3.4 → 0.3.6
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 +286 -272
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/scene/modelManager.js +20 -6
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +62 -132
- package/dist/cjs/src/managers/scene/viewport2DManager.js +203 -129
- package/dist/cjs/src/utils/sceneClearingUtility.js +2 -2
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/managers/scene/modelManager.js +20 -6
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +63 -133
- package/dist/esm/src/managers/scene/viewport2DManager.js +202 -130
- package/dist/esm/src/utils/sceneClearingUtility.js +2 -2
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { inherits as _inherits, createClass as _createClass,
|
|
1
|
+
import { inherits as _inherits, createClass as _createClass, slicedToArray as _slicedToArray, createForOfIteratorHelper as _createForOfIteratorHelper, superPropGet as _superPropGet, classCallCheck as _classCallCheck, callSuper as _callSuper, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
2
|
import { BaseDisposable } from '../../core/baseDisposable.js';
|
|
3
|
+
import * as THREE from 'three';
|
|
4
|
+
import { computeFilteredBoundingBox } from '../../utils/boundingBoxUtils.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Viewport2DInstance
|
|
@@ -85,6 +87,18 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
85
87
|
// Map of viewport instances by viewType or custom key
|
|
86
88
|
_this2.viewports = new Map();
|
|
87
89
|
|
|
90
|
+
// Per-refresh-cycle bbox cache: keyed by object.uuid, cleared each refresh()
|
|
91
|
+
// so each component bbox is computed once per cycle regardless of viewport count
|
|
92
|
+
_this2._bboxCache = new Map();
|
|
93
|
+
|
|
94
|
+
// Per-refresh-cycle component list cache: eliminates redundant scene traversals
|
|
95
|
+
// when all 3 viewports render in the same cycle
|
|
96
|
+
_this2._componentListCache = null;
|
|
97
|
+
|
|
98
|
+
// rAF debounce flag — prevents multiple same-frame refresh() calls from
|
|
99
|
+
// stacking up independent renderComponents() runs
|
|
100
|
+
_this2._refreshPending = false;
|
|
101
|
+
|
|
88
102
|
// Event listener reference for cleanup
|
|
89
103
|
_this2._objectTransformedListener = null;
|
|
90
104
|
console.log('🔲 Viewport2DManager initialized (multi-instance support)');
|
|
@@ -106,7 +120,6 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
106
120
|
|
|
107
121
|
// Listen for object transformations to refresh all viewports
|
|
108
122
|
this._objectTransformedListener = function (eventData) {
|
|
109
|
-
console.log('🔲 Viewport2DManager detected object transformation, refreshing all viewports');
|
|
110
123
|
_this3.refresh(); // Refresh all viewports
|
|
111
124
|
};
|
|
112
125
|
|
|
@@ -172,6 +185,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
172
185
|
case 3:
|
|
173
186
|
// Create new viewport instance
|
|
174
187
|
viewport = new Viewport2DInstance(this.sceneViewer, this.Konva, viewType, container);
|
|
188
|
+
viewport._instanceKey = key;
|
|
175
189
|
this.viewports.set(key, viewport);
|
|
176
190
|
|
|
177
191
|
// Initialize the stage for this viewport
|
|
@@ -349,9 +363,9 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
349
363
|
viewport.stage.width(width);
|
|
350
364
|
viewport.stage.height(height);
|
|
351
365
|
|
|
352
|
-
// Redraw
|
|
366
|
+
// Redraw grid immediately; schedule debounced component render
|
|
353
367
|
this.drawGrid(viewport);
|
|
354
|
-
this.
|
|
368
|
+
this.refresh(viewport._instanceKey);
|
|
355
369
|
}
|
|
356
370
|
}
|
|
357
371
|
|
|
@@ -528,32 +542,19 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
528
542
|
}, {
|
|
529
543
|
key: "renderComponent",
|
|
530
544
|
value: function renderComponent(viewport, component, centerX, centerY, scale) {
|
|
531
|
-
|
|
532
|
-
// Get component position and rotation
|
|
533
|
-
var pos3D = {
|
|
534
|
-
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,
|
|
535
|
-
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,
|
|
536
|
-
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
|
|
537
|
-
};
|
|
538
|
-
var rot3D = {
|
|
539
|
-
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,
|
|
540
|
-
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,
|
|
541
|
-
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
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
// Get bounding box dimensions
|
|
545
|
+
// Get world-space bounding box dimensions and center
|
|
545
546
|
var _this$getComponentDim = this.getComponentDimensions(component),
|
|
546
547
|
worldWidth = _this$getComponentDim.worldWidth,
|
|
547
548
|
worldDepth = _this$getComponentDim.worldDepth,
|
|
548
|
-
worldHeight = _this$getComponentDim.worldHeight
|
|
549
|
+
worldHeight = _this$getComponentDim.worldHeight,
|
|
550
|
+
bboxCenter = _this$getComponentDim.bboxCenter;
|
|
549
551
|
|
|
550
|
-
// Project 3D
|
|
551
|
-
var _this$project3DTo2D = this.project3DTo2D(viewport,
|
|
552
|
+
// Project 3D bbox center to 2D based on view type
|
|
553
|
+
var _this$project3DTo2D = this.project3DTo2D(viewport, bboxCenter, worldWidth, worldDepth, worldHeight),
|
|
552
554
|
posX = _this$project3DTo2D.posX,
|
|
553
555
|
posY = _this$project3DTo2D.posY,
|
|
554
556
|
rectWidth = _this$project3DTo2D.rectWidth,
|
|
555
557
|
rectHeight = _this$project3DTo2D.rectHeight;
|
|
556
|
-
_this$project3DTo2D.rotationDegrees;
|
|
557
558
|
var screenX = centerX + posX * scale;
|
|
558
559
|
var screenY = centerY - posY * scale; // Flip Y for screen coords
|
|
559
560
|
|
|
@@ -597,105 +598,156 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
597
598
|
});
|
|
598
599
|
|
|
599
600
|
// Add mouse event handlers
|
|
600
|
-
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight);
|
|
601
|
+
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter);
|
|
601
602
|
componentGroup.add(rect);
|
|
602
603
|
componentGroup.add(label);
|
|
603
604
|
viewport.componentLayer.add(componentGroup);
|
|
604
605
|
}
|
|
605
606
|
|
|
606
607
|
/**
|
|
607
|
-
*
|
|
608
|
+
* Compute worldBoundingBox for a live Three.js Object3D using the same
|
|
609
|
+
* vertex-accurate approach as computeFilteredBoundingBox (explicitly calls
|
|
610
|
+
* geometry.computeBoundingBox() on each mesh before measuring).
|
|
611
|
+
* @param {THREE.Object3D} object
|
|
612
|
+
* @returns {{min: number[], max: number[]}}
|
|
613
|
+
*/
|
|
614
|
+
}, {
|
|
615
|
+
key: "_getOrComputeWorldBoundingBox",
|
|
616
|
+
value: function _getOrComputeWorldBoundingBox(object) {
|
|
617
|
+
var _object$userData, _object$userData2;
|
|
618
|
+
// Fast path: offset the stored world bbox by the position delta since load time.
|
|
619
|
+
// Translation only shifts the bbox center — extents stay identical — so this is O(1)
|
|
620
|
+
// instead of O(meshes × vertices) from a full geometry traversal.
|
|
621
|
+
var stored = (_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.worldBoundingBox;
|
|
622
|
+
var basePos = (_object$userData2 = object.userData) === null || _object$userData2 === void 0 ? void 0 : _object$userData2._wbbBasePosition;
|
|
623
|
+
if (stored && basePos) {
|
|
624
|
+
var dx = object.position.x - basePos.x;
|
|
625
|
+
var dy = object.position.y - basePos.y;
|
|
626
|
+
var dz = object.position.z - basePos.z;
|
|
627
|
+
if (dx === 0 && dy === 0 && dz === 0) return stored;
|
|
628
|
+
return {
|
|
629
|
+
min: [stored.min[0] + dx, stored.min[1] + dy, stored.min[2] + dz],
|
|
630
|
+
max: [stored.max[0] + dx, stored.max[1] + dy, stored.max[2] + dz]
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Slow path: full vertex-accurate traversal (fallback when userData not populated)
|
|
635
|
+
if (this._bboxCache.has(object.uuid)) {
|
|
636
|
+
return this._bboxCache.get(object.uuid);
|
|
637
|
+
}
|
|
638
|
+
var box = computeFilteredBoundingBox(object, []);
|
|
639
|
+
var result;
|
|
640
|
+
if (box.isEmpty()) {
|
|
641
|
+
// Object has no geometry; fall back to a point at world position
|
|
642
|
+
var wp = new THREE.Vector3();
|
|
643
|
+
object.getWorldPosition(wp);
|
|
644
|
+
result = {
|
|
645
|
+
min: [wp.x, wp.y, wp.z],
|
|
646
|
+
max: [wp.x, wp.y, wp.z]
|
|
647
|
+
};
|
|
648
|
+
} else {
|
|
649
|
+
result = {
|
|
650
|
+
min: [box.min.x, box.min.y, box.min.z],
|
|
651
|
+
max: [box.max.x, box.max.y, box.max.z]
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
this._bboxCache.set(object.uuid, result);
|
|
655
|
+
return result;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Get component dimensions and world-space center from worldBoundingBox
|
|
608
660
|
*/
|
|
609
661
|
}, {
|
|
610
662
|
key: "getComponentDimensions",
|
|
611
663
|
value: function getComponentDimensions(component) {
|
|
612
|
-
var _component$
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
if (
|
|
619
|
-
var
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
664
|
+
var _component$getWorldPo;
|
|
665
|
+
// Always recompute from the live Three.js object so that the rect reflects
|
|
666
|
+
// the current world position after translate/drag operations.
|
|
667
|
+
// userData.worldBoundingBox is a load-time snapshot and goes stale whenever
|
|
668
|
+
// the object moves, so we cannot rely on it here.
|
|
669
|
+
var wbb = this._getOrComputeWorldBoundingBox(component);
|
|
670
|
+
if (wbb !== null && wbb !== void 0 && wbb.min && wbb !== null && wbb !== void 0 && wbb.max) {
|
|
671
|
+
var _wbb$min = _slicedToArray(wbb.min, 3),
|
|
672
|
+
minX = _wbb$min[0],
|
|
673
|
+
minY = _wbb$min[1],
|
|
674
|
+
minZ = _wbb$min[2];
|
|
675
|
+
var _wbb$max = _slicedToArray(wbb.max, 3),
|
|
676
|
+
maxX = _wbb$max[0],
|
|
677
|
+
maxY = _wbb$max[1],
|
|
678
|
+
maxZ = _wbb$max[2];
|
|
679
|
+
var cx = (minX + maxX) / 2;
|
|
680
|
+
var cy = (minY + maxY) / 2;
|
|
681
|
+
var cz = (minZ + maxZ) / 2;
|
|
682
|
+
// Guard against Infinity/NaN from empty or degenerate boxes
|
|
683
|
+
if (isFinite(cx) && isFinite(cy) && isFinite(cz)) {
|
|
684
|
+
return {
|
|
685
|
+
worldWidth: Math.max(maxX - minX, 0.01),
|
|
686
|
+
worldDepth: Math.max(maxY - minY, 0.01),
|
|
687
|
+
worldHeight: Math.max(maxZ - minZ, 0.01),
|
|
688
|
+
bboxCenter: {
|
|
689
|
+
x: cx,
|
|
690
|
+
y: cy,
|
|
691
|
+
z: cz
|
|
692
|
+
}
|
|
693
|
+
};
|
|
624
694
|
}
|
|
625
695
|
}
|
|
626
|
-
// Fallback
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
worldWidth = Math.abs(dims.x);
|
|
630
|
-
worldDepth = Math.abs(dims.y);
|
|
631
|
-
worldHeight = Math.abs(dims.z);
|
|
632
|
-
}
|
|
633
|
-
// Last resort: geometry bounding box
|
|
634
|
-
else if ((_component$geometry = component.geometry) !== null && _component$geometry !== void 0 && _component$geometry.boundingBox) {
|
|
635
|
-
var _bbox = component.geometry.boundingBox;
|
|
636
|
-
worldWidth = Math.abs(_bbox.max.x - _bbox.min.x);
|
|
637
|
-
worldDepth = Math.abs(_bbox.max.y - _bbox.min.y);
|
|
638
|
-
worldHeight = Math.abs(_bbox.max.z - _bbox.min.z);
|
|
639
|
-
}
|
|
696
|
+
// Fallback: world position of the object, unit dimensions
|
|
697
|
+
var wp = new THREE.Vector3();
|
|
698
|
+
(_component$getWorldPo = component.getWorldPosition) === null || _component$getWorldPo === void 0 || _component$getWorldPo.call(component, wp);
|
|
640
699
|
return {
|
|
641
|
-
worldWidth:
|
|
642
|
-
worldDepth:
|
|
643
|
-
worldHeight:
|
|
700
|
+
worldWidth: 1,
|
|
701
|
+
worldDepth: 1,
|
|
702
|
+
worldHeight: 1,
|
|
703
|
+
bboxCenter: {
|
|
704
|
+
x: wp.x,
|
|
705
|
+
y: wp.y,
|
|
706
|
+
z: wp.z
|
|
707
|
+
}
|
|
644
708
|
};
|
|
645
709
|
}
|
|
646
710
|
|
|
647
711
|
/**
|
|
648
|
-
* Project
|
|
712
|
+
* Project world-space bbox center to 2D based on view type.
|
|
713
|
+
* worldBoundingBox is an AABB so rotation is already encoded in the extents —
|
|
714
|
+
* no separate rotation correction is needed.
|
|
649
715
|
* @param {Viewport2DInstance} viewport - The viewport instance
|
|
716
|
+
* @param {Object} bboxCenter - World-space center {x, y, z}
|
|
717
|
+
* @param {number} worldWidth - X extent (max[0] - min[0])
|
|
718
|
+
* @param {number} worldDepth - Y extent (max[1] - min[1])
|
|
719
|
+
* @param {number} worldHeight - Z extent (max[2] - min[2])
|
|
650
720
|
*/
|
|
651
721
|
}, {
|
|
652
722
|
key: "project3DTo2D",
|
|
653
|
-
value: function project3DTo2D(viewport,
|
|
654
|
-
var posX, posY, rectWidth, rectHeight;
|
|
655
|
-
var rotationAngle = rot3D.z;
|
|
656
|
-
var rotationDegrees = rotationAngle * 180 / Math.PI;
|
|
723
|
+
value: function project3DTo2D(viewport, bboxCenter, worldWidth, worldDepth, worldHeight) {
|
|
657
724
|
var scale = viewport.PIXELS_PER_UNIT;
|
|
725
|
+
var posX, posY, rectWidth, rectHeight;
|
|
658
726
|
switch (viewport.viewType) {
|
|
659
727
|
case 'top':
|
|
660
|
-
//
|
|
661
|
-
posX =
|
|
662
|
-
posY =
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
if (Math.abs(rotationDegrees) === 90 || Math.abs(rotationDegrees) === 270) {
|
|
666
|
-
rectWidth = worldDepth * scale;
|
|
667
|
-
rectHeight = worldWidth * scale;
|
|
668
|
-
} else {
|
|
669
|
-
rectWidth = worldWidth * scale;
|
|
670
|
-
rectHeight = worldDepth * scale;
|
|
671
|
-
}
|
|
728
|
+
// Looking down Z-axis — X/Y plane
|
|
729
|
+
posX = bboxCenter.x;
|
|
730
|
+
posY = bboxCenter.y;
|
|
731
|
+
rectWidth = worldWidth * scale;
|
|
732
|
+
rectHeight = worldDepth * scale;
|
|
672
733
|
break;
|
|
673
734
|
case 'front':
|
|
674
|
-
//
|
|
675
|
-
posX =
|
|
676
|
-
posY =
|
|
677
|
-
|
|
678
|
-
if (Math.abs(rotationDegrees) === 90 || Math.abs(rotationDegrees) === 270) {
|
|
679
|
-
rectWidth = worldDepth * scale;
|
|
680
|
-
} else {
|
|
681
|
-
rectWidth = worldWidth * scale;
|
|
682
|
-
}
|
|
735
|
+
// Looking along Y-axis — X/Z plane
|
|
736
|
+
posX = bboxCenter.x;
|
|
737
|
+
posY = bboxCenter.z;
|
|
738
|
+
rectWidth = worldWidth * scale;
|
|
683
739
|
rectHeight = worldHeight * scale;
|
|
684
740
|
break;
|
|
685
741
|
case 'side':
|
|
686
|
-
//
|
|
687
|
-
posX = -
|
|
688
|
-
posY =
|
|
689
|
-
|
|
690
|
-
rectWidth = worldWidth * scale;
|
|
691
|
-
} else {
|
|
692
|
-
rectWidth = worldDepth * scale;
|
|
693
|
-
}
|
|
742
|
+
// Looking along X-axis — Y/Z plane (Y negated for left-right orientation)
|
|
743
|
+
posX = -bboxCenter.y;
|
|
744
|
+
posY = bboxCenter.z;
|
|
745
|
+
rectWidth = worldDepth * scale;
|
|
694
746
|
rectHeight = worldHeight * scale;
|
|
695
747
|
break;
|
|
696
748
|
default:
|
|
697
|
-
posX =
|
|
698
|
-
posY =
|
|
749
|
+
posX = bboxCenter.x;
|
|
750
|
+
posY = bboxCenter.y;
|
|
699
751
|
rectWidth = worldWidth * scale;
|
|
700
752
|
rectHeight = worldDepth * scale;
|
|
701
753
|
}
|
|
@@ -703,8 +755,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
703
755
|
posX: posX,
|
|
704
756
|
posY: posY,
|
|
705
757
|
rectWidth: rectWidth,
|
|
706
|
-
rectHeight: rectHeight
|
|
707
|
-
rotationDegrees: rotationDegrees
|
|
758
|
+
rectHeight: rectHeight
|
|
708
759
|
};
|
|
709
760
|
}
|
|
710
761
|
|
|
@@ -714,7 +765,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
714
765
|
*/
|
|
715
766
|
}, {
|
|
716
767
|
key: "addComponentInteractions",
|
|
717
|
-
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight) {
|
|
768
|
+
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter) {
|
|
718
769
|
var _this6 = this;
|
|
719
770
|
if (!this.Konva) return;
|
|
720
771
|
var colors = this.generateComponentColor(component.id);
|
|
@@ -726,7 +777,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
726
777
|
rect.stroke('#007bff');
|
|
727
778
|
rect.strokeWidth(3);
|
|
728
779
|
viewport.stage.container().style.cursor = 'grab';
|
|
729
|
-
viewport.componentLayer.
|
|
780
|
+
viewport.componentLayer.batchDraw();
|
|
730
781
|
}
|
|
731
782
|
});
|
|
732
783
|
rect.on('mouseleave', function () {
|
|
@@ -735,7 +786,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
735
786
|
rect.stroke(colors.stroke);
|
|
736
787
|
rect.strokeWidth(2);
|
|
737
788
|
viewport.stage.container().style.cursor = 'default';
|
|
738
|
-
viewport.componentLayer.
|
|
789
|
+
viewport.componentLayer.batchDraw();
|
|
739
790
|
}
|
|
740
791
|
});
|
|
741
792
|
|
|
@@ -779,7 +830,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
779
830
|
// Snap to grid
|
|
780
831
|
var snappedPos = _this6.snapScreenToGrid(viewport, currentPos.x, currentPos.y, scale, worldOriginX, worldOriginY);
|
|
781
832
|
componentGroup.position(snappedPos);
|
|
782
|
-
viewport.componentLayer.
|
|
833
|
+
viewport.componentLayer.batchDraw();
|
|
783
834
|
});
|
|
784
835
|
|
|
785
836
|
// DRAG END
|
|
@@ -797,9 +848,9 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
797
848
|
// Convert screen to world coordinates
|
|
798
849
|
var worldCoords = _this6.screenToWorldCoords(viewport, finalPos.x, finalPos.y, scale, worldOriginX, worldOriginY);
|
|
799
850
|
|
|
800
|
-
// Calculate new position
|
|
851
|
+
// Calculate new position: delta from old bbox center to new bbox center
|
|
801
852
|
var currentPos = component.position;
|
|
802
|
-
var newPosition = _this6.worldCoordsToObjectPosition(viewport, worldCoords, currentPos,
|
|
853
|
+
var newPosition = _this6.worldCoordsToObjectPosition(viewport, worldCoords, currentPos, bboxCenter);
|
|
803
854
|
|
|
804
855
|
// Apply translation via centralPlant API
|
|
805
856
|
var deltaX = newPosition.x - currentPos.x;
|
|
@@ -902,37 +953,45 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
902
953
|
}
|
|
903
954
|
|
|
904
955
|
/**
|
|
905
|
-
* Convert world coordinates to 3D object position
|
|
956
|
+
* Convert dragged 2D world coordinates to a new 3D object position.
|
|
957
|
+
* coord1/coord2 represent where the bbox CENTER should be in the view's 2D plane;
|
|
958
|
+
* we compute the delta from the old bbox center and apply it to the pivot position.
|
|
906
959
|
* @param {Viewport2DInstance} viewport - The viewport instance
|
|
960
|
+
* @param {{coord1, coord2}} worldCoords - Projected world coordinates from screen
|
|
961
|
+
* @param {{x,y,z}} currentPosition - Current Three.js object position (pivot)
|
|
962
|
+
* @param {{x,y,z}} bboxCenter - Old world-space bbox center
|
|
907
963
|
*/
|
|
908
964
|
}, {
|
|
909
965
|
key: "worldCoordsToObjectPosition",
|
|
910
|
-
value: function worldCoordsToObjectPosition(viewport, worldCoords, currentPosition,
|
|
966
|
+
value: function worldCoordsToObjectPosition(viewport, worldCoords, currentPosition, bboxCenter) {
|
|
911
967
|
var coord1 = worldCoords.coord1,
|
|
912
968
|
coord2 = worldCoords.coord2;
|
|
913
969
|
switch (viewport.viewType) {
|
|
914
970
|
case 'top':
|
|
971
|
+
// coord1=X, coord2=Y in world space
|
|
915
972
|
return {
|
|
916
|
-
x: coord1,
|
|
917
|
-
y: coord2,
|
|
973
|
+
x: currentPosition.x + (coord1 - bboxCenter.x),
|
|
974
|
+
y: currentPosition.y + (coord2 - bboxCenter.y),
|
|
918
975
|
z: currentPosition.z
|
|
919
976
|
};
|
|
920
977
|
case 'front':
|
|
978
|
+
// coord1=X, coord2=Z in world space
|
|
921
979
|
return {
|
|
922
|
-
x: coord1,
|
|
980
|
+
x: currentPosition.x + (coord1 - bboxCenter.x),
|
|
923
981
|
y: currentPosition.y,
|
|
924
|
-
z: coord2 -
|
|
982
|
+
z: currentPosition.z + (coord2 - bboxCenter.z)
|
|
925
983
|
};
|
|
926
984
|
case 'side':
|
|
985
|
+
// coord1=-Y (negated), coord2=Z in world space
|
|
927
986
|
return {
|
|
928
987
|
x: currentPosition.x,
|
|
929
|
-
y: -coord1,
|
|
930
|
-
z: coord2 -
|
|
988
|
+
y: currentPosition.y + (-coord1 - bboxCenter.y),
|
|
989
|
+
z: currentPosition.z + (coord2 - bboxCenter.z)
|
|
931
990
|
};
|
|
932
991
|
default:
|
|
933
992
|
return {
|
|
934
|
-
x: coord1,
|
|
935
|
-
y: coord2,
|
|
993
|
+
x: currentPosition.x + (coord1 - bboxCenter.x),
|
|
994
|
+
y: currentPosition.y + (coord2 - bboxCenter.y),
|
|
936
995
|
z: currentPosition.z
|
|
937
996
|
};
|
|
938
997
|
}
|
|
@@ -944,17 +1003,20 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
944
1003
|
}, {
|
|
945
1004
|
key: "getSceneComponents",
|
|
946
1005
|
value: function getSceneComponents() {
|
|
1006
|
+
if (this._componentListCache) return this._componentListCache;
|
|
947
1007
|
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
948
1008
|
return [];
|
|
949
1009
|
}
|
|
950
1010
|
var components = [];
|
|
951
1011
|
this.sceneViewer.scene.traverse(function (object) {
|
|
952
|
-
var _object$
|
|
953
|
-
|
|
954
|
-
|
|
1012
|
+
var _object$userData3, _object$userData4;
|
|
1013
|
+
// Only match the ROOT component object — must have both objectType:'component'
|
|
1014
|
+
// AND libraryId (inner GLB mesh nodes don't have libraryId)
|
|
1015
|
+
if (((_object$userData3 = object.userData) === null || _object$userData3 === void 0 ? void 0 : _object$userData3.objectType) === 'component' && (_object$userData4 = object.userData) !== null && _object$userData4 !== void 0 && _object$userData4.libraryId) {
|
|
955
1016
|
components.push(object);
|
|
956
1017
|
}
|
|
957
1018
|
});
|
|
1019
|
+
this._componentListCache = components;
|
|
958
1020
|
return components;
|
|
959
1021
|
}
|
|
960
1022
|
|
|
@@ -1060,35 +1122,45 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
1060
1122
|
}
|
|
1061
1123
|
|
|
1062
1124
|
/**
|
|
1063
|
-
* Refresh a specific viewport or all viewports
|
|
1125
|
+
* Refresh a specific viewport or all viewports.
|
|
1126
|
+
* Debounced via requestAnimationFrame so multiple calls within the same
|
|
1127
|
+
* frame (e.g. from Viewport2D mount + refreshAll2DViews) collapse into one.
|
|
1064
1128
|
* @param {string} key - Optional viewport key. If not provided, refreshes all viewports
|
|
1065
1129
|
*/
|
|
1066
1130
|
}, {
|
|
1067
1131
|
key: "refresh",
|
|
1068
1132
|
value: function refresh() {
|
|
1133
|
+
var _this7 = this;
|
|
1069
1134
|
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
1070
|
-
if (
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1135
|
+
if (this._refreshPending) return;
|
|
1136
|
+
this._refreshPending = true;
|
|
1137
|
+
requestAnimationFrame(function () {
|
|
1138
|
+
_this7._refreshPending = false;
|
|
1139
|
+
// Clear per-cycle caches so each component is measured/traversed once per paint
|
|
1140
|
+
_this7._bboxCache.clear();
|
|
1141
|
+
_this7._componentListCache = null;
|
|
1142
|
+
if (key) {
|
|
1143
|
+
var viewport = _this7.viewports.get(key);
|
|
1144
|
+
if (viewport && viewport.isReady) {
|
|
1145
|
+
_this7.renderComponents(viewport);
|
|
1146
|
+
}
|
|
1147
|
+
} else {
|
|
1148
|
+
var _iterator = _createForOfIteratorHelper(_this7.viewports.values()),
|
|
1149
|
+
_step;
|
|
1150
|
+
try {
|
|
1151
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1152
|
+
var _viewport = _step.value;
|
|
1153
|
+
if (_viewport.isReady) {
|
|
1154
|
+
_this7.renderComponents(_viewport);
|
|
1155
|
+
}
|
|
1084
1156
|
}
|
|
1157
|
+
} catch (err) {
|
|
1158
|
+
_iterator.e(err);
|
|
1159
|
+
} finally {
|
|
1160
|
+
_iterator.f();
|
|
1085
1161
|
}
|
|
1086
|
-
} catch (err) {
|
|
1087
|
-
_iterator.e(err);
|
|
1088
|
-
} finally {
|
|
1089
|
-
_iterator.f();
|
|
1090
1162
|
}
|
|
1091
|
-
}
|
|
1163
|
+
});
|
|
1092
1164
|
}
|
|
1093
1165
|
|
|
1094
1166
|
/**
|
|
@@ -222,10 +222,10 @@ var SceneClearingUtility = /*#__PURE__*/function () {
|
|
|
222
222
|
throw new Error('Scene not available for clearing');
|
|
223
223
|
case 1:
|
|
224
224
|
componentsToRemove = [];
|
|
225
|
-
scene = this.sceneViewer.scene; // Collect
|
|
225
|
+
scene = this.sceneViewer.scene; // Collect component, segment, and gateway objects
|
|
226
226
|
scene.traverse(function (child) {
|
|
227
227
|
if (child === scene) return;
|
|
228
|
-
var isComponent = child.userData && (child.userData.objectType === 'component' || child.userData.objectType === '
|
|
228
|
+
var isComponent = child.userData && (child.userData.objectType === 'component' || child.userData.objectType === 'segment' || child.userData.objectType === 'gateway' || child.userData.objectType === 'connector');
|
|
229
229
|
var isDirectChild = child.parent === scene;
|
|
230
230
|
if (isComponent && isDirectChild) {
|
|
231
231
|
componentsToRemove.push(child);
|