@mindexec/cli 0.2.218 → 0.2.220

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.
Files changed (23) hide show
  1. package/package.json +1 -1
  2. package/scripts/remote-fleet-render-smoke.mjs +11 -0
  3. package/wwwroot/_content/MindExecution.Shared/css/mind-map-overrides.css +36 -6
  4. package/wwwroot/_content/MindExecution.Shared/js/background-themes.js +28 -113
  5. package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +2157 -104
  6. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +399 -96
  7. package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +121 -49
  8. package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +77 -3
  9. package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +83 -14
  10. package/wwwroot/_content/MindExecution.Shared/js/mind-map-text-overlay-v2.js +5 -0
  11. package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +2 -2
  12. package/wwwroot/_framework/{MindExecution.Core.21gc0645uz.dll → MindExecution.Core.xsad4wu36e.dll} +0 -0
  13. package/wwwroot/_framework/{MindExecution.Plugins.Admin.29mytzdaun.dll → MindExecution.Plugins.Admin.m5d94977um.dll} +0 -0
  14. package/wwwroot/_framework/{MindExecution.Plugins.Business.asckvekct8.dll → MindExecution.Plugins.Business.ntqdn1hta3.dll} +0 -0
  15. package/wwwroot/_framework/{MindExecution.Plugins.Concept.u9kzsgf64o.dll → MindExecution.Plugins.Concept.mqiyx4db4r.dll} +0 -0
  16. package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.kibqg6rvqh.dll → MindExecution.Plugins.PlanMaster.fnortumnuu.dll} +0 -0
  17. package/wwwroot/_framework/{MindExecution.Plugins.YouTube.089r64n2hv.dll → MindExecution.Plugins.YouTube.86osu6wpgh.dll} +0 -0
  18. package/wwwroot/_framework/{MindExecution.Shared.tlbhl3vzry.dll → MindExecution.Shared.wg2otcw4bv.dll} +0 -0
  19. package/wwwroot/_framework/{MindExecution.Web.7axuoygrwi.dll → MindExecution.Web.gfio3kfxrd.dll} +0 -0
  20. package/wwwroot/_framework/blazor.boot.json +17 -17
  21. package/wwwroot/index.html +3 -3
  22. package/wwwroot/service-worker-assets.js +28 -28
  23. package/wwwroot/service-worker.js +1 -1
