@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
|
@@ -99,6 +99,9 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
99
99
|
// stacking up independent renderComponents() runs
|
|
100
100
|
_this2._refreshPending = false;
|
|
101
101
|
|
|
102
|
+
// Set of viewport keys pending refresh (collects keys across multiple refresh() calls in same frame)
|
|
103
|
+
_this2._pendingRefreshKeys = new Set();
|
|
104
|
+
|
|
102
105
|
// Event listener reference for cleanup
|
|
103
106
|
_this2._objectTransformedListener = null;
|
|
104
107
|
console.log('🔲 Viewport2DManager initialized (multi-instance support)');
|
|
@@ -188,8 +191,10 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
188
191
|
viewport._instanceKey = key;
|
|
189
192
|
this.viewports.set(key, viewport);
|
|
190
193
|
|
|
191
|
-
// Initialize the stage for this viewport
|
|
192
|
-
|
|
194
|
+
// Initialize the stage for this viewport (waits for DOM layout to settle)
|
|
195
|
+
_context.n = 4;
|
|
196
|
+
return this.initializeStage(viewport);
|
|
197
|
+
case 4:
|
|
193
198
|
return _context.a(2, viewport.isReady);
|
|
194
199
|
}
|
|
195
200
|
}, _callee, this);
|
|
@@ -283,50 +288,67 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
283
288
|
/**
|
|
284
289
|
* Initialize Konva stage for a specific viewport instance
|
|
285
290
|
* @param {Viewport2DInstance} viewport - The viewport instance to initialize
|
|
291
|
+
* @returns {Promise<void>} Resolves when viewport is fully ready
|
|
286
292
|
*/
|
|
287
293
|
)
|
|
288
294
|
}, {
|
|
289
295
|
key: "initializeStage",
|
|
290
296
|
value: function initializeStage(viewport) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
var width = rect.width || 800;
|
|
299
|
-
var height = rect.height || 600;
|
|
300
|
-
console.log("\uD83D\uDCD0 Initializing Konva stage (".concat(viewport.viewType, "): ").concat(width, "x").concat(height));
|
|
301
|
-
|
|
302
|
-
// Create Konva stage for this viewport
|
|
303
|
-
viewport.stage = new this.Konva.Stage({
|
|
304
|
-
container: viewport.container,
|
|
305
|
-
width: width,
|
|
306
|
-
height: height
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
// Create separate layers for grid and components
|
|
310
|
-
viewport.gridLayer = new this.Konva.Layer();
|
|
311
|
-
viewport.componentLayer = new this.Konva.Layer();
|
|
312
|
-
|
|
313
|
-
// Add layers to stage in order (grid first, then components)
|
|
314
|
-
viewport.stage.add(viewport.gridLayer);
|
|
315
|
-
viewport.stage.add(viewport.componentLayer);
|
|
316
|
-
|
|
317
|
-
// Setup resize handling
|
|
318
|
-
this.setupResizeListener(viewport);
|
|
319
|
-
|
|
320
|
-
// Setup zoom and pan handlers
|
|
321
|
-
this.setupZoomAndPanHandlers(viewport);
|
|
297
|
+
var _this4 = this;
|
|
298
|
+
return new Promise(function (resolve) {
|
|
299
|
+
if (!_this4.Konva || !viewport.container) {
|
|
300
|
+
console.error('❌ Cannot initialize stage: Konva or container missing');
|
|
301
|
+
resolve();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
322
304
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
305
|
+
// Get container dimensions
|
|
306
|
+
var rect = viewport.container.getBoundingClientRect();
|
|
307
|
+
var width = rect.width || 800;
|
|
308
|
+
var height = rect.height || 600;
|
|
309
|
+
console.log("\uD83D\uDCD0 Initializing Konva stage (".concat(viewport.viewType, "): ").concat(width, "x").concat(height));
|
|
310
|
+
|
|
311
|
+
// Create Konva stage for this viewport
|
|
312
|
+
viewport.stage = new _this4.Konva.Stage({
|
|
313
|
+
container: viewport.container,
|
|
314
|
+
width: width,
|
|
315
|
+
height: height
|
|
316
|
+
});
|
|
326
317
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
318
|
+
// Create separate layers for grid and components
|
|
319
|
+
viewport.gridLayer = new _this4.Konva.Layer();
|
|
320
|
+
viewport.componentLayer = new _this4.Konva.Layer();
|
|
321
|
+
|
|
322
|
+
// Add layers to stage in order (grid first, then components)
|
|
323
|
+
viewport.stage.add(viewport.gridLayer);
|
|
324
|
+
viewport.stage.add(viewport.componentLayer);
|
|
325
|
+
|
|
326
|
+
// Setup resize handling
|
|
327
|
+
_this4.setupResizeListener(viewport);
|
|
328
|
+
|
|
329
|
+
// Setup zoom and pan handlers
|
|
330
|
+
_this4.setupZoomAndPanHandlers(viewport);
|
|
331
|
+
|
|
332
|
+
// Draw initial grid (lightweight, safe to do immediately)
|
|
333
|
+
_this4.drawGrid(viewport);
|
|
334
|
+
|
|
335
|
+
// Defer component rendering to next frame to ensure DOM layout is finalized.
|
|
336
|
+
// Without this, getBoundingClientRect() may return stale/zero dimensions
|
|
337
|
+
// if the container hasn't been fully laid out by CSS yet.
|
|
338
|
+
requestAnimationFrame(function () {
|
|
339
|
+
// Re-check container dimensions after layout settles
|
|
340
|
+
var finalRect = viewport.container.getBoundingClientRect();
|
|
341
|
+
if (finalRect.width > 0 && finalRect.height > 0) {
|
|
342
|
+
viewport.stage.width(finalRect.width);
|
|
343
|
+
viewport.stage.height(finalRect.height);
|
|
344
|
+
_this4.drawGrid(viewport);
|
|
345
|
+
}
|
|
346
|
+
_this4.renderComponents(viewport);
|
|
347
|
+
viewport.isReady = true;
|
|
348
|
+
console.log("\u2705 Viewport2DManager stage initialized (".concat(viewport.viewType, ")"));
|
|
349
|
+
resolve();
|
|
350
|
+
});
|
|
351
|
+
});
|
|
330
352
|
}
|
|
331
353
|
|
|
332
354
|
/**
|
|
@@ -336,12 +358,12 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
336
358
|
}, {
|
|
337
359
|
key: "setupResizeListener",
|
|
338
360
|
value: function setupResizeListener(viewport) {
|
|
339
|
-
var
|
|
361
|
+
var _this5 = this;
|
|
340
362
|
if (typeof window === 'undefined' || !window.ResizeObserver || !viewport.container) {
|
|
341
363
|
return;
|
|
342
364
|
}
|
|
343
365
|
viewport._resizeObserver = new ResizeObserver(function () {
|
|
344
|
-
|
|
366
|
+
_this5.resizeStage(viewport);
|
|
345
367
|
});
|
|
346
368
|
viewport._resizeObserver.observe(viewport.container);
|
|
347
369
|
}
|
|
@@ -376,6 +398,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
376
398
|
}, {
|
|
377
399
|
key: "setupZoomAndPanHandlers",
|
|
378
400
|
value: function setupZoomAndPanHandlers(viewport) {
|
|
401
|
+
var _this6 = this;
|
|
379
402
|
if (!viewport.stage) return;
|
|
380
403
|
|
|
381
404
|
// Mouse wheel zoom
|
|
@@ -401,6 +424,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
401
424
|
y: pointer.y - mousePointTo.y * clampedScale
|
|
402
425
|
};
|
|
403
426
|
viewport.stage.position(newPos);
|
|
427
|
+
_this6.drawGrid(viewport);
|
|
404
428
|
viewport.stage.batchDraw();
|
|
405
429
|
});
|
|
406
430
|
|
|
@@ -420,6 +444,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
420
444
|
viewport.stage.x(viewport.stage.x() + dx);
|
|
421
445
|
viewport.stage.y(viewport.stage.y() + dy);
|
|
422
446
|
viewport.lastPanPoint = pos;
|
|
447
|
+
_this6.drawGrid(viewport);
|
|
423
448
|
viewport.stage.batchDraw();
|
|
424
449
|
});
|
|
425
450
|
viewport.stage.on('mouseup', function () {
|
|
@@ -444,33 +469,40 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
444
469
|
var width = viewport.stage.width();
|
|
445
470
|
var height = viewport.stage.height();
|
|
446
471
|
var gridSize = viewport.PIXELS_PER_UNIT;
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
var
|
|
450
|
-
|
|
472
|
+
var stageX = viewport.stage.x();
|
|
473
|
+
var stageY = viewport.stage.y();
|
|
474
|
+
var scale = viewport.stage.scaleX();
|
|
475
|
+
|
|
476
|
+
// World origin sits at (width/2, height/2) in stage-local coordinates
|
|
477
|
+
var originX = width / 2;
|
|
478
|
+
var originY = height / 2;
|
|
479
|
+
|
|
480
|
+
// Compute the visible area in stage-local coordinates, with 1-cell padding
|
|
481
|
+
var visLeft = -stageX / scale - gridSize;
|
|
482
|
+
var visTop = -stageY / scale - gridSize;
|
|
483
|
+
var visRight = (width - stageX) / scale + gridSize;
|
|
484
|
+
var visBottom = (height - stageY) / scale + gridSize;
|
|
451
485
|
var gridGroup = new this.Konva.Group();
|
|
452
|
-
|
|
453
|
-
// Draw vertical lines centered at origin
|
|
454
|
-
var startX = centerX % gridSize - gridSize;
|
|
455
486
|
var gridColor = '#dddddd';
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
487
|
+
|
|
488
|
+
// Draw vertical lines — start at the first grid column left of the visible area
|
|
489
|
+
var firstX = Math.floor((visLeft - originX) / gridSize) * gridSize + originX;
|
|
490
|
+
for (var x = firstX; x <= visRight; x += gridSize) {
|
|
491
|
+
var isOriginLine = Math.abs(x - originX) < 0.5;
|
|
459
492
|
gridGroup.add(new this.Konva.Line({
|
|
460
|
-
points: [x,
|
|
493
|
+
points: [x, visTop, x, visBottom],
|
|
461
494
|
stroke: gridColor,
|
|
462
495
|
strokeWidth: isOriginLine ? 2 : 1,
|
|
463
496
|
listening: false
|
|
464
497
|
}));
|
|
465
498
|
}
|
|
466
499
|
|
|
467
|
-
// Draw horizontal lines
|
|
468
|
-
var
|
|
469
|
-
for (var y =
|
|
470
|
-
var
|
|
471
|
-
var _isOriginLine = _distFromCenter < 1;
|
|
500
|
+
// Draw horizontal lines — start at the first grid row above the visible area
|
|
501
|
+
var firstY = Math.floor((visTop - originY) / gridSize) * gridSize + originY;
|
|
502
|
+
for (var y = firstY; y <= visBottom; y += gridSize) {
|
|
503
|
+
var _isOriginLine = Math.abs(y - originY) < 0.5;
|
|
472
504
|
gridGroup.add(new this.Konva.Line({
|
|
473
|
-
points: [
|
|
505
|
+
points: [visLeft, y, visRight, y],
|
|
474
506
|
stroke: gridColor,
|
|
475
507
|
strokeWidth: _isOriginLine ? 2 : 1,
|
|
476
508
|
listening: false
|
|
@@ -480,14 +512,14 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
480
512
|
// Draw center crosshair at world origin
|
|
481
513
|
var crosshairSize = gridSize;
|
|
482
514
|
gridGroup.add(new this.Konva.Line({
|
|
483
|
-
points: [
|
|
515
|
+
points: [originX, originY - crosshairSize, originX, originY + crosshairSize],
|
|
484
516
|
stroke: '#333',
|
|
485
517
|
strokeWidth: 1,
|
|
486
518
|
listening: false,
|
|
487
519
|
dash: [5, 5]
|
|
488
520
|
}));
|
|
489
521
|
gridGroup.add(new this.Konva.Line({
|
|
490
|
-
points: [
|
|
522
|
+
points: [originX - crosshairSize, originY, originX + crosshairSize, originY],
|
|
491
523
|
stroke: '#333',
|
|
492
524
|
strokeWidth: 1,
|
|
493
525
|
listening: false,
|
|
@@ -504,7 +536,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
504
536
|
}, {
|
|
505
537
|
key: "renderComponents",
|
|
506
538
|
value: function renderComponents(viewport) {
|
|
507
|
-
var
|
|
539
|
+
var _this7 = this;
|
|
508
540
|
if (!viewport.componentLayer || !viewport.stage || !this.sceneViewer) return;
|
|
509
541
|
viewport.componentLayer.destroyChildren();
|
|
510
542
|
|
|
@@ -515,19 +547,18 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
515
547
|
return;
|
|
516
548
|
}
|
|
517
549
|
|
|
518
|
-
//
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
viewport._lastComponentCount = components.length;
|
|
522
|
-
}
|
|
550
|
+
// Track render count for debugging
|
|
551
|
+
if (viewport._renderCount === undefined) viewport._renderCount = 0;
|
|
552
|
+
viewport._renderCount++;
|
|
523
553
|
var width = viewport.stage.width();
|
|
524
554
|
var height = viewport.stage.height();
|
|
525
555
|
var centerX = width / 2;
|
|
526
556
|
var centerY = height / 2;
|
|
527
557
|
var scale = viewport.PIXELS_PER_UNIT;
|
|
558
|
+
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, ")"));
|
|
528
559
|
components.forEach(function (component) {
|
|
529
560
|
try {
|
|
530
|
-
|
|
561
|
+
_this7.renderComponent(viewport, component, centerX, centerY, scale);
|
|
531
562
|
} catch (err) {
|
|
532
563
|
console.warn('⚠️ Error rendering component in 2D:', component.name, err);
|
|
533
564
|
}
|
|
@@ -558,6 +589,11 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
558
589
|
var screenX = centerX + posX * scale;
|
|
559
590
|
var screenY = centerY - posY * scale; // Flip Y for screen coords
|
|
560
591
|
|
|
592
|
+
// Debug: Log ALL component positions on first render only
|
|
593
|
+
if (viewport._renderCount === 1) {
|
|
594
|
+
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)));
|
|
595
|
+
}
|
|
596
|
+
|
|
561
597
|
// Generate unique color for this component
|
|
562
598
|
var colors = this.generateComponentColor(component.id);
|
|
563
599
|
|
|
@@ -587,18 +623,19 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
587
623
|
draggable: false
|
|
588
624
|
});
|
|
589
625
|
|
|
590
|
-
// Add label
|
|
626
|
+
// Add label (hidden by default; shown on hover)
|
|
591
627
|
var label = new this.Konva.Text({
|
|
592
628
|
x: -rectWidth / 2,
|
|
593
629
|
y: -rectHeight / 2 - 20,
|
|
594
630
|
text: component.name || 'Component',
|
|
595
631
|
fontSize: 12,
|
|
596
632
|
fill: '#333',
|
|
597
|
-
listening: false
|
|
633
|
+
listening: false,
|
|
634
|
+
visible: false
|
|
598
635
|
});
|
|
599
636
|
|
|
600
637
|
// Add mouse event handlers
|
|
601
|
-
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter);
|
|
638
|
+
this.addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter, label);
|
|
602
639
|
componentGroup.add(rect);
|
|
603
640
|
componentGroup.add(label);
|
|
604
641
|
viewport.componentLayer.add(componentGroup);
|
|
@@ -635,7 +672,14 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
635
672
|
if (this._bboxCache.has(object.uuid)) {
|
|
636
673
|
return this._bboxCache.get(object.uuid);
|
|
637
674
|
}
|
|
638
|
-
|
|
675
|
+
|
|
676
|
+
// Force matrix updates before computing bbox to ensure world-space accuracy
|
|
677
|
+
object.updateMatrix();
|
|
678
|
+
object.updateMatrixWorld(true);
|
|
679
|
+
|
|
680
|
+
// Exclude io-devices and connectors to match the stored worldBoundingBox
|
|
681
|
+
// computed in modelManager.replaceWithGLBModels()
|
|
682
|
+
var box = computeFilteredBoundingBox(object, ['io-device', 'connector']);
|
|
639
683
|
var result;
|
|
640
684
|
if (box.isEmpty()) {
|
|
641
685
|
// Object has no geometry; fall back to a point at world position
|
|
@@ -765,8 +809,8 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
765
809
|
*/
|
|
766
810
|
}, {
|
|
767
811
|
key: "addComponentInteractions",
|
|
768
|
-
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter) {
|
|
769
|
-
var
|
|
812
|
+
value: function addComponentInteractions(viewport, rect, componentGroup, component, worldWidth, worldDepth, worldHeight, bboxCenter, label) {
|
|
813
|
+
var _this8 = this;
|
|
770
814
|
if (!this.Konva) return;
|
|
771
815
|
var colors = this.generateComponentColor(component.id);
|
|
772
816
|
|
|
@@ -777,6 +821,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
777
821
|
rect.stroke('#007bff');
|
|
778
822
|
rect.strokeWidth(3);
|
|
779
823
|
viewport.stage.container().style.cursor = 'grab';
|
|
824
|
+
if (label) label.visible(true);
|
|
780
825
|
viewport.componentLayer.batchDraw();
|
|
781
826
|
}
|
|
782
827
|
});
|
|
@@ -786,6 +831,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
786
831
|
rect.stroke(colors.stroke);
|
|
787
832
|
rect.strokeWidth(2);
|
|
788
833
|
viewport.stage.container().style.cursor = 'default';
|
|
834
|
+
if (label) label.visible(false);
|
|
789
835
|
viewport.componentLayer.batchDraw();
|
|
790
836
|
}
|
|
791
837
|
});
|
|
@@ -793,12 +839,12 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
793
839
|
// CLICK EVENT
|
|
794
840
|
rect.on('click', function () {
|
|
795
841
|
if (!viewport.isDragging) {
|
|
796
|
-
var
|
|
842
|
+
var _this8$sceneViewer;
|
|
797
843
|
console.log("\uD83C\uDFAF Component clicked: ".concat(component.name));
|
|
798
844
|
|
|
799
845
|
// Use centralPlant API to select component
|
|
800
|
-
if ((
|
|
801
|
-
|
|
846
|
+
if ((_this8$sceneViewer = _this8.sceneViewer) !== null && _this8$sceneViewer !== void 0 && _this8$sceneViewer.centralPlant && component.uuid) {
|
|
847
|
+
_this8.sceneViewer.centralPlant.selectComponent(component.uuid);
|
|
802
848
|
}
|
|
803
849
|
}
|
|
804
850
|
});
|
|
@@ -828,7 +874,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
828
874
|
var worldOriginY = stageHeight / 2;
|
|
829
875
|
|
|
830
876
|
// Snap to grid
|
|
831
|
-
var snappedPos =
|
|
877
|
+
var snappedPos = _this8.snapScreenToGrid(viewport, currentPos.x, currentPos.y, scale, worldOriginX, worldOriginY);
|
|
832
878
|
componentGroup.position(snappedPos);
|
|
833
879
|
viewport.componentLayer.batchDraw();
|
|
834
880
|
});
|
|
@@ -836,7 +882,7 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
836
882
|
// DRAG END
|
|
837
883
|
componentGroup.on('dragend', function () {
|
|
838
884
|
setTimeout(function () {
|
|
839
|
-
var
|
|
885
|
+
var _this8$sceneViewer2;
|
|
840
886
|
viewport.isDragging = false;
|
|
841
887
|
var finalPos = componentGroup.position();
|
|
842
888
|
var stageWidth = viewport.stage.width();
|
|
@@ -846,17 +892,17 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
846
892
|
var worldOriginY = stageHeight / 2;
|
|
847
893
|
|
|
848
894
|
// Convert screen to world coordinates
|
|
849
|
-
var worldCoords =
|
|
895
|
+
var worldCoords = _this8.screenToWorldCoords(viewport, finalPos.x, finalPos.y, scale, worldOriginX, worldOriginY);
|
|
850
896
|
|
|
851
897
|
// Calculate new position: delta from old bbox center to new bbox center
|
|
852
898
|
var currentPos = component.position;
|
|
853
|
-
var newPosition =
|
|
899
|
+
var newPosition = _this8.worldCoordsToObjectPosition(viewport, worldCoords, currentPos, bboxCenter);
|
|
854
900
|
|
|
855
901
|
// Apply translation via centralPlant API
|
|
856
902
|
var deltaX = newPosition.x - currentPos.x;
|
|
857
903
|
var deltaY = newPosition.y - currentPos.y;
|
|
858
904
|
var deltaZ = newPosition.z - currentPos.z;
|
|
859
|
-
if ((
|
|
905
|
+
if ((_this8$sceneViewer2 = _this8.sceneViewer) !== null && _this8$sceneViewer2 !== void 0 && _this8$sceneViewer2.centralPlant && component.uuid) {
|
|
860
906
|
var success = true;
|
|
861
907
|
|
|
862
908
|
// Suppress per-axis path updates so the pathfinder only runs once,
|
|
@@ -864,32 +910,32 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
864
910
|
// Running updatePaths() after each individual axis (the default
|
|
865
911
|
// translateComponent behaviour) produces intermediate wrong results on
|
|
866
912
|
// the first drag because no cached fingerprint exists yet to skip them.
|
|
867
|
-
var wasAutoUpdate =
|
|
868
|
-
|
|
913
|
+
var wasAutoUpdate = _this8.sceneViewer.shouldUpdatePaths;
|
|
914
|
+
_this8.sceneViewer.shouldUpdatePaths = false;
|
|
869
915
|
try {
|
|
870
916
|
if (Math.abs(deltaX) > 0.01) {
|
|
871
|
-
success = success &&
|
|
917
|
+
success = success && _this8.sceneViewer.centralPlant.translate(component.uuid, 'x', deltaX);
|
|
872
918
|
}
|
|
873
919
|
if (Math.abs(deltaY) > 0.01) {
|
|
874
|
-
success = success &&
|
|
920
|
+
success = success && _this8.sceneViewer.centralPlant.translate(component.uuid, 'y', deltaY);
|
|
875
921
|
}
|
|
876
922
|
if (Math.abs(deltaZ) > 0.01) {
|
|
877
|
-
success = success &&
|
|
923
|
+
success = success && _this8.sceneViewer.centralPlant.translate(component.uuid, 'z', deltaZ);
|
|
878
924
|
}
|
|
879
925
|
} finally {
|
|
880
|
-
|
|
926
|
+
_this8.sceneViewer.shouldUpdatePaths = wasAutoUpdate;
|
|
881
927
|
}
|
|
882
|
-
if (!success &&
|
|
928
|
+
if (!success && _this8.dragStartPosition) {
|
|
883
929
|
console.warn('⚠️ Failed to translate component, reverting position');
|
|
884
|
-
componentGroup.position(
|
|
930
|
+
componentGroup.position(_this8.dragStartPosition);
|
|
885
931
|
} else {
|
|
886
932
|
console.log("\u2705 Component ".concat(component.name, " translated successfully in 2D viewport"));
|
|
887
933
|
|
|
888
934
|
// Single path update with the final combined position
|
|
889
|
-
if (wasAutoUpdate &&
|
|
935
|
+
if (wasAutoUpdate && _this8.sceneViewer) {
|
|
890
936
|
console.log('🔄 Auto-updating paths after 2D viewport translation...');
|
|
891
937
|
try {
|
|
892
|
-
|
|
938
|
+
_this8.sceneViewer.updatePaths();
|
|
893
939
|
console.log('✅ Paths auto-updated successfully from 2D viewport');
|
|
894
940
|
} catch (error) {
|
|
895
941
|
console.error('❌ Error auto-updating paths from 2D viewport:', error);
|
|
@@ -1142,28 +1188,39 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
1142
1188
|
}, {
|
|
1143
1189
|
key: "refresh",
|
|
1144
1190
|
value: function refresh() {
|
|
1145
|
-
var
|
|
1191
|
+
var _this9 = this;
|
|
1146
1192
|
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
1193
|
+
// Collect viewport keys to refresh; null means "all viewports"
|
|
1194
|
+
if (key) {
|
|
1195
|
+
this._pendingRefreshKeys.add(key);
|
|
1196
|
+
} else {
|
|
1197
|
+
// null key means refresh all — mark with special sentinel
|
|
1198
|
+
this._pendingRefreshKeys.add('__ALL__');
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// If already scheduled, the rAF callback will process our newly-added key
|
|
1147
1202
|
if (this._refreshPending) return;
|
|
1148
1203
|
this._refreshPending = true;
|
|
1149
1204
|
requestAnimationFrame(function () {
|
|
1150
|
-
|
|
1205
|
+
_this9._refreshPending = false;
|
|
1206
|
+
|
|
1151
1207
|
// Clear per-cycle caches so each component is measured/traversed once per paint
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1208
|
+
_this9._bboxCache.clear();
|
|
1209
|
+
_this9._componentListCache = null;
|
|
1210
|
+
|
|
1211
|
+
// Check if we need to refresh all viewports
|
|
1212
|
+
var refreshAll = _this9._pendingRefreshKeys.has('__ALL__');
|
|
1213
|
+
var keysToRefresh = new Set(_this9._pendingRefreshKeys);
|
|
1214
|
+
_this9._pendingRefreshKeys.clear();
|
|
1215
|
+
if (refreshAll) {
|
|
1216
|
+
// Refresh all viewports
|
|
1217
|
+
var _iterator = _createForOfIteratorHelper(_this9.viewports.values()),
|
|
1161
1218
|
_step;
|
|
1162
1219
|
try {
|
|
1163
1220
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1164
|
-
var
|
|
1165
|
-
if (
|
|
1166
|
-
|
|
1221
|
+
var viewport = _step.value;
|
|
1222
|
+
if (viewport.isReady) {
|
|
1223
|
+
_this9.renderComponents(viewport);
|
|
1167
1224
|
}
|
|
1168
1225
|
}
|
|
1169
1226
|
} catch (err) {
|
|
@@ -1171,6 +1228,23 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
1171
1228
|
} finally {
|
|
1172
1229
|
_iterator.f();
|
|
1173
1230
|
}
|
|
1231
|
+
} else {
|
|
1232
|
+
// Refresh only the specific viewports that were requested
|
|
1233
|
+
var _iterator2 = _createForOfIteratorHelper(keysToRefresh),
|
|
1234
|
+
_step2;
|
|
1235
|
+
try {
|
|
1236
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
1237
|
+
var viewportKey = _step2.value;
|
|
1238
|
+
var _viewport = _this9.viewports.get(viewportKey);
|
|
1239
|
+
if (_viewport && _viewport.isReady) {
|
|
1240
|
+
_this9.renderComponents(_viewport);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
} catch (err) {
|
|
1244
|
+
_iterator2.e(err);
|
|
1245
|
+
} finally {
|
|
1246
|
+
_iterator2.f();
|
|
1247
|
+
}
|
|
1174
1248
|
}
|
|
1175
1249
|
});
|
|
1176
1250
|
}
|
|
@@ -1191,20 +1265,20 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
1191
1265
|
}
|
|
1192
1266
|
|
|
1193
1267
|
// Dispose all viewport instances
|
|
1194
|
-
var
|
|
1195
|
-
|
|
1268
|
+
var _iterator3 = _createForOfIteratorHelper(this.viewports.entries()),
|
|
1269
|
+
_step3;
|
|
1196
1270
|
try {
|
|
1197
|
-
for (
|
|
1198
|
-
var
|
|
1199
|
-
key =
|
|
1200
|
-
viewport =
|
|
1271
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
1272
|
+
var _step3$value = _slicedToArray(_step3.value, 2),
|
|
1273
|
+
key = _step3$value[0],
|
|
1274
|
+
viewport = _step3$value[1];
|
|
1201
1275
|
console.log("\uD83D\uDDD1\uFE0F Disposing viewport: ".concat(key));
|
|
1202
1276
|
viewport.dispose();
|
|
1203
1277
|
}
|
|
1204
1278
|
} catch (err) {
|
|
1205
|
-
|
|
1279
|
+
_iterator3.e(err);
|
|
1206
1280
|
} finally {
|
|
1207
|
-
|
|
1281
|
+
_iterator3.f();
|
|
1208
1282
|
}
|
|
1209
1283
|
this.viewports.clear();
|
|
1210
1284
|
this.Konva = null;
|
|
@@ -95,7 +95,12 @@ function computeFilteredBoundingBox(object) {
|
|
|
95
95
|
|
|
96
96
|
// Build a Set for O(1) lookups
|
|
97
97
|
var excludeSet = new Set(excludeTypes);
|
|
98
|
-
|
|
98
|
+
|
|
99
|
+
// Force matrix updates to ensure world-space coordinates are accurate.
|
|
100
|
+
// Using force=true ensures matrices are updated even if matrixWorldNeedsUpdate is false,
|
|
101
|
+
// which can happen after positioning a model before the render loop runs.
|
|
102
|
+
object.updateMatrix();
|
|
103
|
+
object.updateMatrixWorld(true);
|
|
99
104
|
object.traverse(function (child) {
|
|
100
105
|
// Only process nodes with geometry (Mesh, SkinnedMesh, etc.)
|
|
101
106
|
if (!child.geometry) return;
|