@mindexec/cli 0.2.219 → 0.2.221

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 (22) hide show
  1. package/package.json +1 -1
  2. package/scripts/remote-fleet-render-smoke.mjs +11 -0
  3. package/wwwroot/_content/MindExecution.Shared/js/background-themes.js +28 -113
  4. package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +1952 -152
  5. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +375 -98
  6. package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +108 -49
  7. package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +85 -3
  8. package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +83 -14
  9. package/wwwroot/_content/MindExecution.Shared/js/mind-map-text-overlay-v2.js +5 -0
  10. package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +2 -2
  11. package/wwwroot/_framework/{MindExecution.Core.c9wgwsw9z6.dll → MindExecution.Core.xsad4wu36e.dll} +0 -0
  12. package/wwwroot/_framework/{MindExecution.Plugins.Admin.29mytzdaun.dll → MindExecution.Plugins.Admin.m5d94977um.dll} +0 -0
  13. package/wwwroot/_framework/{MindExecution.Plugins.Business.g8txk1zzic.dll → MindExecution.Plugins.Business.ntqdn1hta3.dll} +0 -0
  14. package/wwwroot/_framework/{MindExecution.Plugins.Concept.u9kzsgf64o.dll → MindExecution.Plugins.Concept.mqiyx4db4r.dll} +0 -0
  15. package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.kibqg6rvqh.dll → MindExecution.Plugins.PlanMaster.fnortumnuu.dll} +0 -0
  16. package/wwwroot/_framework/{MindExecution.Plugins.YouTube.089r64n2hv.dll → MindExecution.Plugins.YouTube.86osu6wpgh.dll} +0 -0
  17. package/wwwroot/_framework/{MindExecution.Shared.tbutfszqeu.dll → MindExecution.Shared.wg2otcw4bv.dll} +0 -0
  18. package/wwwroot/_framework/{MindExecution.Web.7axuoygrwi.dll → MindExecution.Web.gfio3kfxrd.dll} +0 -0
  19. package/wwwroot/_framework/blazor.boot.json +17 -17
  20. package/wwwroot/index.html +3 -3
  21. package/wwwroot/service-worker-assets.js +27 -27
  22. 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;