@@ -4,6 +4,7 @@ window.MindMapInteractions = (function () {
4
4
  const CTRL_WHEEL_SCROLL_EDGE_EPSILON = 2;
5
5
  const PAN_LIVE_REFRESH_FORCE_FRAMES = 2;
6
6
  const MOTION_DOM_FANOUT_DELAY_MS = 180;
7
+ const MOTION_DOM_FANOUT_ENABLED = false;
7
8
  const MOTION_WILL_CHANGE_ENABLE_DELAY_MS = 240;
8
9
  const PRIMARY_CLICK_DELAY_MS = 280;
9
10
  const BACKGROUND_PRIMARY_CLICK_DELAY_MS = 320;
@@ -25,11 +26,14 @@ window.MindMapInteractions = (function () {
25
26
 
26
27
  function isBrowserSelectionLocked() {
27
28
  const body = document?.body;
29
+ const css3dWrapper = document?.getElementById?.('css3d-dom-wrapper');
28
30
  return browserSelectionLockReasons.size > 0 ||
29
31
  body?.classList?.contains?.(BROWSER_SELECTION_LOCK_CLASS) === true ||
30
32
  body?.classList?.contains?.('is-node-dragging') === true ||
31
33
  body?.classList?.contains?.('is-panning') === true ||
32
- body?.classList?.contains?.('is-zooming') === true;
34
+ body?.classList?.contains?.('is-zooming') === true ||
35
+ css3dWrapper?.classList?.contains?.('is-panning') === true ||
36
+ css3dWrapper?.classList?.contains?.('is-zooming') === true;
33
37
  }
34
38
 
35
39
  function handleBrowserSelectStart(event) {
@@ -99,18 +103,24 @@ window.MindMapInteractions = (function () {
99
103
  if (!module || typeof document === 'undefined' || !document.body) {
100
104
  return;
101
105
  }
106
+ if (MOTION_DOM_FANOUT_ENABLED !== true) {
107
+ clearZoomMotionChrome(module);
108
+ return;
109
+ }
102
110
 
103
111
  clearModuleTimer(module, '_zoomMotionChromeTimer');
104
112
  module._zoomMotionChromeTimer = setTimeout(() => {
105
113
  module._zoomMotionChromeTimer = null;
114
+ const targetElement = module?.cssRenderer?.domElement || document.body;
106
115
  if (module.isZooming === true) {
107
- document.body.classList.add('is-zooming');
116
+ targetElement.classList.add('is-zooming');
108
117
  }
109
118
  }, MOTION_DOM_FANOUT_DELAY_MS);
110
119
  }
111
120
 
112
121
  function clearZoomMotionChrome(module) {
113
122
  clearModuleTimer(module, '_zoomMotionChromeTimer');
123
+ module?.cssRenderer?.domElement?.classList?.remove?.('is-zooming');
114
124
  document?.body?.classList?.remove?.('is-zooming');
115
125
  }
116
126
 
@@ -123,6 +133,10 @@ window.MindMapInteractions = (function () {
123
133
  if (!module || !element) {
124
134
  return;
125
135
  }
136
+ if (MOTION_DOM_FANOUT_ENABLED !== true) {
137
+ clearPanMotionChrome(module);
138
+ return;
139
+ }
126
140
 
127
141
  clearModuleTimer(module, '_panMotionChromeTimer');
128
142
  module._panMotionChromeTimer = setTimeout(() => {
@@ -144,6 +158,10 @@ window.MindMapInteractions = (function () {
144
158
  if (!module || !window.MindMapCss3DManager?.setWillChange) {
145
159
  return;
146
160
  }
161
+ if (module.renderDebugFlags?.enableCss3dWillChange !== true) {
162
+ clearMotionWillChangeEnable(module, { disableIfIdle: true });
163
+ return;
164
+ }
147
165
 
148
166
  clearModuleTimer(module, '_motionWillChangeEnableTimer');
149
167
  module._motionWillChangeEnableTimer = setTimeout(() => {
@@ -160,6 +178,7 @@ window.MindMapInteractions = (function () {
160
178
  if (options.disableIfIdle === true &&
161
179
  module?.isZooming !== true &&
162
180
  module?.isPanning !== true &&
181
+ module?.renderDebugFlags?.enableCss3dWillChange === true &&
163
182
  window.MindMapCss3DManager?.setWillChange) {
164
183
  window.MindMapCss3DManager.setWillChange(false, module);
165
184
  }
@@ -267,10 +286,29 @@ window.MindMapInteractions = (function () {
267
286
 
268
287
  function getViewportMetrics(module) {
269
288
  ensureActiveContainer(module);
270
- const width = Math.max(0, Number(module?.container?.clientWidth || 0));
271
- const height = Math.max(0, Number(module?.container?.clientHeight || 0));
289
+ const rect = module?.container?.getBoundingClientRect?.() || null;
290
+ const width = Math.max(0, Number(rect?.width || module?.container?.clientWidth || 0));
291
+ const height = Math.max(0, Number(rect?.height || module?.container?.clientHeight || 0));
292
+ const left = Number(rect?.left || 0);
293
+ const top = Number(rect?.top || 0);
272
294
  const dpr = Math.max(1, Number(window.devicePixelRatio || 1));
273
- return { width, height, dpr };
295
+ return { width, height, left, top, dpr };
296
+ }
297
+
298
+ function getCachedViewportMetrics(module) {
299
+ const width = Math.max(0, Number(module?._lastViewportWidth || 0));
300
+ const height = Math.max(0, Number(module?._lastViewportHeight || 0));
301
+ if (width > 0 && height > 0) {
302
+ return {
303
+ width,
304
+ height,
305
+ left: Number(module?._lastViewportLeft || 0),
306
+ top: Number(module?._lastViewportTop || 0),
307
+ dpr: Math.max(1, Number(module?._lastViewportDpr || window.devicePixelRatio || 1))
308
+ };
309
+ }
310
+
311
+ return getViewportMetrics(module);
274
312
  }
275
313
 
276
314
  function haveViewportMetricsChanged(module, metrics, force = false) {
@@ -280,9 +318,13 @@ window.MindMapInteractions = (function () {
280
318
 
281
319
  const lastWidth = Number(module?._lastViewportWidth || 0);
282
320
  const lastHeight = Number(module?._lastViewportHeight || 0);
321
+ const lastLeft = Number(module?._lastViewportLeft || 0);
322
+ const lastTop = Number(module?._lastViewportTop || 0);
283
323
  const lastDpr = Number(module?._lastViewportDpr || 0);
284
324
  return Math.abs(metrics.width - lastWidth) > 1 ||
285
325
  Math.abs(metrics.height - lastHeight) > 1 ||
326
+ Math.abs(metrics.left - lastLeft) > 1 ||
327
+ Math.abs(metrics.top - lastTop) > 1 ||
286
328
  Math.abs(metrics.dpr - lastDpr) > 0.02;
287
329
  }
288
330
 
@@ -293,6 +335,8 @@ window.MindMapInteractions = (function () {
293
335
 
294
336
  module._lastViewportWidth = metrics.width;
295
337
  module._lastViewportHeight = metrics.height;
338
+ module._lastViewportLeft = metrics.left;
339
+ module._lastViewportTop = metrics.top;
296
340
  module._lastViewportDpr = metrics.dpr;
297
341
  }
298
342
 
@@ -545,6 +589,17 @@ window.MindMapInteractions = (function () {
545
589
  Number(module._panLiveRefreshForceFrames || 0),
546
590
  PAN_LIVE_REFRESH_FORCE_FRAMES
547
591
  );
592
+ module._cameraNavigationForceFrames = Math.max(
593
+ Number(module._cameraNavigationForceFrames || 0),
594
+ PAN_LIVE_REFRESH_FORCE_FRAMES
595
+ );
596
+ wakeCameraNavigationAnimation(module, 'pan-input');
597
+ }
598
+
599
+ function wakeCameraNavigationAnimation(module, reason = 'camera-navigation-input') {
600
+ if (module && typeof module.requestAnimationWake === 'function') {
601
+ module.requestAnimationWake(reason);
602
+ }
548
603
  }
549
604
 
550
605
  function isEditableElement(element) {
@@ -1409,30 +1464,36 @@ window.MindMapInteractions = (function () {
1409
1464
  // ▲▲▲ [New] Scrollbar-drag helper functions ▲▲▲
1410
1465
 
1411
1466
  // ▼▼▼ [New] Centralized Pointer Update Helper ▼▼▼
1412
- function updatePointer(module, e) {
1413
- if (!module) return;
1414
- ensureActiveContainer(module);
1415
-
1416
- const rect = module.container?.getBoundingClientRect?.() ||
1417
- module.cssRenderer?.domElement?.getBoundingClientRect?.();
1418
- if (!rect || rect.width <= 0 || rect.height <= 0) return;
1419
-
1420
- const x = (e.clientX - rect.left) / rect.width;
1421
- const y = (e.clientY - rect.top) / rect.height;
1422
- module.pointer.x = (x * 2) - 1;
1423
- module.pointer.y = -((y * 2) - 1);
1424
- }
1467
+ function setPointerFromClientPosition(module, clientX, clientY) {
1468
+ if (!module?.pointer) return false;
1469
+
1470
+ const metrics = getCachedViewportMetrics(module);
1471
+ if (!metrics || metrics.width <= 0 || metrics.height <= 0) {
1472
+ return false;
1473
+ }
1474
+
1475
+ const x = (Number(clientX || 0) - Number(metrics.left || 0)) / metrics.width;
1476
+ const y = (Number(clientY || 0) - Number(metrics.top || 0)) / metrics.height;
1477
+ module.pointer.x = (x * 2) - 1;
1478
+ module.pointer.y = -((y * 2) - 1);
1479
+ return true;
1480
+ }
1481
+
1482
+ function updatePointer(module, e) {
1483
+ if (!module) return;
1484
+ setPointerFromClientPosition(module, e?.clientX, e?.clientY);
1485
+ }
1425
1486
  // ▲▲▲ [New] ▲▲▲
1426
1487
 
1427
1488
  // ▼▼▼ [New] World Point Conversion Helper (Screen creation fix) ▼▼▼
1428
1489
  function getWorldPoint(module, mouseX, mouseY) {
1429
1490
  if (!module.camera || !module.raycaster || !module.plane) return null;
1430
1491
 
1431
- const rect = module.container?.getBoundingClientRect?.();
1432
- const width = rect?.width || module.container?.clientWidth || 1;
1433
- const height = rect?.height || module.container?.clientHeight || 1;
1434
- const localX = rect ? (mouseX - rect.left) : mouseX;
1435
- const localY = rect ? (mouseY - rect.top) : mouseY;
1492
+ const metrics = getCachedViewportMetrics(module);
1493
+ const width = Math.max(1, Number(metrics.width || 0));
1494
+ const height = Math.max(1, Number(metrics.height || 0));
1495
+ const localX = Number(mouseX || 0) - Number(metrics.left || 0);
1496
+ const localY = Number(mouseY || 0) - Number(metrics.top || 0);
1436
1497
 
1437
1498
  const vec = new THREE.Vector2(
1438
1499
  (localX / width) * 2 - 1,
@@ -1855,8 +1916,9 @@ window.MindMapInteractions = (function () {
1855
1916
  vec.project(module.camera);
1856
1917
 
1857
1918
  // Convert from NDC (-1 to +1) to screen pixels
1858
- const x = (vec.x + 1) * module.container.clientWidth / 2;
1859
- const y = (-vec.y + 1) * module.container.clientHeight / 2;
1919
+ const metrics = getCachedViewportMetrics(module);
1920
+ const x = (vec.x + 1) * Math.max(1, Number(metrics.width || 0)) / 2;
1921
+ const y = (-vec.y + 1) * Math.max(1, Number(metrics.height || 0)) / 2;
1860
1922
 
1861
1923
  return { x, y };
1862
1924
  }
@@ -1868,8 +1930,7 @@ window.MindMapInteractions = (function () {
1868
1930
  if (!module.worldStartPos || !module.lastMouseClientX || !module.lastMouseClientY) return;
1869
1931
 
1870
1932
  // Calculate current world position of mouse cursor
1871
- module.pointer.x = (module.lastMouseClientX / module.container.clientWidth) * 2 - 1;
1872
- module.pointer.y = -(module.lastMouseClientY / module.container.clientHeight) * 2 + 1;
1933
+ setPointerFromClientPosition(module, module.lastMouseClientX, module.lastMouseClientY);
1873
1934
  module.raycaster.setFromCamera(module.pointer, module.camera);
1874
1935
 
1875
1936
  const worldEndPos = new THREE.Vector3();
@@ -4763,8 +4824,7 @@ window.MindMapInteractions = (function () {
4763
4824
  module.lastMouseClientY = e.clientY;
4764
4825
 
4765
4826
  // Get current mouse world position
4766
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
4767
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
4827
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
4768
4828
  module.raycaster.setFromCamera(module.pointer, module.camera);
4769
4829
 
4770
4830
  const worldEndPos = new THREE.Vector3();
@@ -4807,8 +4867,7 @@ window.MindMapInteractions = (function () {
4807
4867
  }
4808
4868
 
4809
4869
  if (module.wasDragged) {
4810
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
4811
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
4870
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
4812
4871
  module.raycaster.setFromCamera(module.pointer, module.camera);
4813
4872
  if (module.raycaster.ray.intersectPlane(module.plane, module.intersectPoint)) {
4814
4873
  const newPos = _tmpDragPos.copy(module.intersectPoint).sub(module.dragOffset);
@@ -4866,8 +4925,7 @@ window.MindMapInteractions = (function () {
4866
4925
 
4867
4926
  if (module.wasDragged) {
4868
4927
  const t0 = performance.now();
4869
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
4870
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
4928
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
4871
4929
  module.raycaster.setFromCamera(module.pointer, module.camera);
4872
4930
  const t1 = performance.now();
4873
4931
 
@@ -5040,8 +5098,7 @@ window.MindMapInteractions = (function () {
5040
5098
  module.selectionRectElement.style.display = 'none';
5041
5099
  }
5042
5100
  if (module.worldStartPos) {
5043
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
5044
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
5101
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
5045
5102
  module.raycaster.setFromCamera(module.pointer, module.camera);
5046
5103
 
5047
5104
  const worldEndPos = new THREE.Vector3();
@@ -6173,12 +6230,13 @@ window.MindMapInteractions = (function () {
6173
6230
  const panFactor = TRACKPAD_PAN_SENSITIVITY * module.camera.position.z;
6174
6231
  module.targetX += normalizedDeltaX * panFactor;
6175
6232
  module.targetY -= normalizedDeltaY * panFactor;
6176
- module._lastPanInputAt = performance.now();
6233
+ const panInputAt = performance.now();
6234
+ module._lastPanInputAt = panInputAt;
6177
6235
  module._forceUpdateFrames = Math.max(module._forceUpdateFrames || 0, 2);
6178
6236
  module._cameraNavigationForceFrames = Math.max(module._cameraNavigationForceFrames || 0, 2);
6179
- module._deferPassiveOverlayRefresh = false;
6180
- module._overlayDirty = true;
6181
- window.MindMapTextOverlayV2?.invalidateView?.(module);
6237
+ module._deferPassiveOverlayRefresh = true;
6238
+ module._cameraNavigationOverlayInputTime = panInputAt;
6239
+ wakeCameraNavigationAnimation(module, 'trackpad-pan-input');
6182
6240
 
6183
6241
  if (module.isSelecting) {
6184
6242
  updateSelectionBox(module);
@@ -6293,8 +6351,13 @@ window.MindMapInteractions = (function () {
6293
6351
  module._zoomFallbackExpired = false;
6294
6352
  // ▲▲▲ [Perf] ▲▲▲
6295
6353
 
6296
- const mouseX = (clientX / module.container.clientWidth) * 2 - 1;
6297
- const mouseY = -(clientY / module.container.clientHeight) * 2 + 1;
6354
+ const viewportMetrics = getCachedViewportMetrics(module);
6355
+ const viewportWidth = Math.max(1, Number(viewportMetrics.width || 0));
6356
+ const viewportHeight = Math.max(1, Number(viewportMetrics.height || 0));
6357
+ const localClientX = Number(clientX || 0) - Number(viewportMetrics.left || 0);
6358
+ const localClientY = Number(clientY || 0) - Number(viewportMetrics.top || 0);
6359
+ const mouseX = (localClientX / viewportWidth) * 2 - 1;
6360
+ const mouseY = -(localClientY / viewportHeight) * 2 + 1;
6298
6361
  const vfov = (module.camera.fov * Math.PI) / 180;
6299
6362
  const viewHeight = 2 * Math.tan(vfov / 2) * module.camera.position.z;
6300
6363
  const viewWidth = viewHeight * module.camera.aspect;
@@ -6332,7 +6395,8 @@ window.MindMapInteractions = (function () {
6332
6395
  module.targetY = newY;
6333
6396
  module._forceUpdateFrames = Math.max(Number(module._forceUpdateFrames || 0), 2);
6334
6397
  module._cameraNavigationForceFrames = Math.max(Number(module._cameraNavigationForceFrames || 0), 2);
6335
- // ▲▲▲ [Changed] ▲▲▲
6398
+ wakeCameraNavigationAnimation(module, 'wheel-zoom-input');
6399
+ // ▲▲▲ [Changed] ▲▲▲
6336
6400
 
6337
6401
  // ▼▼▼ [Perf] 줌 종료 감지 및 CSS3D 업데이트 타이머 ▼▼▼
6338
6402
  // 기존 타이머 취소 (연속 스크롤 감지)
@@ -6574,8 +6638,7 @@ window.MindMapInteractions = (function () {
6574
6638
  }
6575
6639
  }
6576
6640
 
6577
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
6578
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
6641
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
6579
6642
  module.raycaster.setFromCamera(module.pointer, module.camera);
6580
6643
 
6581
6644
  // Optimization: raycast using the spatial grid
@@ -6819,11 +6882,20 @@ window.MindMapInteractions = (function () {
6819
6882
  }
6820
6883
 
6821
6884
 
6822
- function onHoverMove(module, e) {
6823
- // Do not change cursor while the user is panning/dragging/resizing/selecting
6824
- if (module.isPanning || module.isDraggingNode || module.isDraggingMultipleNodes || module.isResizing || module.isSelecting) {
6825
- return;
6826
- }
6885
+ function onHoverMove(module, e) {
6886
+ // Do not run hover raycasts or DOM hit checks while the camera is moving.
6887
+ if (
6888
+ module.isPanning ||
6889
+ module.isZooming ||
6890
+ module._cameraMovingThisFrame === true ||
6891
+ module._viewSyncMotionActive === true ||
6892
+ module.isDraggingNode ||
6893
+ module.isDraggingMultipleNodes ||
6894
+ module.isResizing ||
6895
+ module.isSelecting
6896
+ ) {
6897
+ return;
6898
+ }
6827
6899
 
6828
6900
  // Skip hover checks while dragging the scrollbar
6829
6901
  if (module.isScrollbarDragging) {
@@ -2903,6 +2903,69 @@
2903
2903
  (this.imageInstanceData?.nodeIds?.length || 0) > 0;
2904
2904
  }
2905
2905
 
2906
+ canUseUltraResidentCameraOnlyFrame(camera = this._module?.camera, module = this._module) {
2907
+ if (FORCE_RESIDENT_INSTANCES_IN_MID_FAR !== true || !camera || !module) {
2908
+ return false;
2909
+ }
2910
+
2911
+ const cameraZ = Number(camera?.position?.z || 0);
2912
+ const lodBand = getLodBandForCameraZ(cameraZ);
2913
+ if (lodBand !== 'MID' && lodBand !== 'FAR') {
2914
+ return false;
2915
+ }
2916
+
2917
+ if (this.isInLODMode !== true ||
2918
+ this._currentLodBand !== lodBand ||
2919
+ this.isLoading === true ||
2920
+ module.isLoading === true ||
2921
+ this._fullResHandoffActive === true ||
2922
+ module.isDraggingNode === true ||
2923
+ module.isDraggingMultipleNodes === true ||
2924
+ module.isResizing === true ||
2925
+ module.isWindowResizing === true ||
2926
+ this.isDragging === true ||
2927
+ this._hasResidentLodInstances() !== true) {
2928
+ return false;
2929
+ }
2930
+
2931
+ const multiSelectedIds = module?.multiSelectedNodeIds || new Set();
2932
+ const selectedNodeId = module?.selectedNodeIdJs || null;
2933
+ const selectionKey = buildLodSelectionKey(multiSelectedIds, selectedNodeId);
2934
+ if (this._lastAppliedLodSelectionKey !== selectionKey) {
2935
+ return false;
2936
+ }
2937
+
2938
+ const dirtyPositionCount = this._dirtyPositionIds?.size || 0;
2939
+ const pendingSelectionCount = this._pendingSelectionRefreshIds?.size || 0;
2940
+ const imageAtlasQueued = this._imageAtlasQueuedIds?.size || 0;
2941
+ const imageAtlasLoading = this._imageAtlasLoadingIds?.size || 0;
2942
+ const imageAtlasReady = this._imageAtlasBatchReadyIds?.size || 0;
2943
+ const lineDetailRestorePending =
2944
+ ENABLE_INSTANCED_TEXT_LINES === true &&
2945
+ this._lineDetailsPatchPending === true &&
2946
+ lodBand === 'MID';
2947
+
2948
+ return !(
2949
+ this._instancesDirty === true ||
2950
+ this._imageInstancesDirty === true ||
2951
+ this._positionsOnlyDirty === true ||
2952
+ this._isNodeArrayDirty === true ||
2953
+ dirtyPositionCount > 0 ||
2954
+ pendingSelectionCount > 0 ||
2955
+ this._imageAtlasRebuildPending === true ||
2956
+ imageAtlasQueued > 0 ||
2957
+ imageAtlasLoading > 0 ||
2958
+ imageAtlasReady > 0 ||
2959
+ this._imageAtlasBatchActive === true ||
2960
+ this._lodCleanupPending === true ||
2961
+ this._postLoadVisualSyncPending === true ||
2962
+ this._residentRebuildPending === true ||
2963
+ this._deferLineRestorePending === true ||
2964
+ lineDetailRestorePending === true ||
2965
+ this._pendingLodVisibilityVersion >= 0
2966
+ );
2967
+ }
2968
+
2906
2969
  _canRunResidentFullRebuild(reason = 'unknown', lodBand = this._currentLodBand) {
2907
2970
  if (FORCE_RESIDENT_INSTANCES_IN_MID_FAR !== true) {
2908
2971
  return true;
@@ -5607,7 +5670,8 @@
5607
5670
  console.log(`[LODRenderer] CSS3D hidden synchronously in ${(performance.now() - hideStart).toFixed(1)}ms (${cssIdsToHide.size} active)`);
5608
5671
  }
5609
5672
 
5610
- if (window.MindMapCss3DManager?.setWillChange) {
5673
+ if (module?.renderDebugFlags?.enableCss3dWillChange === true &&
5674
+ window.MindMapCss3DManager?.setWillChange) {
5611
5675
  window.MindMapCss3DManager.setWillChange(false, module);
5612
5676
  }
5613
5677
  this._clearResidentLodCleanupIfStable(lodBand);
@@ -5649,7 +5713,8 @@
5649
5713
  this._nearEntryBoostFrames = this._getAdaptiveNearEntryBoostFrames(nearVisibleIds?.size || 0, module);
5650
5714
  this._lodCleanupPending = true;
5651
5715
 
5652
- if (window.MindMapCss3DManager?.setWillChange) {
5716
+ if (module?.renderDebugFlags?.enableCss3dWillChange === true &&
5717
+ window.MindMapCss3DManager?.setWillChange) {
5653
5718
  window.MindMapCss3DManager.setWillChange(true, module);
5654
5719
  }
5655
5720
  const tModeEnd = performance.now();
@@ -9469,7 +9534,16 @@
9469
9534
  return false;
9470
9535
  }
9471
9536
 
9472
- this._setSingleImageInstanceUvRect(normalizedId, slot.uvRect);
9537
+ const didPatchExistingImageRow = this._setSingleImageInstanceUvRect(normalizedId, slot.uvRect);
9538
+ if (!didPatchExistingImageRow) {
9539
+ const imageRow = this._buildResidentImageInstanceRow(entry);
9540
+ if (!imageRow || !this._applyResidentImageInstanceRow(entry, imageRow)) {
9541
+ return false;
9542
+ }
9543
+ }
9544
+
9545
+ this._lastAppliedImageAtlasSignature = this._buildImageAtlasPatchSignature();
9546
+ this._pendingImageAtlasPatchSignature = '';
9473
9547
  if (this._module) {
9474
9548
  this._module._forceUpdateFrames = Math.max(this._module._forceUpdateFrames || 0, 2);
9475
9549
  }
@@ -1098,6 +1098,58 @@
1098
1098
  return texture;
1099
1099
  }
1100
1100
 
1101
+ function getActiveImageStatusTextureRegistry(module) {
1102
+ const owner = module || window.mindMap || null;
1103
+ if (!owner) {
1104
+ return null;
1105
+ }
1106
+
1107
+ if (!(owner._activeImageStatusTextures instanceof Set)) {
1108
+ owner._activeImageStatusTextures = new Set();
1109
+ }
1110
+
1111
+ return owner._activeImageStatusTextures;
1112
+ }
1113
+
1114
+ function registerActiveImageStatusTexture(module, texture, bodyMesh = null) {
1115
+ const statusInfo = texture?.userData?.mindMapImageStatus;
1116
+ if (!statusInfo || statusInfo.state?.isLoading !== true) {
1117
+ return false;
1118
+ }
1119
+
1120
+ const registry = getActiveImageStatusTextureRegistry(module);
1121
+ if (!registry) {
1122
+ return false;
1123
+ }
1124
+
1125
+ statusInfo.bodyMesh = bodyMesh || null;
1126
+ registry.add(texture);
1127
+ return true;
1128
+ }
1129
+
1130
+ function unregisterActiveImageStatusTexture(module, texture) {
1131
+ if (!texture?.userData?.mindMapImageStatus) {
1132
+ return false;
1133
+ }
1134
+
1135
+ const owner = module || window.mindMap || null;
1136
+ const registry = owner?._activeImageStatusTextures;
1137
+ if (registry instanceof Set) {
1138
+ registry.delete(texture);
1139
+ }
1140
+
1141
+ return true;
1142
+ }
1143
+
1144
+ function isActiveImageStatusTexture(texture) {
1145
+ const statusInfo = texture?.userData?.mindMapImageStatus;
1146
+ return !!(
1147
+ statusInfo &&
1148
+ statusInfo.state?.isLoading === true &&
1149
+ statusInfo.ctx
1150
+ );
1151
+ }
1152
+
1101
1153
  function updateAnimatedImageStatusTexture(texture, now = performance.now()) {
1102
1154
  const statusInfo = texture?.userData?.mindMapImageStatus;
1103
1155
  if (!statusInfo || statusInfo.state?.isLoading !== true || !statusInfo.ctx) {
@@ -1127,30 +1179,38 @@
1127
1179
  return;
1128
1180
  }
1129
1181
 
1130
- if (!module?.nodeObjectsById?.forEach) {
1182
+ const registry = module?._activeImageStatusTextures;
1183
+ if (!(registry instanceof Set) || registry.size === 0) {
1131
1184
  return;
1132
1185
  }
1133
1186
 
1134
- module.nodeObjectsById.forEach(nodeEntry => {
1135
- if (nodeEntry?.model?.contentType !== 'image' || nodeEntry?.glObject?.visible === false) {
1136
- return;
1187
+ for (const texture of registry) {
1188
+ if (!isActiveImageStatusTexture(texture)) {
1189
+ registry.delete(texture);
1190
+ continue;
1191
+ }
1192
+
1193
+ const bodyMesh = texture.userData?.mindMapImageStatus?.bodyMesh || null;
1194
+ if (bodyMesh?.visible === false) {
1195
+ continue;
1137
1196
  }
1138
1197
 
1139
- const texture = nodeEntry?.bodyMesh?.material?.map;
1140
1198
  updateAnimatedImageStatusTexture(texture, now);
1141
- });
1199
+ }
1142
1200
  }
1143
1201
 
1144
- function swapImageBodyTexture(bodyMesh, nextTexture) {
1202
+ function swapImageBodyTexture(bodyMesh, nextTexture, module = null) {
1145
1203
  const material = bodyMesh?.material;
1146
1204
  if (!material || !nextTexture) {
1147
1205
  return;
1148
1206
  }
1149
1207
 
1150
1208
  const previousTexture = material.map;
1209
+ unregisterActiveImageStatusTexture(module, previousTexture);
1151
1210
  material.map = nextTexture;
1152
1211
  material.color?.setHex?.(0xffffff);
1153
1212
  material.needsUpdate = true;
1213
+ registerActiveImageStatusTexture(module, nextTexture, bodyMesh);
1154
1214
  const nodeId = bodyMesh?.userData?.nodeId;
1155
1215
  if (nodeId) {
1156
1216
  window.mindMap?.invalidateImageLodTexture?.(nodeId);
@@ -1161,13 +1221,14 @@
1161
1221
  }
1162
1222
  }
1163
1223
 
1164
- function clearImageBodyTexture(bodyMesh, colorHex = 0xffffff) {
1224
+ function clearImageBodyTexture(bodyMesh, colorHex = 0xffffff, module = null) {
1165
1225
  const material = bodyMesh?.material;
1166
1226
  if (!material) {
1167
1227
  return;
1168
1228
  }
1169
1229
 
1170
1230
  const previousTexture = material.map;
1231
+ unregisterActiveImageStatusTexture(module, previousTexture);
1171
1232
  material.map = null;
1172
1233
  material.color?.setHex?.(colorHex);
1173
1234
  material.transparent = false;
@@ -1858,7 +1919,7 @@
1858
1919
  height);
1859
1920
 
1860
1921
  if (fallbackTexture) {
1861
- swapImageBodyTexture(bodyMesh, fallbackTexture);
1922
+ swapImageBodyTexture(bodyMesh, fallbackTexture, options.module || window.mindMap || null);
1862
1923
  }
1863
1924
  };
1864
1925
 
@@ -1869,7 +1930,7 @@
1869
1930
  bodyMesh.userData.fullImageRetryAfter = 0;
1870
1931
  bodyMesh.userData.failedImageRenderKey = '';
1871
1932
  bodyMesh.userData.failedImageRetryAfter = 0;
1872
- clearImageBodyTexture(bodyMesh, 0xf8fafc);
1933
+ clearImageBodyTexture(bodyMesh, 0xf8fafc, options.module || window.mindMap || null);
1873
1934
  return;
1874
1935
  }
1875
1936
 
@@ -1961,7 +2022,7 @@
1961
2022
  bodyMesh.userData.failedImageRenderKey = '';
1962
2023
  bodyMesh.userData.failedImageRetryAfter = 0;
1963
2024
  clearFailedImageUrl(cachedImage.url || imageUrl);
1964
- swapImageBodyTexture(bodyMesh, nextTexture);
2025
+ swapImageBodyTexture(bodyMesh, nextTexture, options.module || window.mindMap || null);
1965
2026
  applyImageCoverUv(bodyMesh, width, height);
1966
2027
  })
1967
2028
  .catch(() => {
@@ -2501,7 +2562,7 @@
2501
2562
  module?.isLoading === true ||
2502
2563
  module?._bulkAddingNodes === true;
2503
2564
  if (nodeModel.contentType === 'image' && !shouldDeferImageBodyTexture) {
2504
- syncImageNodeBodyTexture(hitBody, node);
2565
+ syncImageNodeBodyTexture(hitBody, node, { module });
2505
2566
  } else if (nodeModel.contentType === 'image') {
2506
2567
  prewarmImageNodePreviewCache(node, module);
2507
2568
  }
@@ -2850,8 +2911,16 @@
2850
2911
  entry.glObject.traverse(child => {
2851
2912
  if (child.geometry) try { child.geometry.dispose(); } catch { }
2852
2913
  if (child.material) {
2853
- if (Array.isArray(child.material)) child.material.forEach(m => { try { m.dispose(); } catch { } });
2854
- else try { child.material.dispose(); } catch { }
2914
+ if (Array.isArray(child.material)) {
2915
+ child.material.forEach(m => {
2916
+ unregisterActiveImageStatusTexture(module, m?.map);
2917
+ try { m.dispose(); } catch { }
2918
+ });
2919
+ }
2920
+ else {
2921
+ unregisterActiveImageStatusTexture(module, child.material?.map);
2922
+ try { child.material.dispose(); } catch { }
2923
+ }
2855
2924
  }
2856
2925
  });
2857
2926
  } catch { }
@@ -127,6 +127,10 @@
127
127
  isDomOverlayDebugEnabled(module);
128
128
  }
129
129
 
130
+ function isPassiveDomOverlayEnabled() {
131
+ return PASSIVE_DOM_OVERLAY_ENABLED === true;
132
+ }
133
+
130
134
  function nowMs() {
131
135
  if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
132
136
  return performance.now();
@@ -4578,6 +4582,7 @@
4578
4582
  syncPassiveViewTransform: syncPassiveViewTransform,
4579
4583
  setPassiveOverlaySuppressed: setPassiveOverlaySuppressed,
4580
4584
  setMotionHint: setMotionHint,
4585
+ isPassiveDomOverlayEnabled: isPassiveDomOverlayEnabled,
4581
4586
  invalidateNode: invalidateNode,
4582
4587
  invalidateView: invalidateView,
4583
4588
  updateNodePlacement: updateNodePlacement,
@@ -40,8 +40,8 @@
40
40
  this.setSize = function(width, height){ _width=width; _height=height; _widthHalf=_width/2; _heightHalf=_height/2; domElement.style.width=width+'px'; domElement.style.height=height+'px'; cameraElement.style.width=width+'px'; cameraElement.style.height=height+'px'; };
41
41
  function getCameraCSSMatrix(matrix){ var e=matrix.elements; return 'matrix3d('+epsilon(e[0])+','+epsilon(-e[1])+','+epsilon(e[2])+','+epsilon(e[3])+','+epsilon(e[4])+','+epsilon(-e[5])+','+epsilon(e[6])+','+epsilon(e[7])+','+epsilon(e[8])+','+epsilon(-e[9])+','+epsilon(e[10])+','+epsilon(e[11])+','+epsilon(e[12])+','+epsilon(-e[13])+','+epsilon(e[14])+','+epsilon(e[15])+')'; }
42
42
  function getObjectCSSMatrix(matrix){ var e=matrix.elements; var m='matrix3d('+epsilon(e[0])+','+epsilon(e[1])+','+epsilon(e[2])+','+epsilon(e[3])+','+epsilon(-e[4])+','+epsilon(-e[5])+','+epsilon(-e[6])+','+epsilon(-e[7])+','+epsilon(e[8])+','+epsilon(e[9])+','+epsilon(e[10])+','+epsilon(e[11])+','+epsilon(e[12])+','+epsilon(e[13])+','+epsilon(e[14])+','+epsilon(e[15])+')'; return m; }
43
- function renderObject(object, scene, camera, cameraCSSMatrix){ if (object.isCSS3DObject){ var style=getObjectCSSMatrix(object.matrixWorld); var element=object.element; var cached=cache.objects.get(object); if (cached===undefined || cached.style!==style){ element.style.webkitTransform=element.style.transform=style; cache.objects.set(object, { style }); } element.style.display = object.visible ? '' : 'none'; if (element.parentNode !== cameraElement){ cameraElement.appendChild(element); } } for (var i=0,l=object.children.length;i<l;i++){ renderObject(object.children[i], scene, camera, cameraCSSMatrix); } }
44
- function renderCameraOnly(renderer, camera){ var fov=camera.projectionMatrix.elements[5]*_heightHalf; if (cache.camera.fov!==fov){ renderer.domElement.style.webkitPerspective=renderer.domElement.style.perspective=fov+'px'; cache.camera.fov=fov; } if (camera.parent===null) camera.updateMatrixWorld(); var cameraCSSMatrix='translateZ('+fov+'px)'+getCameraCSSMatrix(camera.matrixWorldInverse); var style=cameraCSSMatrix+'translate('+_widthHalf+'px,'+_heightHalf+'px)'; if (cache.camera.style!==style){ cameraElement.style.webkitTransform=cameraElement.style.transform=style; cache.camera.style=style; } return cameraCSSMatrix; }
43
+ function renderObject(object, scene, camera, cameraCSSMatrix){ if (object.isCSS3DObject){ var style=getObjectCSSMatrix(object.matrixWorld); var display=object.visible ? '' : 'none'; var element=object.element; var cached=cache.objects.get(object); if (cached===undefined || cached.style!==style){ element.style.webkitTransform=element.style.transform=style; } if (cached===undefined || cached.display!==display){ element.style.display=display; } if (cached===undefined || cached.style!==style || cached.display!==display){ cache.objects.set(object, { style, display }); } if (element.parentNode !== cameraElement){ cameraElement.appendChild(element); } } for (var i=0,l=object.children.length;i<l;i++){ renderObject(object.children[i], scene, camera, cameraCSSMatrix); } }
44
+ function renderCameraOnly(renderer, camera){ var fov=camera.projectionMatrix.elements[5]*_heightHalf; if (cache.camera.fov!==fov){ renderer.domElement.style.webkitPerspective=renderer.domElement.style.perspective=fov+'px'; cache.camera.fov=fov; } if (camera.parent===null && camera.matrixWorldNeedsUpdate===true) camera.updateMatrixWorld(); var cameraCSSMatrix='translateZ('+fov+'px)'+getCameraCSSMatrix(camera.matrixWorldInverse); var style=cameraCSSMatrix+'translate('+_widthHalf+'px,'+_heightHalf+'px)'; if (cache.camera.style!==style){ cameraElement.style.webkitTransform=cameraElement.style.transform=style; cache.camera.style=style; } return cameraCSSMatrix; }
45
45
  this.renderCamera = function(camera){ renderCameraOnly(this, camera); };
46
46
  this.render = function(scene, camera){ if (scene.autoUpdate===true) scene.updateMatrixWorld(); var cameraCSSMatrix=renderCameraOnly(this, camera); renderObject(scene, scene, camera, cameraCSSMatrix); };
47
47
  }