@2112-lab/central-plant 0.3.11 → 0.3.13
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 +202 -114
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/scene/modelManager.js +9 -0
- package/dist/cjs/src/managers/scene/viewport2DManager.js +187 -113
- package/dist/cjs/src/utils/boundingBoxUtils.js +6 -1
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/managers/scene/modelManager.js +9 -0
- package/dist/esm/src/managers/scene/viewport2DManager.js +187 -113
- package/dist/esm/src/utils/boundingBoxUtils.js +6 -1
- package/package.json +1 -1
|
@@ -123,6 +123,9 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
123
123
|
// stacking up independent renderComponents() runs
|
|
124
124
|
_this2._refreshPending = false;
|
|
125
125
|
|
|
126
|
+
// Set of viewport keys pending refresh (collects keys across multiple refresh() calls in same frame)
|
|
127
|
+
_this2._pendingRefreshKeys = new Set();
|
|
128
|
+
|
|
126
129
|
// Event listener reference for cleanup
|
|
127
130
|
_this2._objectTransformedListener = null;
|
|
128
131
|
console.log('🔲 Viewport2DManager initialized (multi-instance support)');
|
|
@@ -212,8 +215,10 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
212
215
|
viewport._instanceKey = key;
|
|
213
216
|
this.viewports.set(key, viewport);
|
|
214
217
|
|
|
215
|
-
// Initialize the stage for this viewport
|
|
216
|
-
|
|
218
|
+
// Initialize the stage for this viewport (waits for DOM layout to settle)
|
|
219
|
+
_context.n = 4;
|
|
220
|
+
return this.initializeStage(viewport);
|
|
221
|
+
case 4:
|
|
217
222
|
return _context.a(2, viewport.isReady);
|
|
218
223
|
}
|
|
219
224
|
}, _callee, this);
|
|
@@ -307,50 +312,67 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
307
312
|
/**
|
|
308
313
|
* Initialize Konva stage for a specific viewport instance
|
|
309
314
|
* @param {Viewport2DInstance} viewport - The viewport instance to initialize
|
|
315
|
+
* @returns {Promise<void>} Resolves when viewport is fully ready
|
|
310
316
|
*/
|
|
311
317
|
)
|
|
312
318
|
}, {
|
|
313
319
|
key: "initializeStage",
|
|
314
320
|
value: function initializeStage(viewport) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
var width = rect.width || 800;
|
|
323
|
-
var height = rect.height || 600;
|
|
324
|
-
console.log("\uD83D\uDCD0 Initializing Konva stage (".concat(viewport.viewType, "): ").concat(width, "x").concat(height));
|
|
325
|
-
|
|
326
|
-
// Create Konva stage for this viewport
|
|
327
|
-
viewport.stage = new this.Konva.Stage({
|
|
328
|
-
container: viewport.container,
|
|
329
|
-
width: width,
|
|
330
|
-
height: height
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
// Create separate layers for grid and components
|
|
334
|
-
viewport.gridLayer = new this.Konva.Layer();
|
|
335
|
-
viewport.componentLayer = new this.Konva.Layer();
|
|
336
|
-
|
|
337
|
-
// Add layers to stage in order (grid first, then components)
|
|
338
|
-
viewport.stage.add(viewport.gridLayer);
|
|
339
|
-
viewport.stage.add(viewport.componentLayer);
|
|
340
|
-
|
|
341
|
-
// Setup resize handling
|
|
342
|
-
this.setupResizeListener(viewport);
|
|
343
|
-
|
|
344
|
-
// Setup zoom and pan handlers
|
|
345
|
-
this.setupZoomAndPanHandlers(viewport);
|
|
321
|
+
var _this4 = this;
|
|
322
|
+
return new Promise(function (resolve) {
|
|
323
|
+
if (!_this4.Konva || !viewport.container) {
|
|
324
|
+
console.error('❌ Cannot initialize stage: Konva or container missing');
|
|
325
|
+
resolve();
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
346
328
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
329
|
+
// Get container dimensions
|
|
330
|
+
var rect = viewport.container.getBoundingClientRect();
|
|
331
|
+
var width = rect.width || 800;
|
|
332
|
+
var height = rect.height || 600;
|
|
333
|
+
console.log("\uD83D\uDCD0 Initializing Konva stage (".concat(viewport.viewType, "): ").concat(width, "x").concat(height));
|
|
334
|
+
|
|
335
|
+
// Create Konva stage for this viewport
|
|
336
|
+
viewport.stage = new _this4.Konva.Stage({
|
|
337
|
+
container: viewport.container,
|
|
338
|
+
width: width,
|
|
339
|
+
height: height
|
|
340
|
+
});
|
|
350
341
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
342
|
+
// Create separate layers for grid and components
|
|
343
|
+
viewport.gridLayer = new _this4.Konva.Layer();
|
|
344
|
+
viewport.componentLayer = new _this4.Konva.Layer();
|
|
345
|
+
|
|
346
|
+
// Add layers to stage in order (grid first, then components)
|
|
347
|
+
viewport.stage.add(viewport.gridLayer);
|
|
348
|
+
viewport.stage.add(viewport.componentLayer);
|
|
349
|
+
|
|
350
|
+
// Setup resize handling
|
|
351
|
+
_this4.setupResizeListener(viewport);
|
|
352
|
+
|
|
353
|
+
// Setup zoom and pan handlers
|
|
354
|
+
_this4.setupZoomAndPanHandlers(viewport);
|
|
355
|
+
|
|
356
|
+
// Draw initial grid (lightweight, safe to do immediately)
|
|
357
|
+
_this4.drawGrid(viewport);
|
|
358
|
+
|
|
359
|
+
// Defer component rendering to next frame to ensure DOM layout is finalized.
|
|
360
|
+
// Without this, getBoundingClientRect() may return stale/zero dimensions
|
|
361
|
+
// if the container hasn't been fully laid out by CSS yet.
|
|
362
|
+
requestAnimationFrame(function () {
|
|
363
|
+
// Re-check container dimensions after layout settles
|
|
364
|
+
var finalRect = viewport.container.getBoundingClientRect();
|
|
365
|
+
if (finalRect.width > 0 && finalRect.height > 0) {
|
|
366
|
+
viewport.stage.width(finalRect.width);
|
|
367
|
+
viewport.stage.height(finalRect.height);
|
|
368
|
+
_this4.drawGrid(viewport);
|
|
369
|
+
}
|
|
370
|
+
_this4.renderComponents(viewport);
|
|
371
|
+
viewport.isReady = true;
|
|
372
|
+
console.log("\u2705 Viewport2DManager stage initialized (".concat(viewport.viewType, ")"));
|
|
373
|
+
resolve();
|
|
374
|
+
});
|
|
375
|
+
});
|
|
354
376
|
}
|
|
355
377
|
|
|
356
378
|
/**
|
|
@@ -360,12 +382,12 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
360
382
|
}, {
|
|
361
383
|
key: "setupResizeListener",
|
|
362
384
|
value: function setupResizeListener(viewport) {
|
|
363
|
-
var
|
|
385
|
+
var _this5 = this;
|
|
364
386
|
if (typeof window === 'undefined' || !window.ResizeObserver || !viewport.container) {
|
|
365
387
|
return;
|
|
366
388
|
}
|
|
367
389
|
viewport._resizeObserver = new ResizeObserver(function () {
|
|
368
|
-
|
|
390
|
+
_this5.resizeStage(viewport);
|
|
369
391
|
});
|
|
370
392
|
viewport._resizeObserver.observe(viewport.container);
|
|
371
393
|
}
|
|
@@ -400,6 +422,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
400
422
|
}, {
|
|
401
423
|
key: "setupZoomAndPanHandlers",
|
|
402
424
|
value: function setupZoomAndPanHandlers(viewport) {
|
|
425
|
+
var _this6 = this;
|
|
403
426
|
if (!viewport.stage) return;
|
|
404
427
|
|
|
405
428
|
// Mouse wheel zoom
|
|
@@ -425,6 +448,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
425
448
|
y: pointer.y - mousePointTo.y * clampedScale
|
|
426
449
|
};
|
|
427
450
|
viewport.stage.position(newPos);
|
|
451
|
+
_this6.drawGrid(viewport);
|
|
428
452
|
viewport.stage.batchDraw();
|
|
429
453
|
});
|
|
430
454
|
|
|
@@ -444,6 +468,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
444
468
|
viewport.stage.x(viewport.stage.x() + dx);
|
|
445
469
|
viewport.stage.y(viewport.stage.y() + dy);
|
|
446
470
|
viewport.lastPanPoint = pos;
|
|
471
|
+
_this6.drawGrid(viewport);
|
|
447
472
|
viewport.stage.batchDraw();
|
|
448
473
|
});
|
|
449
474
|
viewport.stage.on('mouseup', function () {
|
|
@@ -468,33 +493,40 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
468
493
|
var width = viewport.stage.width();
|
|
469
494
|
var height = viewport.stage.height();
|
|
470
495
|
var gridSize = viewport.PIXELS_PER_UNIT;
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
var
|
|
474
|
-
|
|
496
|
+
var stageX = viewport.stage.x();
|
|
497
|
+
var stageY = viewport.stage.y();
|
|
498
|
+
var scale = viewport.stage.scaleX();
|
|
499
|
+
|
|
500
|
+
// World origin sits at (width/2, height/2) in stage-local coordinates
|
|
501
|
+
var originX = width / 2;
|
|
502
|
+
var originY = height / 2;
|
|
503
|
+
|
|
504
|
+
// Compute the visible area in stage-local coordinates, with 1-cell padding
|
|
505
|
+
var visLeft = -stageX / scale - gridSize;
|
|
506
|
+
var visTop = -stageY / scale - gridSize;
|
|
507
|
+
var visRight = (width - stageX) / scale + gridSize;
|
|
508
|
+
var visBottom = (height - stageY) / scale + gridSize;
|
|
475
509
|
var gridGroup = new this.Konva.Group();
|
|
476
|
-
|
|
477
|
-
// Draw vertical lines centered at origin
|
|
478
|
-
var startX = centerX % gridSize - gridSize;
|
|
479
510
|
var gridColor = '#dddddd';
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
511
|
+
|
|
512
|
+
// Draw vertical lines — start at the first grid column left of the visible area
|
|
513
|
+
var firstX = Math.floor((visLeft - originX) / gridSize) * gridSize + originX;
|
|
514
|
+
for (var x = firstX; x <= visRight; x += gridSize) {
|
|
515
|
+
var isOriginLine = Math.abs(x - originX) < 0.5;
|
|
483
516
|
gridGroup.add(new this.Konva.Line({
|
|
484
|
-
points: [x,
|
|
517
|
+
points: [x, visTop, x, visBottom],
|
|
485
518
|
stroke: gridColor,
|
|
486
519
|
strokeWidth: isOriginLine ? 2 : 1,
|
|
487
520
|
listening: false
|
|
488
521
|
}));
|
|
489
522
|
}
|
|
490
523
|
|
|
491
|
-
// Draw horizontal lines
|
|
492
|
-
var
|
|
493
|
-
for (var y =
|
|
494
|
-
var
|
|
495
|
-
var _isOriginLine = _distFromCenter < 1;
|
|
524
|
+
// Draw horizontal lines — start at the first grid row above the visible area
|
|
525
|
+
var firstY = Math.floor((visTop - originY) / gridSize) * gridSize + originY;
|
|
526
|
+
for (var y = firstY; y <= visBottom; y += gridSize) {
|
|
527
|
+
var _isOriginLine = Math.abs(y - originY) < 0.5;
|
|
496
528
|
gridGroup.add(new this.Konva.Line({
|
|
497
|
-
points: [
|
|
529
|
+
points: [visLeft, y, visRight, y],
|
|
498
530
|
stroke: gridColor,
|
|
499
531
|
strokeWidth: _isOriginLine ? 2 : 1,
|
|
500
532
|
listening: false
|
|
@@ -504,14 +536,14 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
504
536
|
// Draw center crosshair at world origin
|
|
505
537
|
var crosshairSize = gridSize;
|
|
506
538
|
gridGroup.add(new this.Konva.Line({
|
|
507
|
-
points: [
|
|
539
|
+
points: [originX, originY - crosshairSize, originX, originY + crosshairSize],
|
|
508
540
|
stroke: '#333',
|
|
509
541
|
strokeWidth: 1,
|
|
510
542
|
listening: false,
|
|
511
543
|
dash: [5, 5]
|
|
512
544
|
}));
|
|
513
545
|
gridGroup.add(new this.Konva.Line({
|
|
514
|
-
points: [
|
|
546
|
+
points: [originX - crosshairSize, originY, originX + crosshairSize, originY],
|
|
515
547
|
stroke: '#333',
|
|
516
548
|
strokeWidth: 1,
|
|
517
549
|
listening: false,
|
|
@@ -528,7 +560,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
528
560
|
}, {
|
|
529
561
|
key: "renderComponents",
|
|
530
562
|
value: function renderComponents(viewport) {
|
|
531
|
-
var
|
|
563
|
+
var _this7 = this;
|
|
532
564
|
if (!viewport.componentLayer || !viewport.stage || !this.sceneViewer) return;
|
|
533
565
|
viewport.componentLayer.destroyChildren();
|
|
534
566
|
|
|
@@ -539,19 +571,18 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
539
571
|
return;
|
|
540
572
|
}
|
|
541
573
|
|
|
542
|
-
//
|
|
543
|
-
if (
|
|
544
|
-
|
|
545
|
-
viewport._lastComponentCount = components.length;
|
|
546
|
-
}
|
|
574
|
+
// Track render count for debugging
|
|
575
|
+
if (viewport._renderCount === undefined) viewport._renderCount = 0;
|
|
576
|
+
viewport._renderCount++;
|
|
547
577
|
var width = viewport.stage.width();
|
|
548
578
|
var height = viewport.stage.height();
|
|
549
579
|
var centerX = width / 2;
|
|
550
580
|
var centerY = height / 2;
|
|
551
581
|
var scale = viewport.PIXELS_PER_UNIT;
|
|
582
|
+
console.log("\uD83C\uDFA8 RENDER #".concat(viewport._renderCount, " (").concat(viewport.viewType, "): ").concat(components.length, " components, stage=").concat(width, "x").concat(height, ", center=(").concat(centerX, ", ").concat(centerY, ")"));
|
|
552
583
|
components.forEach(function (component) {
|
|
553
584
|
try {
|
|
554
|
-
|
|
585
|
+
_this7.renderComponent(viewport, component, centerX, centerY, scale);
|
|
555
586
|
} catch (err) {
|
|
556
587
|
console.warn('⚠️ Error rendering component in 2D:', component.name, err);
|
|
557
588
|
}
|
|
@@ -582,6 +613,11 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
582
613
|
var screenX = centerX + posX * scale;
|
|
583
614
|
var screenY = centerY - posY * scale; // Flip Y for screen coords
|
|
584
615
|
|
|
616
|
+
// Debug: Log ALL component positions on first render only
|
|
617
|
+
if (viewport._renderCount === 1) {
|
|
618
|
+
console.log("\uD83D\uDD0D [".concat(viewport.viewType, "] ").concat(component.name, ": bbox.z=").concat(bboxCenter.z.toFixed(2), ", posY=").concat(posY.toFixed(2), ", screenY=").concat(screenY.toFixed(0), ", centerY=").concat(centerY.toFixed(0)));
|
|
619
|
+
}
|
|
620
|
+
|
|
585
621
|
// Generate unique color for this component
|
|
586
622
|
var colors = this.generateComponentColor(component.id);
|
|
587
623
|
|
|
@@ -611,18 +647,19 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
611
647
|
draggable: false
|
|
612
648
|
});
|
|
613
649
|
|
|
614
|
-
// Add label
|
|
650
|
+
// Add label (hidden by default; shown on hover)
|
|
615
651
|
var label = new this.Konva.Text({
|
|
616
652
|
x: -rectWidth / 2,
|
|
617
653
|
y: -rectHeight / 2 - 20,
|
|
618
654
|
text: component.name || 'Component',
|
|
619
655
|
fontSize: 12,
|
|
620
656
|
fill: '#333',
|
|
621
|
-
listening: false
|
|
657
|
+
listening: false,
|
|
658
|
+
visible: false
|
|
622
659
|
});
|
|
623
660
|
|
|
624
661
|
// Add mouse event handlers
|
|
625
|
-
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter);
|
|
662
|
+
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter, label);
|
|
626
663
|
componentGroup.add(rect);
|
|
627
664
|
componentGroup.add(label);
|
|
628
665
|
viewport.componentLayer.add(componentGroup);
|
|
@@ -659,7 +696,14 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
659
696
|
if (this._bboxCache.has(object.uuid)) {
|
|
660
697
|
return this._bboxCache.get(object.uuid);
|
|
661
698
|
}
|
|
662
|
-
|
|
699
|
+
|
|
700
|
+
// Force matrix updates before computing bbox to ensure world-space accuracy
|
|
701
|
+
object.updateMatrix();
|
|
702
|
+
object.updateMatrixWorld(true);
|
|
703
|
+
|
|
704
|
+
// Exclude io-devices and connectors to match the stored worldBoundingBox
|
|
705
|
+
// computed in modelManager.replaceWithGLBModels()
|
|
706
|
+
var box = boundingBoxUtils.computeFilteredBoundingBox(object, ['io-device', 'connector']);
|
|
663
707
|
var result;
|
|
664
708
|
if (box.isEmpty()) {
|
|
665
709
|
// Object has no geometry; fall back to a point at world position
|
|
@@ -789,8 +833,8 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
789
833
|
*/
|
|
790
834
|
}, {
|
|
791
835
|
key: "addComponentInteractions",
|
|
792
|
-
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter) {
|
|
793
|
-
var
|
|
836
|
+
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter, label) {
|
|
837
|
+
var _this8 = this;
|
|
794
838
|
if (!this.Konva) return;
|
|
795
839
|
var colors = this.generateComponentColor(component.id);
|
|
796
840
|
|
|
@@ -801,6 +845,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
801
845
|
rect.stroke('#007bff');
|
|
802
846
|
rect.strokeWidth(3);
|
|
803
847
|
viewport.stage.container().style.cursor = 'grab';
|
|
848
|
+
if (label) label.visible(true);
|
|
804
849
|
viewport.componentLayer.batchDraw();
|
|
805
850
|
}
|
|
806
851
|
});
|
|
@@ -810,6 +855,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
810
855
|
rect.stroke(colors.stroke);
|
|
811
856
|
rect.strokeWidth(2);
|
|
812
857
|
viewport.stage.container().style.cursor = 'default';
|
|
858
|
+
if (label) label.visible(false);
|
|
813
859
|
viewport.componentLayer.batchDraw();
|
|
814
860
|
}
|
|
815
861
|
});
|
|
@@ -817,12 +863,12 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
817
863
|
// CLICK EVENT
|
|
818
864
|
rect.on('click', function () {
|
|
819
865
|
if (!viewport.isDragging) {
|
|
820
|
-
var
|
|
866
|
+
var _this8$sceneViewer;
|
|
821
867
|
console.log("\uD83C\uDFAF Component clicked: ".concat(component.name));
|
|
822
868
|
|
|
823
869
|
// Use centralPlant API to select component
|
|
824
|
-
if ((
|
|
825
|
-
|
|
870
|
+
if ((_this8$sceneViewer = _this8.sceneViewer) !== null && _this8$sceneViewer !== void 0 && _this8$sceneViewer.centralPlant && component.uuid) {
|
|
871
|
+
_this8.sceneViewer.centralPlant.selectComponent(component.uuid);
|
|
826
872
|
}
|
|
827
873
|
}
|
|
828
874
|
});
|
|
@@ -852,7 +898,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
852
898
|
var worldOriginY = stageHeight / 2;
|
|
853
899
|
|
|
854
900
|
// Snap to grid
|
|
855
|
-
var snappedPos =
|
|
901
|
+
var snappedPos = _this8.snapScreenToGrid(viewport, currentPos.x, currentPos.y, scale, worldOriginX, worldOriginY);
|
|
856
902
|
componentGroup.position(snappedPos);
|
|
857
903
|
viewport.componentLayer.batchDraw();
|
|
858
904
|
});
|
|
@@ -860,7 +906,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
860
906
|
// DRAG END
|
|
861
907
|
componentGroup.on('dragend', function () {
|
|
862
908
|
setTimeout(function () {
|
|
863
|
-
var
|
|
909
|
+
var _this8$sceneViewer2;
|
|
864
910
|
viewport.isDragging = false;
|
|
865
911
|
var finalPos = componentGroup.position();
|
|
866
912
|
var stageWidth = viewport.stage.width();
|
|
@@ -870,17 +916,17 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
870
916
|
var worldOriginY = stageHeight / 2;
|
|
871
917
|
|
|
872
918
|
// Convert screen to world coordinates
|
|
873
|
-
var worldCoords =
|
|
919
|
+
var worldCoords = _this8.screenToWorldCoords(viewport, finalPos.x, finalPos.y, scale, worldOriginX, worldOriginY);
|
|
874
920
|
|
|
875
921
|
// Calculate new position: delta from old bbox center to new bbox center
|
|
876
922
|
var currentPos = component.position;
|
|
877
|
-
var newPosition =
|
|
923
|
+
var newPosition = _this8.worldCoordsToObjectPosition(viewport, worldCoords, currentPos, bboxCenter);
|
|
878
924
|
|
|
879
925
|
// Apply translation via centralPlant API
|
|
880
926
|
var deltaX = newPosition.x - currentPos.x;
|
|
881
927
|
var deltaY = newPosition.y - currentPos.y;
|
|
882
928
|
var deltaZ = newPosition.z - currentPos.z;
|
|
883
|
-
if ((
|
|
929
|
+
if ((_this8$sceneViewer2 = _this8.sceneViewer) !== null && _this8$sceneViewer2 !== void 0 && _this8$sceneViewer2.centralPlant && component.uuid) {
|
|
884
930
|
var success = true;
|
|
885
931
|
|
|
886
932
|
// Suppress per-axis path updates so the pathfinder only runs once,
|
|
@@ -888,32 +934,32 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
888
934
|
// Running updatePaths() after each individual axis (the default
|
|
889
935
|
// translateComponent behaviour) produces intermediate wrong results on
|
|
890
936
|
// the first drag because no cached fingerprint exists yet to skip them.
|
|
891
|
-
var wasAutoUpdate =
|
|
892
|
-
|
|
937
|
+
var wasAutoUpdate = _this8.sceneViewer.shouldUpdatePaths;
|
|
938
|
+
_this8.sceneViewer.shouldUpdatePaths = false;
|
|
893
939
|
try {
|
|
894
940
|
if (Math.abs(deltaX) > 0.01) {
|
|
895
|
-
success = success &&
|
|
941
|
+
success = success && _this8.sceneViewer.centralPlant.translate(component.uuid, 'x', deltaX);
|
|
896
942
|
}
|
|
897
943
|
if (Math.abs(deltaY) > 0.01) {
|
|
898
|
-
success = success &&
|
|
944
|
+
success = success && _this8.sceneViewer.centralPlant.translate(component.uuid, 'y', deltaY);
|
|
899
945
|
}
|
|
900
946
|
if (Math.abs(deltaZ) > 0.01) {
|
|
901
|
-
success = success &&
|
|
947
|
+
success = success && _this8.sceneViewer.centralPlant.translate(component.uuid, 'z', deltaZ);
|
|
902
948
|
}
|
|
903
949
|
} finally {
|
|
904
|
-
|
|
950
|
+
_this8.sceneViewer.shouldUpdatePaths = wasAutoUpdate;
|
|
905
951
|
}
|
|
906
|
-
if (!success &&
|
|
952
|
+
if (!success && _this8.dragStartPosition) {
|
|
907
953
|
console.warn('⚠️ Failed to translate component, reverting position');
|
|
908
|
-
componentGroup.position(
|
|
954
|
+
componentGroup.position(_this8.dragStartPosition);
|
|
909
955
|
} else {
|
|
910
956
|
console.log("\u2705 Component ".concat(component.name, " translated successfully in 2D viewport"));
|
|
911
957
|
|
|
912
958
|
// Single path update with the final combined position
|
|
913
|
-
if (wasAutoUpdate &&
|
|
959
|
+
if (wasAutoUpdate && _this8.sceneViewer) {
|
|
914
960
|
console.log('🔄 Auto-updating paths after 2D viewport translation...');
|
|
915
961
|
try {
|
|
916
|
-
|
|
962
|
+
_this8.sceneViewer.updatePaths();
|
|
917
963
|
console.log('✅ Paths auto-updated successfully from 2D viewport');
|
|
918
964
|
} catch (error) {
|
|
919
965
|
console.error('❌ Error auto-updating paths from 2D viewport:', error);
|
|
@@ -1166,28 +1212,39 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
1166
1212
|
}, {
|
|
1167
1213
|
key: "refresh",
|
|
1168
1214
|
value: function refresh() {
|
|
1169
|
-
var
|
|
1215
|
+
var _this9 = this;
|
|
1170
1216
|
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
1217
|
+
// Collect viewport keys to refresh; null means "all viewports"
|
|
1218
|
+
if (key) {
|
|
1219
|
+
this._pendingRefreshKeys.add(key);
|
|
1220
|
+
} else {
|
|
1221
|
+
// null key means refresh all — mark with special sentinel
|
|
1222
|
+
this._pendingRefreshKeys.add('__ALL__');
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// If already scheduled, the rAF callback will process our newly-added key
|
|
1171
1226
|
if (this._refreshPending) return;
|
|
1172
1227
|
this._refreshPending = true;
|
|
1173
1228
|
requestAnimationFrame(function () {
|
|
1174
|
-
|
|
1229
|
+
_this9._refreshPending = false;
|
|
1230
|
+
|
|
1175
1231
|
// Clear per-cycle caches so each component is measured/traversed once per paint
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1232
|
+
_this9._bboxCache.clear();
|
|
1233
|
+
_this9._componentListCache = null;
|
|
1234
|
+
|
|
1235
|
+
// Check if we need to refresh all viewports
|
|
1236
|
+
var refreshAll = _this9._pendingRefreshKeys.has('__ALL__');
|
|
1237
|
+
var keysToRefresh = new Set(_this9._pendingRefreshKeys);
|
|
1238
|
+
_this9._pendingRefreshKeys.clear();
|
|
1239
|
+
if (refreshAll) {
|
|
1240
|
+
// Refresh all viewports
|
|
1241
|
+
var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(_this9.viewports.values()),
|
|
1185
1242
|
_step;
|
|
1186
1243
|
try {
|
|
1187
1244
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1188
|
-
var
|
|
1189
|
-
if (
|
|
1190
|
-
|
|
1245
|
+
var viewport = _step.value;
|
|
1246
|
+
if (viewport.isReady) {
|
|
1247
|
+
_this9.renderComponents(viewport);
|
|
1191
1248
|
}
|
|
1192
1249
|
}
|
|
1193
1250
|
} catch (err) {
|
|
@@ -1195,6 +1252,23 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
1195
1252
|
} finally {
|
|
1196
1253
|
_iterator.f();
|
|
1197
1254
|
}
|
|
1255
|
+
} else {
|
|
1256
|
+
// Refresh only the specific viewports that were requested
|
|
1257
|
+
var _iterator2 = _rollupPluginBabelHelpers.createForOfIteratorHelper(keysToRefresh),
|
|
1258
|
+
_step2;
|
|
1259
|
+
try {
|
|
1260
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
1261
|
+
var viewportKey = _step2.value;
|
|
1262
|
+
var _viewport = _this9.viewports.get(viewportKey);
|
|
1263
|
+
if (_viewport && _viewport.isReady) {
|
|
1264
|
+
_this9.renderComponents(_viewport);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
} catch (err) {
|
|
1268
|
+
_iterator2.e(err);
|
|
1269
|
+
} finally {
|
|
1270
|
+
_iterator2.f();
|
|
1271
|
+
}
|
|
1198
1272
|
}
|
|
1199
1273
|
});
|
|
1200
1274
|
}
|
|
@@ -1215,20 +1289,20 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
1215
1289
|
}
|
|
1216
1290
|
|
|
1217
1291
|
// Dispose all viewport instances
|
|
1218
|
-
var
|
|
1219
|
-
|
|
1292
|
+
var _iterator3 = _rollupPluginBabelHelpers.createForOfIteratorHelper(this.viewports.entries()),
|
|
1293
|
+
_step3;
|
|
1220
1294
|
try {
|
|
1221
|
-
for (
|
|
1222
|
-
var
|
|
1223
|
-
key =
|
|
1224
|
-
viewport =
|
|
1295
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
1296
|
+
var _step3$value = _rollupPluginBabelHelpers.slicedToArray(_step3.value, 2),
|
|
1297
|
+
key = _step3$value[0],
|
|
1298
|
+
viewport = _step3$value[1];
|
|
1225
1299
|
console.log("\uD83D\uDDD1\uFE0F Disposing viewport: ".concat(key));
|
|
1226
1300
|
viewport.dispose();
|
|
1227
1301
|
}
|
|
1228
1302
|
} catch (err) {
|
|
1229
|
-
|
|
1303
|
+
_iterator3.e(err);
|
|
1230
1304
|
} finally {
|
|
1231
|
-
|
|
1305
|
+
_iterator3.f();
|
|
1232
1306
|
}
|
|
1233
1307
|
this.viewports.clear();
|
|
1234
1308
|
this.Konva = null;
|
|
@@ -119,7 +119,12 @@ function computeFilteredBoundingBox(object) {
|
|
|
119
119
|
|
|
120
120
|
// Build a Set for O(1) lookups
|
|
121
121
|
var excludeSet = new Set(excludeTypes);
|
|
122
|
-
|
|
122
|
+
|
|
123
|
+
// Force matrix updates to ensure world-space coordinates are accurate.
|
|
124
|
+
// Using force=true ensures matrices are updated even if matrixWorldNeedsUpdate is false,
|
|
125
|
+
// which can happen after positioning a model before the render loop runs.
|
|
126
|
+
object.updateMatrix();
|
|
127
|
+
object.updateMatrixWorld(true);
|
|
123
128
|
object.traverse(function (child) {
|
|
124
129
|
// Only process nodes with geometry (Mesh, SkinnedMesh, etc.)
|
|
125
130
|
if (!child.geometry) return;
|
|
@@ -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.13
|
|
35
35
|
* @updated 2025-10-22
|
|
36
36
|
*
|
|
37
37
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -561,6 +561,15 @@ var ModelManager = /*#__PURE__*/function () {
|
|
|
561
561
|
var jsonData = _ref2.jsonData,
|
|
562
562
|
glbModel = _ref2.glbModel;
|
|
563
563
|
if (!glbModel) return;
|
|
564
|
+
|
|
565
|
+
// CRITICAL: Force matrix updates before computing bbox.
|
|
566
|
+
// After loadLibraryModel positions the model, the world matrices may not be
|
|
567
|
+
// invalidated yet. computeFilteredBoundingBox uses updateWorldMatrix(false, true)
|
|
568
|
+
// which only updates if matrixWorldNeedsUpdate is true. Force the update here
|
|
569
|
+
// to ensure the bbox is computed with correct world-space coordinates.
|
|
570
|
+
glbModel.updateMatrix();
|
|
571
|
+
glbModel.updateMatrixWorld(true);
|
|
572
|
+
|
|
564
573
|
// Use filtered bbox (excludes connectors + io-devices) so it matches
|
|
565
574
|
// what pathfindingManager._enrichSceneDataWithBoundingBoxes produces
|
|
566
575
|
var filteredBox = computeFilteredBoundingBox(glbModel, ['io-device', 'connector']);
|