@@ -24,15 +25,11 @@ window.MindMapInteractions = (function () {
24
25
  }
25
26
 
26
27
  function isBrowserSelectionLocked() {
27
- const body = document?.body;
28
28
  const css3dWrapper = document?.getElementById?.('css3d-dom-wrapper');
29
29
  return browserSelectionLockReasons.size > 0 ||
30
- body?.classList?.contains?.(BROWSER_SELECTION_LOCK_CLASS) === true ||
31
- body?.classList?.contains?.('is-node-dragging') === true ||
32
- body?.classList?.contains?.('is-panning') === true ||
33
- body?.classList?.contains?.('is-zooming') === true ||
34
30
  css3dWrapper?.classList?.contains?.('is-panning') === true ||
35
- css3dWrapper?.classList?.contains?.('is-zooming') === true;
31
+ css3dWrapper?.classList?.contains?.('is-zooming') === true ||
32
+ css3dWrapper?.classList?.contains?.('is-dragging') === true;
36
33
  }
37
34
 
38
35
  function handleBrowserSelectStart(event) {
@@ -102,6 +99,10 @@ window.MindMapInteractions = (function () {
102
99
  if (!module || typeof document === 'undefined' || !document.body) {
103
100
  return;
104
101
  }
102
+ if (MOTION_DOM_FANOUT_ENABLED !== true) {
103
+ clearZoomMotionChrome(module);
104
+ return;
105
+ }
105
106
 
106
107
  clearModuleTimer(module, '_zoomMotionChromeTimer');
107
108
  module._zoomMotionChromeTimer = setTimeout(() => {
@@ -128,6 +129,10 @@ window.MindMapInteractions = (function () {
128
129
  if (!module || !element) {
129
130
  return;
130
131
  }
132
+ if (MOTION_DOM_FANOUT_ENABLED !== true) {
133
+ clearPanMotionChrome(module);
134
+ return;
135
+ }
131
136
 
132
137
  clearModuleTimer(module, '_panMotionChromeTimer');
133
138
  module._panMotionChromeTimer = setTimeout(() => {
@@ -149,6 +154,10 @@ window.MindMapInteractions = (function () {
149
154
  if (!module || !window.MindMapCss3DManager?.setWillChange) {
150
155
  return;
151
156
  }
157
+ if (module.renderDebugFlags?.enableCss3dWillChange !== true) {
158
+ clearMotionWillChangeEnable(module, { disableIfIdle: true });
159
+ return;
160
+ }
152
161
 
153
162
  clearModuleTimer(module, '_motionWillChangeEnableTimer');
154
163
  module._motionWillChangeEnableTimer = setTimeout(() => {
@@ -165,6 +174,7 @@ window.MindMapInteractions = (function () {
165
174
  if (options.disableIfIdle === true &&
166
175
  module?.isZooming !== true &&
167
176
  module?.isPanning !== true &&
177
+ module?.renderDebugFlags?.enableCss3dWillChange === true &&
168
178
  window.MindMapCss3DManager?.setWillChange) {
169
179
  window.MindMapCss3DManager.setWillChange(false, module);
170
180
  }
@@ -272,10 +282,29 @@ window.MindMapInteractions = (function () {
272
282
 
273
283
  function getViewportMetrics(module) {
274
284
  ensureActiveContainer(module);
275
- const width = Math.max(0, Number(module?.container?.clientWidth || 0));
276
- const height = Math.max(0, Number(module?.container?.clientHeight || 0));
285
+ const rect = module?.container?.getBoundingClientRect?.() || null;
286
+ const width = Math.max(0, Number(rect?.width || module?.container?.clientWidth || 0));
287
+ const height = Math.max(0, Number(rect?.height || module?.container?.clientHeight || 0));
288
+ const left = Number(rect?.left || 0);
289
+ const top = Number(rect?.top || 0);
277
290
  const dpr = Math.max(1, Number(window.devicePixelRatio || 1));
278
- return { width, height, dpr };
291
+ return { width, height, left, top, dpr };
292
+ }
293
+
294
+ function getCachedViewportMetrics(module) {
295
+ const width = Math.max(0, Number(module?._lastViewportWidth || 0));
296
+ const height = Math.max(0, Number(module?._lastViewportHeight || 0));
297
+ if (width > 0 && height > 0) {
298
+ return {
299
+ width,
300
+ height,
301
+ left: Number(module?._lastViewportLeft || 0),
302
+ top: Number(module?._lastViewportTop || 0),
303
+ dpr: Math.max(1, Number(module?._lastViewportDpr || window.devicePixelRatio || 1))
304
+ };
305
+ }
306
+
307
+ return getViewportMetrics(module);
279
308
  }
280
309
 
281
310
  function haveViewportMetricsChanged(module, metrics, force = false) {
@@ -285,9 +314,13 @@ window.MindMapInteractions = (function () {
285
314
 
286
315
  const lastWidth = Number(module?._lastViewportWidth || 0);
287
316
  const lastHeight = Number(module?._lastViewportHeight || 0);
317
+ const lastLeft = Number(module?._lastViewportLeft || 0);
318
+ const lastTop = Number(module?._lastViewportTop || 0);
288
319
  const lastDpr = Number(module?._lastViewportDpr || 0);
289
320
  return Math.abs(metrics.width - lastWidth) > 1 ||
290
321
  Math.abs(metrics.height - lastHeight) > 1 ||
322
+ Math.abs(metrics.left - lastLeft) > 1 ||
323
+ Math.abs(metrics.top - lastTop) > 1 ||
291
324
  Math.abs(metrics.dpr - lastDpr) > 0.02;
292
325
  }
293
326
 
@@ -298,6 +331,8 @@ window.MindMapInteractions = (function () {
298
331
 
299
332
  module._lastViewportWidth = metrics.width;
300
333
  module._lastViewportHeight = metrics.height;
334
+ module._lastViewportLeft = metrics.left;
335
+ module._lastViewportTop = metrics.top;
301
336
  module._lastViewportDpr = metrics.dpr;
302
337
  }
303
338
 
@@ -554,6 +589,13 @@ window.MindMapInteractions = (function () {
554
589
  Number(module._cameraNavigationForceFrames || 0),
555
590
  PAN_LIVE_REFRESH_FORCE_FRAMES
556
591
  );
592
+ wakeCameraNavigationAnimation(module, 'pan-input');
593
+ }
594
+
595
+ function wakeCameraNavigationAnimation(module, reason = 'camera-navigation-input') {
596
+ if (module && typeof module.requestAnimationWake === 'function') {
597
+ module.requestAnimationWake(reason);
598
+ }
557
599
  }
558
600
 
559
601
  function isEditableElement(element) {
@@ -1418,30 +1460,36 @@ window.MindMapInteractions = (function () {
1418
1460
  // ▲▲▲ [New] Scrollbar-drag helper functions ▲▲▲
1419
1461
 
1420
1462
  // ▼▼▼ [New] Centralized Pointer Update Helper ▼▼▼
1421
- function updatePointer(module, e) {
1422
- if (!module) return;
1423
- ensureActiveContainer(module);
1424
-
1425
- const rect = module.container?.getBoundingClientRect?.() ||
1426
- module.cssRenderer?.domElement?.getBoundingClientRect?.();
1427
- if (!rect || rect.width <= 0 || rect.height <= 0) return;
1428
-
1429
- const x = (e.clientX - rect.left) / rect.width;
1430
- const y = (e.clientY - rect.top) / rect.height;
1431
- module.pointer.x = (x * 2) - 1;
1432
- module.pointer.y = -((y * 2) - 1);
1433
- }
1463
+ function setPointerFromClientPosition(module, clientX, clientY) {
1464
+ if (!module?.pointer) return false;
1465
+
1466
+ const metrics = getCachedViewportMetrics(module);
1467
+ if (!metrics || metrics.width <= 0 || metrics.height <= 0) {
1468
+ return false;
1469
+ }
1470
+
1471
+ const x = (Number(clientX || 0) - Number(metrics.left || 0)) / metrics.width;
1472
+ const y = (Number(clientY || 0) - Number(metrics.top || 0)) / metrics.height;
1473
+ module.pointer.x = (x * 2) - 1;
1474
+ module.pointer.y = -((y * 2) - 1);
1475
+ return true;
1476
+ }
1477
+
1478
+ function updatePointer(module, e) {
1479
+ if (!module) return;
1480
+ setPointerFromClientPosition(module, e?.clientX, e?.clientY);
1481
+ }
1434
1482
  // ▲▲▲ [New] ▲▲▲
1435
1483
 
1436
1484
  // ▼▼▼ [New] World Point Conversion Helper (Screen creation fix) ▼▼▼
1437
1485
  function getWorldPoint(module, mouseX, mouseY) {
1438
1486
  if (!module.camera || !module.raycaster || !module.plane) return null;
1439
1487
 
1440
- const rect = module.container?.getBoundingClientRect?.();
1441
- const width = rect?.width || module.container?.clientWidth || 1;
1442
- const height = rect?.height || module.container?.clientHeight || 1;
1443
- const localX = rect ? (mouseX - rect.left) : mouseX;
1444
- const localY = rect ? (mouseY - rect.top) : mouseY;
1488
+ const metrics = getCachedViewportMetrics(module);
1489
+ const width = Math.max(1, Number(metrics.width || 0));
1490
+ const height = Math.max(1, Number(metrics.height || 0));
1491
+ const localX = Number(mouseX || 0) - Number(metrics.left || 0);
1492
+ const localY = Number(mouseY || 0) - Number(metrics.top || 0);
1445
1493
 
1446
1494
  const vec = new THREE.Vector2(
1447
1495
  (localX / width) * 2 - 1,
@@ -1864,8 +1912,9 @@ window.MindMapInteractions = (function () {
1864
1912
  vec.project(module.camera);
1865
1913
 
1866
1914
  // Convert from NDC (-1 to +1) to screen pixels
1867
- const x = (vec.x + 1) * module.container.clientWidth / 2;
1868
- const y = (-vec.y + 1) * module.container.clientHeight / 2;
1915
+ const metrics = getCachedViewportMetrics(module);
1916
+ const x = (vec.x + 1) * Math.max(1, Number(metrics.width || 0)) / 2;
1917
+ const y = (-vec.y + 1) * Math.max(1, Number(metrics.height || 0)) / 2;
1869
1918
 
1870
1919
  return { x, y };
1871
1920
  }
@@ -1877,8 +1926,7 @@ window.MindMapInteractions = (function () {
1877
1926
  if (!module.worldStartPos || !module.lastMouseClientX || !module.lastMouseClientY) return;
1878
1927
 
1879
1928
  // Calculate current world position of mouse cursor
1880
- module.pointer.x = (module.lastMouseClientX / module.container.clientWidth) * 2 - 1;
1881
- module.pointer.y = -(module.lastMouseClientY / module.container.clientHeight) * 2 + 1;
1929
+ setPointerFromClientPosition(module, module.lastMouseClientX, module.lastMouseClientY);
1882
1930
  module.raycaster.setFromCamera(module.pointer, module.camera);
1883
1931
 
1884
1932
  const worldEndPos = new THREE.Vector3();
@@ -4772,8 +4820,7 @@ window.MindMapInteractions = (function () {
4772
4820
  module.lastMouseClientY = e.clientY;
4773
4821
 
4774
4822
  // Get current mouse world position
4775
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
4776
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
4823
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
4777
4824
  module.raycaster.setFromCamera(module.pointer, module.camera);
4778
4825
 
4779
4826
  const worldEndPos = new THREE.Vector3();
@@ -4816,8 +4863,7 @@ window.MindMapInteractions = (function () {
4816
4863
  }
4817
4864
 
4818
4865
  if (module.wasDragged) {
4819
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
4820
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
4866
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
4821
4867
  module.raycaster.setFromCamera(module.pointer, module.camera);
4822
4868
  if (module.raycaster.ray.intersectPlane(module.plane, module.intersectPoint)) {
4823
4869
  const newPos = _tmpDragPos.copy(module.intersectPoint).sub(module.dragOffset);
@@ -4875,8 +4921,7 @@ window.MindMapInteractions = (function () {
4875
4921
 
4876
4922
  if (module.wasDragged) {
4877
4923
  const t0 = performance.now();
4878
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
4879
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
4924
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
4880
4925
  module.raycaster.setFromCamera(module.pointer, module.camera);
4881
4926
  const t1 = performance.now();
4882
4927
 
@@ -5049,8 +5094,7 @@ window.MindMapInteractions = (function () {
5049
5094
  module.selectionRectElement.style.display = 'none';
5050
5095
  }
5051
5096
  if (module.worldStartPos) {
5052
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
5053
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
5097
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
5054
5098
  module.raycaster.setFromCamera(module.pointer, module.camera);
5055
5099
 
5056
5100
  const worldEndPos = new THREE.Vector3();
@@ -6188,6 +6232,7 @@ window.MindMapInteractions = (function () {
6188
6232
  module._cameraNavigationForceFrames = Math.max(module._cameraNavigationForceFrames || 0, 2);
6189
6233
  module._deferPassiveOverlayRefresh = true;
6190
6234
  module._cameraNavigationOverlayInputTime = panInputAt;
6235
+ wakeCameraNavigationAnimation(module, 'trackpad-pan-input');
6191
6236
 
6192
6237
  if (module.isSelecting) {
6193
6238
  updateSelectionBox(module);
@@ -6302,8 +6347,13 @@ window.MindMapInteractions = (function () {
6302
6347
  module._zoomFallbackExpired = false;
6303
6348
  // ▲▲▲ [Perf] ▲▲▲
6304
6349
 
6305
- const mouseX = (clientX / module.container.clientWidth) * 2 - 1;
6306
- const mouseY = -(clientY / module.container.clientHeight) * 2 + 1;
6350
+ const viewportMetrics = getCachedViewportMetrics(module);
6351
+ const viewportWidth = Math.max(1, Number(viewportMetrics.width || 0));
6352
+ const viewportHeight = Math.max(1, Number(viewportMetrics.height || 0));
6353
+ const localClientX = Number(clientX || 0) - Number(viewportMetrics.left || 0);
6354
+ const localClientY = Number(clientY || 0) - Number(viewportMetrics.top || 0);
6355
+ const mouseX = (localClientX / viewportWidth) * 2 - 1;
6356
+ const mouseY = -(localClientY / viewportHeight) * 2 + 1;
6307
6357
  const vfov = (module.camera.fov * Math.PI) / 180;
6308
6358
  const viewHeight = 2 * Math.tan(vfov / 2) * module.camera.position.z;
6309
6359
  const viewWidth = viewHeight * module.camera.aspect;
@@ -6341,7 +6391,8 @@ window.MindMapInteractions = (function () {
6341
6391
  module.targetY = newY;
6342
6392
  module._forceUpdateFrames = Math.max(Number(module._forceUpdateFrames || 0), 2);
6343
6393
  module._cameraNavigationForceFrames = Math.max(Number(module._cameraNavigationForceFrames || 0), 2);
6344
- // ▲▲▲ [Changed] ▲▲▲
6394
+ wakeCameraNavigationAnimation(module, 'wheel-zoom-input');
6395
+ // ▲▲▲ [Changed] ▲▲▲
6345
6396
 
6346
6397
  // ▼▼▼ [Perf] 줌 종료 감지 및 CSS3D 업데이트 타이머 ▼▼▼
6347
6398
  // 기존 타이머 취소 (연속 스크롤 감지)
@@ -6583,8 +6634,7 @@ window.MindMapInteractions = (function () {
6583
6634
  }
6584
6635
  }
6585
6636
 
6586
- module.pointer.x = (e.clientX / module.container.clientWidth) * 2 - 1;
6587
- module.pointer.y = -(e.clientY / module.container.clientHeight) * 2 + 1;
6637
+ setPointerFromClientPosition(module, e.clientX, e.clientY);
6588
6638
  module.raycaster.setFromCamera(module.pointer, module.camera);
6589
6639
 
6590
6640
  // Optimization: raycast using the spatial grid
@@ -6828,11 +6878,20 @@ window.MindMapInteractions = (function () {
6828
6878
  }
6829
6879
 
6830
6880
 
6831
- function onHoverMove(module, e) {
6832
- // Do not change cursor while the user is panning/dragging/resizing/selecting
6833
- if (module.isPanning || module.isDraggingNode || module.isDraggingMultipleNodes || module.isResizing || module.isSelecting) {
6834
- return;
6835
- }
6881
+ function onHoverMove(module, e) {
6882
+ // Do not run hover raycasts or DOM hit checks while the camera is moving.
6883
+ if (
6884
+ module.isPanning ||
6885
+ module.isZooming ||
6886
+ module._cameraMovingThisFrame === true ||
6887
+ module._viewSyncMotionActive === true ||
6888
+ module.isDraggingNode ||
6889
+ module.isDraggingMultipleNodes ||
6890
+ module.isResizing ||
6891
+ module.isSelecting
6892
+ ) {
6893
+ return;
6894
+ }
6836
6895
 
6837
6896
  // Skip hover checks while dragging the scrollbar
6838
6897
  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;
@@ -4889,6 +4952,14 @@
4889
4952
  this._getActiveTemplateCssLodCount(this._module) > 0);
4890
4953
  }
4891
4954
 
4955
+ hasCss3dLodCandidates() {
4956
+ return this.isInLODMode === true &&
4957
+ (
4958
+ (this._lodImageCssFallbackNodeIds?.size || 0) > 0 ||
4959
+ (this._lodTemplateCssNodeIds?.size || 0) > 0
4960
+ );
4961
+ }
4962
+
4892
4963
  _getActiveTemplateCssLodCount(module = this._module) {
4893
4964
  if (this.isInLODMode !== true || !this._lodTemplateCssNodeIds || this._lodTemplateCssNodeIds.size === 0) {
4894
4965
  return 0;
@@ -5607,7 +5678,8 @@
5607
5678
  console.log(`[LODRenderer] CSS3D hidden synchronously in ${(performance.now() - hideStart).toFixed(1)}ms (${cssIdsToHide.size} active)`);
5608
5679
  }
5609
5680
 
5610
- if (window.MindMapCss3DManager?.setWillChange) {
5681
+ if (module?.renderDebugFlags?.enableCss3dWillChange === true &&
5682
+ window.MindMapCss3DManager?.setWillChange) {
5611
5683
  window.MindMapCss3DManager.setWillChange(false, module);
5612
5684
  }
5613
5685
  this._clearResidentLodCleanupIfStable(lodBand);
@@ -5649,7 +5721,8 @@
5649
5721
  this._nearEntryBoostFrames = this._getAdaptiveNearEntryBoostFrames(nearVisibleIds?.size || 0, module);
5650
5722
  this._lodCleanupPending = true;
5651
5723
 
5652
- if (window.MindMapCss3DManager?.setWillChange) {
5724
+ if (module?.renderDebugFlags?.enableCss3dWillChange === true &&
5725
+ window.MindMapCss3DManager?.setWillChange) {
5653
5726
  window.MindMapCss3DManager.setWillChange(true, module);
5654
5727
  }
5655
5728
  const tModeEnd = performance.now();
@@ -9469,7 +9542,16 @@
9469
9542
  return false;
9470
9543
  }
9471
9544
 
9472
- this._setSingleImageInstanceUvRect(normalizedId, slot.uvRect);
9545
+ const didPatchExistingImageRow = this._setSingleImageInstanceUvRect(normalizedId, slot.uvRect);
9546
+ if (!didPatchExistingImageRow) {
9547
+ const imageRow = this._buildResidentImageInstanceRow(entry);
9548
+ if (!imageRow || !this._applyResidentImageInstanceRow(entry, imageRow)) {
9549
+ return false;
9550
+ }
9551
+ }
9552
+
9553
+ this._lastAppliedImageAtlasSignature = this._buildImageAtlasPatchSignature();
9554
+ this._pendingImageAtlasPatchSignature = '';
9473
9555
  if (this._module) {
9474
9556
  this._module._forceUpdateFrames = Math.max(this._module._forceUpdateFrames || 0, 2);
9475
9557
  }
@@ -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
  }