@mindexec/cli 0.2.432 → 0.2.434
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/package.json +1 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +1 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +19 -19
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +83 -176
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-render-plan.js +963 -21
- package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +3 -3
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.slcp5au0e8.dll → MindExecution.Plugins.Concept.7uhld08zkc.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.nk8wgsetbw.dll → MindExecution.Plugins.PlanMaster.y1sj1ifw0z.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.rrrfswr6up.dll → MindExecution.Plugins.YouTube.ij0uk05x1o.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.23xj2d2olw.dll → MindExecution.Shared.1h72etbxec.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.4a5lf7nem7.dll → MindExecution.Web.18xe2efznc.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +11 -11
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +18 -18
- package/wwwroot/service-worker.js +1 -1
|
@@ -1,19 +1,75 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const BUILD_ID = '20260712-
|
|
4
|
+
const BUILD_ID = '20260712-boundary-transition-cache-v38';
|
|
5
5
|
const FRAME_SAMPLE_LIMIT = 240;
|
|
6
6
|
const INITIAL_LINE_TEXTURE_ROWS = 1024;
|
|
7
7
|
const GPU_WARM_RETRY_DELAY_MS = 120;
|
|
8
8
|
const IMAGE_ATLAS_TILE_SIZE = 128;
|
|
9
9
|
const frameSampleStates = new WeakMap();
|
|
10
10
|
const residentLinePrewarmStates = new WeakMap();
|
|
11
|
+
const residentTransitionStates = new WeakMap();
|
|
12
|
+
const cssMediaFrameDomStates = new WeakMap();
|
|
13
|
+
let cssMediaFrameDomReuseCount = 0;
|
|
14
|
+
let cssMediaFrameDomApplyCount = 0;
|
|
15
|
+
const RESIDENT_CSS_CACHE_TEXT_TYPES = new Set(['text', 'note', 'memo', 'markdown', 'code', 'csv-table']);
|
|
11
16
|
const VIEW_SYNC_SECTION_KEYS = [
|
|
12
17
|
'fullResSetup', 'fullResImages', 'fullResCssQueue', 'fullResHandoff', 'fullResOther',
|
|
13
|
-
'lodCleanup', 'lodNodeScan', 'lodResidentApply', 'lodImageInstances',
|
|
18
|
+
'lodCleanup', 'lodNodeScan', 'lodResidentApply', 'lodLinePatch', 'lodImageInstances',
|
|
14
19
|
'lodPositionPatch', 'lodFallbacks', 'lodOther'
|
|
15
20
|
];
|
|
16
21
|
|
|
22
|
+
function configureImageAtlasTexture(texture, THREE) {
|
|
23
|
+
if (!texture || !THREE) return texture;
|
|
24
|
+
if ('colorSpace' in texture && THREE.SRGBColorSpace) texture.colorSpace = THREE.SRGBColorSpace;
|
|
25
|
+
else if ('encoding' in texture && THREE.sRGBEncoding) texture.encoding = THREE.sRGBEncoding;
|
|
26
|
+
texture.minFilter = THREE.LinearFilter;
|
|
27
|
+
texture.magFilter = THREE.LinearFilter;
|
|
28
|
+
texture.wrapS = THREE.ClampToEdgeWrapping;
|
|
29
|
+
texture.wrapT = THREE.ClampToEdgeWrapping;
|
|
30
|
+
texture.flipY = false;
|
|
31
|
+
texture.generateMipmaps = false;
|
|
32
|
+
texture.needsUpdate = true;
|
|
33
|
+
return texture;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getImageAtlasOutputColorChunk(THREE) {
|
|
37
|
+
const chunk = THREE?.ShaderChunk?.colorspace_fragment
|
|
38
|
+
? '#include <colorspace_fragment>'
|
|
39
|
+
: (THREE?.ShaderChunk?.encodings_fragment ? '#include <encodings_fragment>' : '');
|
|
40
|
+
globalThis.MindCanvasDevGuards?.assert?.(chunk.length > 0,
|
|
41
|
+
'resident-image-output-color-chunk-missing', { threeRevision: String(THREE?.REVISION || 'unknown') });
|
|
42
|
+
return chunk;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function syncCommittedResidentTextCount(renderer, hasResidentInstances, forceResident) {
|
|
46
|
+
if (forceResident !== true || !hasResidentInstances || renderer?._lodUsesVisibleSubset === true ||
|
|
47
|
+
renderer?._instancesDirty === true || renderer?._isNodeArrayDirty === true) return -1;
|
|
48
|
+
const count = Number(renderer?.instanceData?.nodeIds?.length || 0);
|
|
49
|
+
renderer._cachedEligibleTextLikeCount = count;
|
|
50
|
+
renderer._lastNodeCount = count;
|
|
51
|
+
return count;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function clearFullResImageVisuals(renderer, nodeObjectsById) {
|
|
55
|
+
const tracked = renderer?._fullResImageVisualIds;
|
|
56
|
+
if (!tracked) return;
|
|
57
|
+
for (const nodeId of tracked) {
|
|
58
|
+
const entry = nodeObjectsById?.get?.(nodeId) || null;
|
|
59
|
+
if (entry) renderer._hideImageLodFullVisual?.(entry);
|
|
60
|
+
}
|
|
61
|
+
if (renderer.isInLODMode === true) {
|
|
62
|
+
const residentIds = renderer.imageInstanceData?.nodeIds || [];
|
|
63
|
+
for (let i = 0; i < residentIds.length; i++) {
|
|
64
|
+
const nodeId = residentIds[i];
|
|
65
|
+
if (!nodeId || tracked.has(nodeId)) continue;
|
|
66
|
+
const entry = nodeObjectsById?.get?.(nodeId) || null;
|
|
67
|
+
if (entry) renderer._hideImageLodFullVisual?.(entry);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
tracked.clear();
|
|
71
|
+
}
|
|
72
|
+
|
|
17
73
|
function isFullResMotionOptimizationActive(module) {
|
|
18
74
|
return (module?._viewSyncMotionActive === true ||
|
|
19
75
|
module?.isPanning === true ||
|
|
@@ -191,8 +247,32 @@
|
|
|
191
247
|
context.fillStyle = '#eef2f7';
|
|
192
248
|
context.fillRect(0, 0, size, size);
|
|
193
249
|
}
|
|
194
|
-
|
|
250
|
+
const THREE = globalThis.THREE;
|
|
251
|
+
const previousTexture = renderer.imageAtlasTexture || null;
|
|
252
|
+
if (THREE?.CanvasTexture) {
|
|
253
|
+
const nextTexture = new THREE.CanvasTexture(renderer.imageAtlasCanvas);
|
|
254
|
+
nextTexture.minFilter = previousTexture?.minFilter ?? THREE.LinearFilter;
|
|
255
|
+
nextTexture.magFilter = previousTexture?.magFilter ?? THREE.LinearFilter;
|
|
256
|
+
nextTexture.wrapS = previousTexture?.wrapS ?? THREE.ClampToEdgeWrapping;
|
|
257
|
+
nextTexture.wrapT = previousTexture?.wrapT ?? THREE.ClampToEdgeWrapping;
|
|
258
|
+
nextTexture.flipY = previousTexture?.flipY ?? false;
|
|
259
|
+
nextTexture.generateMipmaps = previousTexture?.generateMipmaps ?? false;
|
|
260
|
+
if ('colorSpace' in nextTexture && previousTexture?.colorSpace) {
|
|
261
|
+
nextTexture.colorSpace = previousTexture.colorSpace;
|
|
262
|
+
} else if ('encoding' in nextTexture && previousTexture?.encoding != null) {
|
|
263
|
+
nextTexture.encoding = previousTexture.encoding;
|
|
264
|
+
}
|
|
265
|
+
nextTexture.needsUpdate = true;
|
|
266
|
+
renderer.imageAtlasTexture = nextTexture;
|
|
267
|
+
const atlasUniform = renderer.instancedImageMesh?.material?.uniforms?.uImageAtlas || null;
|
|
268
|
+
if (atlasUniform) atlasUniform.value = nextTexture;
|
|
269
|
+
previousTexture?.dispose?.();
|
|
270
|
+
} else if (previousTexture) {
|
|
271
|
+
previousTexture.needsUpdate = true;
|
|
272
|
+
}
|
|
195
273
|
renderer._residentGpuWarmKey = '';
|
|
274
|
+
renderer._residentGpuWarmOffscreenComplete = false;
|
|
275
|
+
renderer._residentImageAtlasWarmVersion = -1;
|
|
196
276
|
return true;
|
|
197
277
|
}
|
|
198
278
|
|
|
@@ -207,6 +287,531 @@
|
|
|
207
287
|
return batch;
|
|
208
288
|
}
|
|
209
289
|
|
|
290
|
+
function reuseCssMediaFrameDom(cssObject, width, height, hasContextSourcePins = false) {
|
|
291
|
+
const wrapper = cssObject?.element || null;
|
|
292
|
+
const isMedia = wrapper?.classList?.contains?.('node-type-image') === true ||
|
|
293
|
+
wrapper?.classList?.contains?.('node-type-video') === true ||
|
|
294
|
+
wrapper?.classList?.contains?.('node-type-embed') === true;
|
|
295
|
+
if (!isMedia || !wrapper?.style) return false;
|
|
296
|
+
|
|
297
|
+
const inner = wrapper.firstElementChild || null;
|
|
298
|
+
const content = inner?.querySelector?.('.node-content-wrapper') || null;
|
|
299
|
+
const response = inner?.querySelector?.('.node-response') || null;
|
|
300
|
+
const surface = inner?.querySelector?.('img,video,canvas.mind-map-video-proxy,iframe,.embed-card,.embed-iframe-shell') || null;
|
|
301
|
+
const resolutionScale = Math.max(1, Number(cssObject?.userData?.resolutionScale || 1));
|
|
302
|
+
const worldWidth = Math.max(1, Math.round(Number(width || 1)));
|
|
303
|
+
const worldHeight = Math.max(1, Math.round(Number(height || 1)));
|
|
304
|
+
const scaledWidth = worldWidth * resolutionScale;
|
|
305
|
+
const scaledHeight = worldHeight * resolutionScale;
|
|
306
|
+
const state = cssMediaFrameDomStates.get(cssObject) || null;
|
|
307
|
+
const structureMatches = !!state && state.wrapper === wrapper && state.inner === inner &&
|
|
308
|
+
state.content === content && state.response === response && state.surface === surface &&
|
|
309
|
+
state.innerChildren === Number(inner?.childElementCount ?? inner?.children?.length ?? 0) &&
|
|
310
|
+
state.contentChildren === Number(content?.childElementCount ?? content?.children?.length ?? 0);
|
|
311
|
+
const frameMatches = structureMatches && state.width === worldWidth && state.height === worldHeight &&
|
|
312
|
+
state.resolutionScale === resolutionScale && state.hasContextSourcePins === (hasContextSourcePins === true);
|
|
313
|
+
const frameStylesReady = wrapper.style.width === `${scaledWidth}px` && wrapper.style.height === `${scaledHeight}px` &&
|
|
314
|
+
(!inner?.style || (inner.style.width === `${worldWidth}px` && inner.style.height === `${worldHeight}px`));
|
|
315
|
+
|
|
316
|
+
if (frameMatches && frameStylesReady) {
|
|
317
|
+
cssMediaFrameDomReuseCount++;
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
cssMediaFrameDomStates.set(cssObject, {
|
|
322
|
+
wrapper,
|
|
323
|
+
inner,
|
|
324
|
+
content,
|
|
325
|
+
response,
|
|
326
|
+
surface,
|
|
327
|
+
innerChildren: Number(inner?.childElementCount ?? inner?.children?.length ?? 0),
|
|
328
|
+
contentChildren: Number(content?.childElementCount ?? content?.children?.length ?? 0),
|
|
329
|
+
width: worldWidth,
|
|
330
|
+
height: worldHeight,
|
|
331
|
+
resolutionScale,
|
|
332
|
+
hasContextSourcePins: hasContextSourcePins === true
|
|
333
|
+
});
|
|
334
|
+
cssMediaFrameDomApplyCount++;
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function reuseStableVisibleCss(renderer, entry, module, nodeIdValue, options = {}) {
|
|
339
|
+
const cssObject = entry?.cssObject || null;
|
|
340
|
+
const element = cssObject?.element || null;
|
|
341
|
+
const nodeId = String(nodeIdValue || entry?.model?.id || entry?.model?.Id || entry?.glObject?.userData?.nodeId || '').trim();
|
|
342
|
+
const cssScene = module?.cssScene || module?.scene || null;
|
|
343
|
+
const allowResident = options.allowResident === true;
|
|
344
|
+
if (!nodeId || !element || entry?.isCssDirty === true || entry?.currentType !== 'CSS' ||
|
|
345
|
+
cssObject.visible !== true || cssObject.userData?._residentTransitionPrepared === true ||
|
|
346
|
+
(!allowResident && renderer?.isInLODMode === true) || (cssScene && cssObject.parent !== cssScene) ||
|
|
347
|
+
element.style?.display === 'none' || element.style?.visibility === 'hidden' || element.style?.opacity === '0' ||
|
|
348
|
+
module?._cssParentRepairNeeded === true || module?._cssTransformDirtyIds?.has?.(nodeId) === true) return false;
|
|
349
|
+
|
|
350
|
+
const selectedNodeId = String(module?.selectedNodeIdJs || module?.selectedNodeId || '').trim();
|
|
351
|
+
const editingNodeId = String(module?._textOverlayV2State?.editing?.nodeId || module?._editingOverlayState?.nodeId || '').trim();
|
|
352
|
+
if (selectedNodeId === nodeId || module?.multiSelectedNodeIds?.has?.(nodeId) === true ||
|
|
353
|
+
module?.draggedNodeId === nodeId || editingNodeId === nodeId ||
|
|
354
|
+
renderer?._getCurrentHoveredNodeId?.(module) === nodeId) return false;
|
|
355
|
+
|
|
356
|
+
const inner = element.querySelector?.('.node-container') || null;
|
|
357
|
+
const targets = inner && inner !== element ? [element, inner] : [element];
|
|
358
|
+
const isHigh = options.isHighDetail === true;
|
|
359
|
+
for (const target of targets) {
|
|
360
|
+
if (!target?.classList || target.classList.contains(isHigh ? 'lod-high' : 'lod-low') !== true ||
|
|
361
|
+
target.classList.contains(isHigh ? 'lod-low' : 'lod-high') === true) return false;
|
|
362
|
+
}
|
|
363
|
+
if (isHigh && (element.matches?.('[data-text-overlay-source-suspended],.mind-map-text-overlay-source-suspended,.mind-map-v2-source-suspended') === true ||
|
|
364
|
+
element.querySelector?.('[data-text-overlay-source-suspended],.mind-map-text-overlay-source-suspended,.mind-map-v2-source-suspended'))) return false;
|
|
365
|
+
|
|
366
|
+
const contentType = String(entry?.model?.contentType ?? entry?.model?.ContentType ?? '').trim().toLowerCase();
|
|
367
|
+
if (contentType === 'image' || contentType === 'video') {
|
|
368
|
+
const media = element.querySelector?.('img,video') || null;
|
|
369
|
+
const source = media?.getAttribute?.('src') || media?.currentSrc || media?.src || '';
|
|
370
|
+
if (!media || !source) return false;
|
|
371
|
+
} else if (contentType === 'embed' &&
|
|
372
|
+
!element.querySelector?.('.embed-card,.embed-frame,.embed-iframe-shell')) return false;
|
|
373
|
+
|
|
374
|
+
renderer?._nearCssVisibleIds?.add?.(nodeId);
|
|
375
|
+
if (renderer) renderer._fullResCssStableReuseCount = Number(renderer._fullResCssStableReuseCount || 0) + 1;
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function reuseActiveCssMediaFallback(renderer, entry, module) {
|
|
380
|
+
const cssObject = entry?.cssObject || null;
|
|
381
|
+
const element = cssObject?.element || null;
|
|
382
|
+
const nodeId = String(entry?.model?.id || entry?.model?.Id || entry?.glObject?.userData?.nodeId || '').trim();
|
|
383
|
+
const cssScene = module?.cssScene || module?.scene || null;
|
|
384
|
+
if (!nodeId || !element || entry?.isCssDirty === true || cssObject.visible !== true ||
|
|
385
|
+
!renderer?._lodImageCssFallbackNodeIds?.has?.(nodeId) ||
|
|
386
|
+
(cssScene && cssObject.parent !== cssScene) || element.style?.display === 'none' ||
|
|
387
|
+
element.style?.visibility === 'hidden' || element.style?.opacity === '0') return false;
|
|
388
|
+
if (String(module?.selectedNodeIdJs || module?.selectedNodeId || '') === nodeId ||
|
|
389
|
+
module?.multiSelectedNodeIds?.has?.(nodeId) === true || module?.draggedNodeId === nodeId ||
|
|
390
|
+
renderer?._getCurrentHoveredNodeId?.(module) === nodeId) return false;
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function hasAnimatedGifCssFallbackCandidates(renderer, module, isAnimatedGifModel) {
|
|
395
|
+
const nodeObjectsById = module?.nodeObjectsById || renderer?._module?.nodeObjectsById || null;
|
|
396
|
+
if (!nodeObjectsById || typeof isAnimatedGifModel !== 'function') return false;
|
|
397
|
+
const isGifId = (value) => {
|
|
398
|
+
const nodeId = String(value || '').trim();
|
|
399
|
+
return !!nodeId && isAnimatedGifModel(nodeObjectsById.get(nodeId)?.model) === true;
|
|
400
|
+
};
|
|
401
|
+
const scan = (ids) => {
|
|
402
|
+
if (!ids) return false;
|
|
403
|
+
for (const nodeId of ids) if (isGifId(nodeId)) return true;
|
|
404
|
+
return false;
|
|
405
|
+
};
|
|
406
|
+
const visibleIds = module?._visibleIds || null;
|
|
407
|
+
if (scan(visibleIds)) return true;
|
|
408
|
+
if (module?._prevVisibleIds !== visibleIds && scan(module?._prevVisibleIds)) return true;
|
|
409
|
+
if (isGifId(module?.selectedNodeIdJs) || scan(module?.multiSelectedNodeIds)) return true;
|
|
410
|
+
return scan(renderer?._lodImageCssFallbackNodeIds);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function hasResidentDirtyWork(renderer, camera, module, resolveLodBand, buildSelectionKey, isAnimatedGifModel) {
|
|
414
|
+
if (!renderer) return false;
|
|
415
|
+
const lodBand = camera && typeof resolveLodBand === 'function'
|
|
416
|
+
? resolveLodBand(Number(camera.position?.z || 0))
|
|
417
|
+
: renderer._currentLodBand;
|
|
418
|
+
if (renderer._instancesDirty === true || renderer._imageInstancesDirty === true ||
|
|
419
|
+
renderer._positionsOnlyDirty === true || renderer._isNodeArrayDirty === true ||
|
|
420
|
+
Number(renderer._dirtyPositionIds?.size || 0) > 0 || Number(renderer._pendingSelectionRefreshIds?.size || 0) > 0 ||
|
|
421
|
+
renderer._imageAtlasRebuildPending === true || Number(renderer._imageAtlasQueuedIds?.size || 0) > 0 ||
|
|
422
|
+
Number(renderer._imageAtlasLoadingIds?.size || 0) > 0 || Number(renderer._imageAtlasBatchReadyIds?.size || 0) > 0 ||
|
|
423
|
+
renderer._imageAtlasBatchActive === true || renderer._lodCleanupPending === true ||
|
|
424
|
+
renderer._deferLineRestorePending === true || renderer._hasPendingLineDetailRestore?.(lodBand) === true ||
|
|
425
|
+
Number(renderer._pendingLodVisibilityVersion ?? -1) >= 0 || renderer._fullResHandoffActive === true ||
|
|
426
|
+
renderer.isLoading === true || module?.isLoading === true || renderer._hasResidentLodInstances?.() !== true) return true;
|
|
427
|
+
const selectionKey = typeof buildSelectionKey === 'function'
|
|
428
|
+
? buildSelectionKey(module?.multiSelectedNodeIds || null, module?.selectedNodeIdJs || null)
|
|
429
|
+
: '';
|
|
430
|
+
if (renderer._lastAppliedLodSelectionKey !== selectionKey) return true;
|
|
431
|
+
const usesCssImageFallbacks = renderer._shouldUseCssImageFallbackInResidentLod?.(module, lodBand) === true;
|
|
432
|
+
const usesAnimatedGifFallbacks = hasAnimatedGifCssFallbackCandidates(renderer, module, isAnimatedGifModel);
|
|
433
|
+
const fallbackCount = Number(renderer._lodImageCssFallbackNodeIds?.size || 0);
|
|
434
|
+
if (!usesAnimatedGifFallbacks && fallbackCount <= 0) return false;
|
|
435
|
+
const activeFallbackCount = Number(renderer._getActiveCssMediaLodFallbackCount?.(module) || 0);
|
|
436
|
+
return (usesAnimatedGifFallbacks && activeFallbackCount <= 0) ||
|
|
437
|
+
(fallbackCount > 0 && (!(usesCssImageFallbacks || usesAnimatedGifFallbacks) || activeFallbackCount <= 0));
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function hasPendingNearCssWarmup(renderer, module, buildSelectionKey, isCss3dEnabled, supportsCss3dModel) {
|
|
441
|
+
if (!renderer || renderer.isInLODMode !== false) return false;
|
|
442
|
+
if (renderer._css3dProcessing === true || Number(renderer._css3dQueuedMap?.size || 0) > 0 ||
|
|
443
|
+
renderer._hasCss3dQueueItems?.() === true || Number(renderer._nearEntryBoostFrames || 0) > 0) return true;
|
|
444
|
+
const moduleRef = module || renderer._module || null;
|
|
445
|
+
const visibleIds = renderer._getNearVisibleIds?.(moduleRef) || null;
|
|
446
|
+
const nodeObjectsById = moduleRef?.nodeObjectsById || null;
|
|
447
|
+
if (!visibleIds || !nodeObjectsById || visibleIds.size === 0) return false;
|
|
448
|
+
const selectionKey = buildSelectionKey?.(moduleRef?.multiSelectedNodeIds || null, moduleRef?.selectedNodeIdJs || null) || '';
|
|
449
|
+
const stableKey = buildFullResKey(renderer._currentLodBand, moduleRef?._visibilityVersion || 0, selectionKey,
|
|
450
|
+
nodeObjectsById.size, visibleIds.size, renderer._nearCssVisibleIds?.size || 0,
|
|
451
|
+
renderer._activeFullResCssNodeIds?.size || 0, isCss3dEnabled?.(moduleRef) !== false, moduleRef, renderer);
|
|
452
|
+
if (stableKey && renderer._lastNearCssNoWorkKey === stableKey) return false;
|
|
453
|
+
for (const nodeId of visibleIds) {
|
|
454
|
+
if (renderer._nearCssVisibleIds?.has?.(nodeId)) continue;
|
|
455
|
+
const entry = nodeObjectsById.get(nodeId);
|
|
456
|
+
if (entry?.glObject && supportsCss3dModel?.(entry.model) === true) return true;
|
|
457
|
+
}
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function resetPreparedLayoutRecord(record) {
|
|
462
|
+
if (!record?.layoutPrepared) return;
|
|
463
|
+
const cssObject = record.cssObject;
|
|
464
|
+
const element = record.element;
|
|
465
|
+
if (cssObject?.userData) cssObject.userData._residentTransitionPrepared = false;
|
|
466
|
+
record.layoutPrepared = false;
|
|
467
|
+
if (cssObject?.visible !== true && element?.style) {
|
|
468
|
+
element.style.setProperty?.('display', 'none', 'important');
|
|
469
|
+
element.style.setProperty?.('visibility', 'visible', 'important');
|
|
470
|
+
element.style.setProperty?.('opacity', '1', 'important');
|
|
471
|
+
element.style.setProperty?.('pointer-events', record.pointerEvents || 'auto', 'important');
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function clearTransitionRecords(state) {
|
|
476
|
+
if (!state) return;
|
|
477
|
+
state.layoutEpoch = Number(state.layoutEpoch || 0) + 1;
|
|
478
|
+
if (state.layoutRetryTimer) clearTimeout(state.layoutRetryTimer);
|
|
479
|
+
for (const record of state.parked?.values?.() || []) resetPreparedLayoutRecord(record);
|
|
480
|
+
state.parked?.clear?.();
|
|
481
|
+
state.layoutQueue = null;
|
|
482
|
+
state.layoutCursor = 0;
|
|
483
|
+
state.layoutScheduled = false;
|
|
484
|
+
state.layoutFrameScheduled = false;
|
|
485
|
+
state.layoutRetryTimer = null;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function getTransitionState(renderer, module, nodeObjectsById) {
|
|
489
|
+
let state = residentTransitionStates.get(renderer);
|
|
490
|
+
if (!state || state.module !== module || state.nodeObjectsById !== nodeObjectsById) {
|
|
491
|
+
clearTransitionRecords(state);
|
|
492
|
+
state = {
|
|
493
|
+
renderer, module, nodeObjectsById, active: false, selectionKey: '', parked: new Map(),
|
|
494
|
+
layoutQueue: null, layoutCursor: 0, layoutScheduled: false, layoutFrameScheduled: false,
|
|
495
|
+
layoutRetryTimer: null, layoutEpoch: 0
|
|
496
|
+
};
|
|
497
|
+
residentTransitionStates.set(renderer, state);
|
|
498
|
+
}
|
|
499
|
+
return state;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function getResidentCssCacheKind(entry) {
|
|
503
|
+
const model = entry?.model || null;
|
|
504
|
+
const contentType = String(model?.contentType ?? model?.ContentType ?? '').trim().toLowerCase();
|
|
505
|
+
if (contentType === 'image') return 'image';
|
|
506
|
+
if (contentType === 'video' || contentType === 'embed' || contentType === 'templatelauncher') return contentType;
|
|
507
|
+
if (RESIDENT_CSS_CACHE_TEXT_TYPES.has(contentType)) return 'text';
|
|
508
|
+
const metadata = model?.metadata || model?.Metadata || null;
|
|
509
|
+
const nodeType = String(model?.nodeType ?? model?.NodeType ?? '').toLowerCase();
|
|
510
|
+
const semanticType = String(metadata?.SemanticType ?? metadata?.semanticType ?? '');
|
|
511
|
+
const agentId = metadata?.agentId ?? metadata?.AgentId;
|
|
512
|
+
return nodeType.startsWith('agent_') || semanticType === 'MindCanvasAgent' || semanticType === 'AgentCommand' ||
|
|
513
|
+
semanticType === 'BusinessAutomationNode' || (agentId != null && String(agentId).trim() !== '') ? 'text' : null;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function cacheResidentCssEntry(state, entry, nodeId, kind) {
|
|
517
|
+
const cssObject = entry?.cssObject || null;
|
|
518
|
+
if (!state?.active || !kind || entry?.isCssDirty === true || !cssObject?.element) return false;
|
|
519
|
+
const cssScene = state.module?.cssScene || state.module?.scene || null;
|
|
520
|
+
if (!cssScene || (cssObject.parent != null && cssObject.parent !== cssScene)) return false;
|
|
521
|
+
const id = String(nodeId || '');
|
|
522
|
+
const previous = state.parked.get(id) || null;
|
|
523
|
+
if (previous?.layoutPrepared === true &&
|
|
524
|
+
(previous.cssObject !== cssObject || previous.element !== cssObject.element)) resetPreparedLayoutRecord(previous);
|
|
525
|
+
state.parked.set(id, {
|
|
526
|
+
nodeId: id,
|
|
527
|
+
entry, cssObject, element: cssObject.element, parent: cssObject.parent, kind,
|
|
528
|
+
pointerEvents: previous?.pointerEvents ?? cssObject.element.style?.pointerEvents ?? '',
|
|
529
|
+
layoutEligible: previous?.layoutEligible === true,
|
|
530
|
+
layoutPrepared: previous?.layoutPrepared === true && previous.cssObject === cssObject && previous.element === cssObject.element,
|
|
531
|
+
selectionKey: state.selectionKey,
|
|
532
|
+
...getEntryContentState(entry)
|
|
533
|
+
});
|
|
534
|
+
state.layoutQueue = null;
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function cachePreparedResidentCss(renderer, entry, module, nodeObjectsById) {
|
|
539
|
+
const state = residentTransitionStates.get(renderer);
|
|
540
|
+
if (!state || state.module !== module || state.nodeObjectsById !== nodeObjectsById) return false;
|
|
541
|
+
const nodeId = entry?.model?.id || entry?.model?.Id || entry?.glObject?.userData?.nodeId || '';
|
|
542
|
+
const cached = cacheResidentCssEntry(state, entry, nodeId, getResidentCssCacheKind(entry));
|
|
543
|
+
if (cached) {
|
|
544
|
+
const record = state.parked.get(String(nodeId || ''));
|
|
545
|
+
if (record) record.layoutEligible = true;
|
|
546
|
+
scheduleResidentCssLayoutWarm(renderer, module, nodeObjectsById);
|
|
547
|
+
}
|
|
548
|
+
return cached;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function beginResidentCssTransition(renderer, module, nodeObjectsById, previousBand, nextBand, selectionKey) {
|
|
552
|
+
if (!renderer || !module || !nodeObjectsById) return false;
|
|
553
|
+
const state = getTransitionState(renderer, module, nodeObjectsById);
|
|
554
|
+
const enteringResident = previousBand === 'NORMAL' && nextBand === 'MID';
|
|
555
|
+
const returningFullRes = (previousBand === 'MID' || previousBand === 'FAR') && nextBand === 'NORMAL';
|
|
556
|
+
if (enteringResident) {
|
|
557
|
+
clearTransitionRecords(state);
|
|
558
|
+
state.active = true;
|
|
559
|
+
state.selectionKey = String(selectionKey || '');
|
|
560
|
+
for (const [nodeId, entry] of nodeObjectsById) {
|
|
561
|
+
cacheResidentCssEntry(state, entry, nodeId, getResidentCssCacheKind(entry));
|
|
562
|
+
}
|
|
563
|
+
} else if (!returningFullRes) {
|
|
564
|
+
clearTransitionRecords(state);
|
|
565
|
+
state.active = false;
|
|
566
|
+
state.selectionKey = '';
|
|
567
|
+
}
|
|
568
|
+
return enteringResident || (returningFullRes && state.active);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function getEntryContentState(entry) {
|
|
572
|
+
const model = entry?.model || null;
|
|
573
|
+
return {
|
|
574
|
+
model,
|
|
575
|
+
source: model?._visibleContent ?? model?.response ?? model?.Response ?? model?.content ?? model?.Content ?? '',
|
|
576
|
+
prompt: model?.prompt ?? model?.Prompt ?? '',
|
|
577
|
+
width: Number(model?.width || model?.Width || 0),
|
|
578
|
+
height: Number(model?.height || model?.Height || 0),
|
|
579
|
+
media: model?.thumbnailUrl ?? model?.ThumbnailUrl ?? model?.displayUrl ?? model?.DisplayUrl ?? ''
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function parkFullResCss(renderer, entry, module, nodeObjectsById, selectionKey, kind = 'text') {
|
|
584
|
+
const cssObject = entry?.cssObject || null;
|
|
585
|
+
const element = cssObject?.element || null;
|
|
586
|
+
const nodeId = String(entry?.model?.id || entry?.model?.Id || entry?.glObject?.userData?.nodeId || '').trim();
|
|
587
|
+
if (!renderer || !cssObject || !element || !nodeId) return false;
|
|
588
|
+
const state = getTransitionState(renderer, module, nodeObjectsById);
|
|
589
|
+
let cached = false;
|
|
590
|
+
if (state.active && state.selectionKey === String(selectionKey || '') && entry.isCssDirty !== true) {
|
|
591
|
+
cached = cacheResidentCssEntry(state, entry, nodeId, kind);
|
|
592
|
+
if (cached) {
|
|
593
|
+
const record = state.parked.get(nodeId);
|
|
594
|
+
if (record) record.layoutEligible = true;
|
|
595
|
+
renderer._residentCssParkCount = Number(renderer._residentCssParkCount || 0) + 1;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
cssObject.visible = false;
|
|
599
|
+
entry.currentType = 'GL';
|
|
600
|
+
if (element.style?.display !== 'none') {
|
|
601
|
+
element.style?.setProperty?.('display', 'none', 'important');
|
|
602
|
+
}
|
|
603
|
+
if (cached && !state.layoutRetryTimer) {
|
|
604
|
+
const epoch = state.layoutEpoch;
|
|
605
|
+
state.layoutRetryTimer = setTimeout(() => {
|
|
606
|
+
state.layoutRetryTimer = null;
|
|
607
|
+
if (residentTransitionStates.get(renderer) === state && state.layoutEpoch === epoch) {
|
|
608
|
+
scheduleResidentCssLayoutWarm(renderer, module, nodeObjectsById);
|
|
609
|
+
}
|
|
610
|
+
}, 0);
|
|
611
|
+
}
|
|
612
|
+
return true;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function scheduleResidentCssLayoutWarm(renderer, module, nodeObjectsById) {
|
|
616
|
+
const state = residentTransitionStates.get(renderer);
|
|
617
|
+
if (!state?.active || state.module !== module || state.nodeObjectsById !== nodeObjectsById ||
|
|
618
|
+
renderer?._disposed === true || renderer?.isInLODMode !== true || module?.isLoading === true) return false;
|
|
619
|
+
const visibleIds = module?._visibleIds || module?._prevVisibleIds || renderer?._visibleIds || null;
|
|
620
|
+
if (visibleIds?.size > 0) {
|
|
621
|
+
for (const nodeId of visibleIds) {
|
|
622
|
+
const record = state.parked.get(String(nodeId || ''));
|
|
623
|
+
if (record) record.layoutEligible = true;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (isPrewarmInteractionActive(module)) {
|
|
627
|
+
if (!state.layoutRetryTimer) {
|
|
628
|
+
const epoch = state.layoutEpoch;
|
|
629
|
+
state.layoutRetryTimer = setTimeout(() => {
|
|
630
|
+
state.layoutRetryTimer = null;
|
|
631
|
+
if (residentTransitionStates.get(renderer) === state && state.layoutEpoch === epoch) {
|
|
632
|
+
scheduleResidentCssLayoutWarm(renderer, module, nodeObjectsById);
|
|
633
|
+
}
|
|
634
|
+
}, 80);
|
|
635
|
+
}
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
if (state.layoutScheduled || state.layoutFrameScheduled) return false;
|
|
639
|
+
if (!state.layoutQueue) {
|
|
640
|
+
state.layoutQueue = [];
|
|
641
|
+
state.layoutCursor = 0;
|
|
642
|
+
for (const record of state.parked.values()) {
|
|
643
|
+
if (record.layoutEligible === true && record.layoutPrepared !== true) state.layoutQueue.push(record);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (state.layoutCursor >= state.layoutQueue.length) {
|
|
647
|
+
state.layoutQueue = null;
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
const epoch = state.layoutEpoch;
|
|
652
|
+
state.layoutScheduled = true;
|
|
653
|
+
const run = () => {
|
|
654
|
+
state.layoutScheduled = false;
|
|
655
|
+
if (residentTransitionStates.get(renderer) !== state || state.layoutEpoch !== epoch || !state.active ||
|
|
656
|
+
renderer?._disposed === true || renderer?.isInLODMode !== true || renderer?._module !== module ||
|
|
657
|
+
module?.nodeObjectsById !== nodeObjectsById || module?.isLoading === true) return;
|
|
658
|
+
if (isPrewarmInteractionActive(module)) {
|
|
659
|
+
state.layoutQueue = null;
|
|
660
|
+
scheduleResidentCssLayoutWarm(renderer, module, nodeObjectsById);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Visibility can expand while the wheel is still settling after
|
|
665
|
+
// NORMAL -> MID. Refresh from the latest set during idle so those
|
|
666
|
+
// CSS owners are not created synchronously on MID -> NORMAL.
|
|
667
|
+
const latestVisibleIds = module?._visibleIds || module?._prevVisibleIds || renderer?._visibleIds || null;
|
|
668
|
+
const latestPriority = latestVisibleIds?.size > 0
|
|
669
|
+
? renderer?._getNearVisiblePriority?.(latestVisibleIds, nodeObjectsById, module?.camera)
|
|
670
|
+
: null;
|
|
671
|
+
if (Array.isArray(latestPriority) && latestPriority.length > 0) {
|
|
672
|
+
renderer?._queueCss3dPrewarm?.(latestPriority, nodeObjectsById, module, 'MID');
|
|
673
|
+
}
|
|
674
|
+
if (residentTransitionStates.get(renderer) !== state || state.layoutEpoch !== epoch ||
|
|
675
|
+
!Array.isArray(state.layoutQueue)) return;
|
|
676
|
+
const layoutQueue = state.layoutQueue;
|
|
677
|
+
|
|
678
|
+
const startedAt = performance.now();
|
|
679
|
+
let prepared = 0;
|
|
680
|
+
while (state.layoutCursor < layoutQueue.length && prepared < 4 &&
|
|
681
|
+
(prepared === 0 || performance.now() - startedAt < 2)) {
|
|
682
|
+
const record = layoutQueue[state.layoutCursor++];
|
|
683
|
+
if (state.parked.get(record.nodeId) !== record || record.entry?.isCssDirty === true ||
|
|
684
|
+
record.cssObject?.visible === true || !record.element?.style) continue;
|
|
685
|
+
record.cssObject.userData = record.cssObject.userData || {};
|
|
686
|
+
record.cssObject.userData._residentTransitionPrepared = true;
|
|
687
|
+
record.element.style.setProperty?.('visibility', 'visible', 'important');
|
|
688
|
+
record.element.style.setProperty?.('opacity', '0', 'important');
|
|
689
|
+
record.element.style.setProperty?.('pointer-events', 'none', 'important');
|
|
690
|
+
record.element.style.setProperty?.('display', 'block', 'important');
|
|
691
|
+
record.layoutPrepared = true;
|
|
692
|
+
prepared++;
|
|
693
|
+
}
|
|
694
|
+
if (prepared > 0) {
|
|
695
|
+
renderer._residentCssLayoutWarmCount = Number(renderer._residentCssLayoutWarmCount || 0) + prepared;
|
|
696
|
+
module._css3dVisualChangedThisFrame = true;
|
|
697
|
+
module._css3dVisualChangedSinceLastRender = true;
|
|
698
|
+
}
|
|
699
|
+
if (state.layoutQueue !== layoutQueue) return;
|
|
700
|
+
if (state.layoutCursor < layoutQueue.length) {
|
|
701
|
+
state.layoutFrameScheduled = true;
|
|
702
|
+
const continueWarm = () => {
|
|
703
|
+
state.layoutFrameScheduled = false;
|
|
704
|
+
if (residentTransitionStates.get(renderer) === state && state.layoutEpoch === epoch) {
|
|
705
|
+
scheduleResidentCssLayoutWarm(renderer, module, nodeObjectsById);
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
if (typeof globalThis.requestAnimationFrame === 'function') globalThis.requestAnimationFrame(continueWarm);
|
|
709
|
+
else setTimeout(continueWarm, 16);
|
|
710
|
+
} else {
|
|
711
|
+
state.layoutQueue = null;
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
if (typeof globalThis.requestIdleCallback === 'function') globalThis.requestIdleCallback(run, { timeout: 120 });
|
|
715
|
+
else setTimeout(run, 16);
|
|
716
|
+
return true;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function parkReadyResidentImage(renderer, entry, module, nodeObjectsById, selectionKey, nodeId, animatedGif, selected, interactiveOwner) {
|
|
720
|
+
if (animatedGif === true || selected === true || interactiveOwner === true ||
|
|
721
|
+
renderer?._hasActiveImageLodInstance?.(nodeId) !== true) return false;
|
|
722
|
+
parkFullResCss(renderer, entry, module, nodeObjectsById, selectionKey, 'image');
|
|
723
|
+
renderer._hideImageLodFullVisual?.(entry);
|
|
724
|
+
renderer._setGlowVisibility?.(entry, false);
|
|
725
|
+
return true;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
function restoreParkedFullResCss(renderer, entry, module, nodeObjectsById, selectionKey, lodBand, nodeIdValue) {
|
|
729
|
+
if (!renderer || lodBand !== 'NORMAL') return false;
|
|
730
|
+
const state = residentTransitionStates.get(renderer);
|
|
731
|
+
const nodeId = String(nodeIdValue || entry?.model?.id || entry?.model?.Id || '').trim();
|
|
732
|
+
const record = state?.parked?.get?.(nodeId) || null;
|
|
733
|
+
const current = getEntryContentState(entry);
|
|
734
|
+
const cssScene = module?.cssScene || module?.scene || null;
|
|
735
|
+
const valid = !!record && state.module === module && state.nodeObjectsById === nodeObjectsById &&
|
|
736
|
+
record.entry === entry && record.model === current.model && record.cssObject === entry?.cssObject &&
|
|
737
|
+
record.element === entry?.cssObject?.element && cssScene &&
|
|
738
|
+
(record.parent == null || record.parent === cssScene) &&
|
|
739
|
+
(entry.cssObject.parent == null || entry.cssObject.parent === cssScene) && entry.isCssDirty !== true &&
|
|
740
|
+
record.selectionKey === String(selectionKey || '') && record.source === current.source &&
|
|
741
|
+
record.prompt === current.prompt && record.width === current.width && record.height === current.height &&
|
|
742
|
+
record.media === current.media;
|
|
743
|
+
if (!valid) {
|
|
744
|
+
if (record) {
|
|
745
|
+
resetPreparedLayoutRecord(record);
|
|
746
|
+
state.parked.delete(nodeId);
|
|
747
|
+
}
|
|
748
|
+
if (state?.active) renderer._residentCssRestoreMissCount = Number(renderer._residentCssRestoreMissCount || 0) + 1;
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
const cssObject = record.cssObject;
|
|
753
|
+
const element = record.element;
|
|
754
|
+
const layoutPrepared = record.layoutPrepared === true && cssObject.userData?._residentTransitionPrepared === true;
|
|
755
|
+
if (cssObject.userData) cssObject.userData._residentTransitionPrepared = false;
|
|
756
|
+
if (cssObject.parent !== cssScene) cssScene.add?.(cssObject);
|
|
757
|
+
if (entry.glObject) {
|
|
758
|
+
entry.glObject.updateWorldMatrix?.(true, false);
|
|
759
|
+
entry.glObject.matrixWorld?.decompose?.(renderer._tmpWorldPos, renderer._tmpWorldQuat, renderer._tmpWorldScale);
|
|
760
|
+
if (renderer._tmpWorldPos) cssObject.position?.copy?.(renderer._tmpWorldPos);
|
|
761
|
+
if (renderer._tmpWorldQuat) cssObject.quaternion?.copy?.(renderer._tmpWorldQuat);
|
|
762
|
+
entry.glObject.visible = true;
|
|
763
|
+
if (entry.bodyMesh) entry.bodyMesh.visible = false;
|
|
764
|
+
if (entry.tailMesh) entry.tailMesh.visible = false;
|
|
765
|
+
}
|
|
766
|
+
cssObject.visible = true;
|
|
767
|
+
if (!layoutPrepared && element.style?.display !== 'block') element.style?.setProperty?.('display', 'block', 'important');
|
|
768
|
+
if (element.style?.visibility !== 'visible') element.style?.setProperty?.('visibility', 'visible', 'important');
|
|
769
|
+
if (element.style?.opacity !== '1') element.style?.setProperty?.('opacity', '1', 'important');
|
|
770
|
+
if (layoutPrepared) element.style?.setProperty?.('pointer-events', record.pointerEvents || 'auto', 'important');
|
|
771
|
+
if (element.style?.transition !== 'none') element.style?.setProperty?.('transition', 'none', 'important');
|
|
772
|
+
const rootStyle = element.firstElementChild?.style || null;
|
|
773
|
+
if (rootStyle && rootStyle.getPropertyValue?.('content-visibility') !== 'visible') {
|
|
774
|
+
rootStyle.setProperty?.('content-visibility', 'visible', 'important');
|
|
775
|
+
rootStyle.setProperty?.('contain-intrinsic-size', 'auto', 'important');
|
|
776
|
+
}
|
|
777
|
+
cssObject.updateMatrixWorld?.(true);
|
|
778
|
+
entry.currentType = 'CSS';
|
|
779
|
+
renderer._setCss3dLodClass?.(entry, renderer._shouldUseHighCss3dDetail?.(entry, module) !== false);
|
|
780
|
+
renderer._nearCssVisibleIds?.add?.(nodeId);
|
|
781
|
+
if (record.kind === 'image') renderer._syncCssImageBodyBridge?.(entry, module);
|
|
782
|
+
if (record.kind === 'video') globalThis.MindMapCss3DManager?.syncVideoNodeVisibilityPlayback?.(entry.model, cssObject, true);
|
|
783
|
+
renderer._lodImageCssFallbackNodeIds?.delete?.(nodeId);
|
|
784
|
+
state.parked.delete(nodeId);
|
|
785
|
+
renderer._residentCssRestoreCount = Number(renderer._residentCssRestoreCount || 0) + 1;
|
|
786
|
+
module._css3dVisualChangedThisFrame = true;
|
|
787
|
+
module._css3dVisualChangedSinceLastRender = true;
|
|
788
|
+
return true;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function completeFullResTransition(renderer, allowedCssCount) {
|
|
792
|
+
if (!renderer || Number(renderer._nearCssVisibleIds?.size || 0) < Number(allowedCssCount || 0) ||
|
|
793
|
+
renderer._hasCss3dQueueItems?.() === true || Number(renderer._css3dQueuedMap?.size || 0) > 0) return false;
|
|
794
|
+
if (renderer._nearEntryBoostFrames > 0) renderer._residentBoostClearCount = Number(renderer._residentBoostClearCount || 0) + 1;
|
|
795
|
+
renderer._nearEntryBoostFrames = 0;
|
|
796
|
+
const state = residentTransitionStates.get(renderer);
|
|
797
|
+
if (state) {
|
|
798
|
+
clearTransitionRecords(state);
|
|
799
|
+
state.active = false;
|
|
800
|
+
}
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function ensureResidentLineDetails(renderer, lodBand) {
|
|
805
|
+
if (!renderer || lodBand !== 'MID') return false;
|
|
806
|
+
if (renderer.lineDataDirty === true || renderer._lineDetailsPatchPending === true) {
|
|
807
|
+
renderer._markLineDetailsDirty?.();
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
renderer._residentStableLineReuseCount = Number(renderer._residentStableLineReuseCount || 0) + 1;
|
|
811
|
+
if (renderer.instancedLineMesh) renderer.instancedLineMesh.visible = renderer._shouldShowInstancedLineMesh?.(lodBand) === true;
|
|
812
|
+
return true;
|
|
813
|
+
}
|
|
814
|
+
|
|
210
815
|
function reusePreparedImageInstances(renderer, state) {
|
|
211
816
|
if (renderer?.isInLODMode !== false || renderer?._imageInstancesDirtyReason !== 'image-slot-invalidated' ||
|
|
212
817
|
state?.imageCandidateIds?.size !== state?.imagePreparedIds?.size) return false;
|
|
@@ -221,17 +826,169 @@
|
|
|
221
826
|
return true;
|
|
222
827
|
}
|
|
223
828
|
|
|
829
|
+
function prepareIdleResidentImageInstances(state) {
|
|
830
|
+
const renderer = state?.renderer;
|
|
831
|
+
const module = state?.module;
|
|
832
|
+
const nodeObjectsById = state?.nodeObjectsById;
|
|
833
|
+
if (!renderer || !module || !nodeObjectsById || renderer._disposed === true ||
|
|
834
|
+
renderer._module !== module || module.nodeObjectsById !== nodeObjectsById ||
|
|
835
|
+
renderer.isInLODMode !== false || module.isLoading === true ||
|
|
836
|
+
isPrewarmInteractionActive(module) || renderer._hasPendingImageAtlasWork?.() === true ||
|
|
837
|
+
state.imageCandidateIds?.size !== state.imagePreparedIds?.size ||
|
|
838
|
+
typeof renderer._updateImageInstanceData !== 'function' ||
|
|
839
|
+
typeof renderer._applyImageInstanceData !== 'function') return false;
|
|
840
|
+
|
|
841
|
+
const committedIds = Array.isArray(renderer.imageInstanceData?.nodeIds)
|
|
842
|
+
? renderer.imageInstanceData.nodeIds
|
|
843
|
+
: [];
|
|
844
|
+
const committedSet = new Set(committedIds);
|
|
845
|
+
let missingPreparedImage = false;
|
|
846
|
+
for (const nodeId of state.imagePreparedIds) {
|
|
847
|
+
if (!committedSet.has(nodeId)) {
|
|
848
|
+
missingPreparedImage = true;
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
if (!missingPreparedImage && renderer._imageInstancesDirty !== true) return false;
|
|
853
|
+
|
|
854
|
+
renderer._updateImageInstanceData(nodeObjectsById, true);
|
|
855
|
+
renderer._applyImageInstanceData();
|
|
856
|
+
renderer._lastAppliedImageAtlasSignature =
|
|
857
|
+
renderer._pendingImageAtlasPatchSignature ||
|
|
858
|
+
renderer._buildImageAtlasPatchSignature?.() || '';
|
|
859
|
+
renderer._pendingImageAtlasPatchSignature = '';
|
|
860
|
+
renderer._imageAtlasRebuildPending = false;
|
|
861
|
+
renderer._imageAtlasRebuildDeferredUntil = 0;
|
|
862
|
+
renderer._clearImageInstancesDirty?.();
|
|
863
|
+
renderer._syncResidentCountsAfterDelta?.();
|
|
864
|
+
if (renderer.instancedImageMesh) renderer.instancedImageMesh.visible = false;
|
|
865
|
+
renderer._residentGpuWarmKey = '';
|
|
866
|
+
renderer._residentGpuWarmOffscreenComplete = false;
|
|
867
|
+
renderer._residentImageIdlePatchCount = Number(renderer._residentImageIdlePatchCount || 0) + 1;
|
|
868
|
+
return true;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
function stagePreparedResidentLineRow(state, entry, lineData) {
|
|
872
|
+
const renderer = state?.renderer;
|
|
873
|
+
const model = entry?.model || null;
|
|
874
|
+
const nodeId = String(model?.id || model?.Id || '');
|
|
875
|
+
const nodeIds = renderer?.instanceData?.nodeIds;
|
|
876
|
+
const geometry = renderer?.instancedMesh?.geometry || null;
|
|
877
|
+
const lineCountAttr = geometry?.getAttribute?.('instanceLineCount') || null;
|
|
878
|
+
const lineHeightAttr = geometry?.getAttribute?.('instanceLineHeightPx') || null;
|
|
879
|
+
const linePaddingAttr = geometry?.getAttribute?.('instanceLinePaddingPx') || null;
|
|
880
|
+
const lineDataArray = renderer?.lineDataArray || null;
|
|
881
|
+
const rowCount = Number(renderer?.lineTextureRows || 0);
|
|
882
|
+
if (!nodeId || !Array.isArray(nodeIds) || !lineData || !lineCountAttr || !lineHeightAttr ||
|
|
883
|
+
!linePaddingAttr || !lineDataArray || rowCount <= 0) return false;
|
|
884
|
+
if (state.lineNodeIds !== nodeIds) {
|
|
885
|
+
state.lineNodeIds = nodeIds;
|
|
886
|
+
state.lineIndexById = new Map();
|
|
887
|
+
for (let i = 0; i < nodeIds.length; i++) state.lineIndexById.set(String(nodeIds[i] || ''), i);
|
|
888
|
+
}
|
|
889
|
+
const index = state.lineIndexById.get(nodeId);
|
|
890
|
+
const rowWidth = Math.floor(lineDataArray.length / rowCount);
|
|
891
|
+
if (!Number.isInteger(index) || index < 0 || index >= lineCountAttr.count || rowWidth <= 0) return false;
|
|
892
|
+
const lineCounts = renderer.instanceData.lineCounts || (renderer.instanceData.lineCounts = []);
|
|
893
|
+
const lineLengths = renderer.instanceData.lineLengths || (renderer.instanceData.lineLengths = []);
|
|
894
|
+
const lineHeights = renderer.instanceData.lineHeights || (renderer.instanceData.lineHeights = []);
|
|
895
|
+
const linePaddings = renderer.instanceData.linePaddings || (renderer.instanceData.linePaddings = []);
|
|
896
|
+
const lineCount = Number(lineData.lineCount || 0);
|
|
897
|
+
const lineHeight = Number(lineData.lineHeightPx || 24);
|
|
898
|
+
const paddingX = Number(lineData.paddingX || 0);
|
|
899
|
+
const paddingY = Number(lineData.paddingY || 0);
|
|
900
|
+
lineCounts[index] = lineCount;
|
|
901
|
+
lineHeights[index] = lineHeight;
|
|
902
|
+
linePaddings[index * 2] = paddingX;
|
|
903
|
+
linePaddings[index * 2 + 1] = paddingY;
|
|
904
|
+
lineCountAttr.setX(index, lineCount);
|
|
905
|
+
lineHeightAttr.setX(index, lineHeight);
|
|
906
|
+
linePaddingAttr.setXY(index, paddingX, paddingY);
|
|
907
|
+
const base = index * rowWidth;
|
|
908
|
+
for (let j = 0; j < rowWidth; j++) {
|
|
909
|
+
const value = Number(lineData.lineLengths?.[j] || 0);
|
|
910
|
+
lineLengths[base + j] = value;
|
|
911
|
+
lineDataArray[base + j] = Math.max(0, Math.min(255, Math.round(value * 255)));
|
|
912
|
+
}
|
|
913
|
+
state.lineRowsStaged = true;
|
|
914
|
+
state.preparedLineRowCount = Number(state.preparedLineRowCount || 0) + 1;
|
|
915
|
+
return true;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
function commitPreparedResidentLineRows(state) {
|
|
919
|
+
if (!state?.lineRowsStaged) return false;
|
|
920
|
+
const renderer = state.renderer;
|
|
921
|
+
const geometry = renderer?.instancedMesh?.geometry || null;
|
|
922
|
+
const lineCountAttr = geometry?.getAttribute?.('instanceLineCount') || null;
|
|
923
|
+
const lineHeightAttr = geometry?.getAttribute?.('instanceLineHeightPx') || null;
|
|
924
|
+
const linePaddingAttr = geometry?.getAttribute?.('instanceLinePaddingPx') || null;
|
|
925
|
+
if (!lineCountAttr || !lineHeightAttr || !linePaddingAttr || !renderer?.lineDataTexture) return false;
|
|
926
|
+
lineCountAttr.needsUpdate = true;
|
|
927
|
+
lineHeightAttr.needsUpdate = true;
|
|
928
|
+
linePaddingAttr.needsUpdate = true;
|
|
929
|
+
renderer.lineDataTexture.needsUpdate = true;
|
|
930
|
+
renderer.lineDataDirty = false;
|
|
931
|
+
renderer._lineDetailsPatchPending = false;
|
|
932
|
+
renderer._lastInstanceCount = Number(renderer.instanceData?.nodeIds?.length || 0);
|
|
933
|
+
renderer._residentGpuWarmKey = '';
|
|
934
|
+
renderer._residentLineBufferPrewarmCount = Number(state.preparedLineRowCount || 0);
|
|
935
|
+
state.lineRowsStaged = false;
|
|
936
|
+
return true;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
function prepareIdleResidentBuffers(state) {
|
|
940
|
+
const renderer = state?.renderer;
|
|
941
|
+
const module = state?.module;
|
|
942
|
+
const nodeObjectsById = state?.nodeObjectsById;
|
|
943
|
+
if (!renderer || !module || !nodeObjectsById || renderer._disposed === true ||
|
|
944
|
+
renderer._module !== module || module.nodeObjectsById !== nodeObjectsById ||
|
|
945
|
+
renderer.isInLODMode !== false || renderer._hasResidentLodInstances?.() === true ||
|
|
946
|
+
module.isLoading === true || isPrewarmInteractionActive(module) ||
|
|
947
|
+
typeof renderer._updateInstanceData !== 'function' || typeof renderer._applyInstanceData !== 'function') return false;
|
|
948
|
+
renderer._residentBuildPhase = 'initial-build';
|
|
949
|
+
renderer._updateInstanceData(nodeObjectsById);
|
|
950
|
+
renderer._applyInstanceData();
|
|
951
|
+
renderer._syncResidentCountsAfterDelta?.();
|
|
952
|
+
renderer._lineDetailsPatchPending = renderer._residentLineFallbackUsed === true;
|
|
953
|
+
renderer._clearInstancesDirty?.();
|
|
954
|
+
renderer._clearImageInstancesDirty?.();
|
|
955
|
+
renderer._positionsOnlyDirty = false;
|
|
956
|
+
renderer._dirtyPositionIds?.clear?.();
|
|
957
|
+
renderer._residentRebuildPending = false;
|
|
958
|
+
renderer._residentRebuildDeferredUntil = 0;
|
|
959
|
+
renderer._noteResidentFullBuild?.('initial-build', 'MID');
|
|
960
|
+
renderer._residentIdleBuildCount = Number(renderer._residentIdleBuildCount || 0) + 1;
|
|
961
|
+
renderer._residentLineBufferPrewarmCount = Number(renderer.instanceData?.nodeIds?.length || 0);
|
|
962
|
+
renderer._residentGpuWarmKey = '';
|
|
963
|
+
[renderer.instancedMesh, renderer.instancedBorderLineMesh, renderer.instancedLineMesh,
|
|
964
|
+
renderer.instancedHaloMesh, renderer.instancedConsoleMesh, renderer.instancedImageMesh]
|
|
965
|
+
.filter(Boolean).forEach(mesh => { mesh.visible = false; });
|
|
966
|
+
renderer._setInstancedAgentBadgeVisibility?.(false);
|
|
967
|
+
renderer._setInstancedFarInsetBorderVisibility?.(false);
|
|
968
|
+
return renderer._hasResidentLodInstances?.() === true;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
function retryResidentPreparation(state, delay = 80) {
|
|
972
|
+
if (!state || state.retryTimer) return;
|
|
973
|
+
state.retryTimer = setTimeout(() => {
|
|
974
|
+
state.retryTimer = null;
|
|
975
|
+
if (residentLinePrewarmStates.get(state.renderer) !== state || state.renderer?._disposed === true ||
|
|
976
|
+
state.renderer?._module !== state.module || state.module?.nodeObjectsById !== state.nodeObjectsById) return;
|
|
977
|
+
scheduleResidentLinePrewarm(state.renderer, state.module, state.nodeObjectsById);
|
|
978
|
+
}, delay);
|
|
979
|
+
}
|
|
980
|
+
|
|
224
981
|
function queueResidentLinePrewarm(state) {
|
|
225
982
|
if (!state || state.scheduled || state.complete) return;
|
|
226
983
|
state.scheduled = true;
|
|
227
984
|
const run = deadline => {
|
|
228
985
|
state.scheduled = false;
|
|
229
986
|
if (residentLinePrewarmStates.get(state.renderer) !== state || state.renderer?._disposed === true ||
|
|
230
|
-
state.renderer?._module !== state.module ||
|
|
231
|
-
|
|
232
|
-
state.module?.isLoading === true ||
|
|
987
|
+
state.renderer?._module !== state.module || state.module?.nodeObjectsById !== state.nodeObjectsById) return;
|
|
988
|
+
if (state.module?.isLoading === true ||
|
|
233
989
|
state.key !== `${Number(state.renderer?._instancesDirtySerial || 0)}:${Number(state.nodeObjectsById.size || 0)}` ||
|
|
234
990
|
isPrewarmInteractionActive(state.module)) {
|
|
991
|
+
retryResidentPreparation(state);
|
|
235
992
|
return;
|
|
236
993
|
}
|
|
237
994
|
if (!state.entries) state.entries = Array.from(state.nodeObjectsById.values());
|
|
@@ -249,6 +1006,8 @@
|
|
|
249
1006
|
rememberPreparedLine(state.renderer, entry, width, height,
|
|
250
1007
|
state.renderer._getLineDataForNode?.(model, entry.lodSeed, width, height, entry));
|
|
251
1008
|
}
|
|
1009
|
+
stagePreparedResidentLineRow(state, entry,
|
|
1010
|
+
getPreparedLineData(state.renderer, entry, width, height));
|
|
252
1011
|
state.prepared++;
|
|
253
1012
|
} else if (model && contentType === 'image') {
|
|
254
1013
|
const nodeId = String(model.id || model.Id || '');
|
|
@@ -266,6 +1025,7 @@
|
|
|
266
1025
|
if (state.cursor >= state.entries.length) {
|
|
267
1026
|
if (state.pendingImageEntries.length > 0 && state.imagePass < 20) {
|
|
268
1027
|
const isFirstImagePass = state.imagePass === 0;
|
|
1028
|
+
if (isFirstImagePass) commitPreparedResidentLineRows(state);
|
|
269
1029
|
if (isFirstImagePass) prepareImageAtlasCapacity(state.renderer, state.imageCandidateIds.size);
|
|
270
1030
|
state.entries = Array.from(new Set(state.pendingImageEntries));
|
|
271
1031
|
state.pendingImageEntries.length = 0;
|
|
@@ -280,6 +1040,8 @@
|
|
|
280
1040
|
}
|
|
281
1041
|
return;
|
|
282
1042
|
}
|
|
1043
|
+
prepareIdleResidentBuffers(state);
|
|
1044
|
+
commitPreparedResidentLineRows(state);
|
|
283
1045
|
state.complete = true;
|
|
284
1046
|
state.renderer._residentLinePrewarmCount = state.prepared;
|
|
285
1047
|
state.renderer._residentImagePrewarmCount = state.imagePreparedIds.size;
|
|
@@ -288,6 +1050,7 @@
|
|
|
288
1050
|
if (state.renderer.isInLODMode === true && state.renderer._lineDetailsPatchPending === true) {
|
|
289
1051
|
state.renderer._markLineDetailsDirty?.();
|
|
290
1052
|
}
|
|
1053
|
+
prepareIdleResidentImageInstances(state);
|
|
291
1054
|
queueResidentGpuWarm(state);
|
|
292
1055
|
return;
|
|
293
1056
|
}
|
|
@@ -301,7 +1064,76 @@
|
|
|
301
1064
|
}
|
|
302
1065
|
|
|
303
1066
|
function getResidentGpuKey(renderer) {
|
|
304
|
-
|
|
1067
|
+
const geometryKey = [renderer?.instancedMesh, renderer?.instancedBorderLineMesh, renderer?.instancedLineMesh,
|
|
1068
|
+
renderer?.instancedHaloMesh, renderer?.instancedConsoleMesh, renderer?.instancedImageMesh]
|
|
1069
|
+
.map(mesh => String(mesh?.geometry?.uuid || '-')).join(',');
|
|
1070
|
+
return `${Number(renderer?._residentGpuContextGeneration || 0)}:` +
|
|
1071
|
+
`${String(renderer?.lineDataTexture?.uuid || '-')}/${Number(renderer?.lineDataTexture?.version || 0)}:` +
|
|
1072
|
+
`${String(renderer?.imageAtlasTexture?.uuid || '-')}/${Number(renderer?.imageAtlasTexture?.version || 0)}:` +
|
|
1073
|
+
`${Number(renderer?.lineTextureRows || 0)}:${geometryKey}`;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
function invalidateResidentGpuWarm(renderer) {
|
|
1077
|
+
if (!renderer) return;
|
|
1078
|
+
renderer._residentGpuContextGeneration = Number(renderer._residentGpuContextGeneration || 0) + 1;
|
|
1079
|
+
renderer._residentGpuWarmKey = '';
|
|
1080
|
+
renderer._residentGpuWarmComplete = false;
|
|
1081
|
+
renderer._residentGpuWarmOffscreenComplete = false;
|
|
1082
|
+
renderer._residentImageAtlasWarmVersion = -1;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
function ensureResidentGpuContextTracking(renderer) {
|
|
1086
|
+
const canvas = renderer?.renderer?.domElement || null;
|
|
1087
|
+
if (!canvas?.addEventListener || renderer._residentGpuContextCanvas === canvas) return;
|
|
1088
|
+
const previousCanvas = renderer._residentGpuContextCanvas;
|
|
1089
|
+
if (previousCanvas?.removeEventListener) {
|
|
1090
|
+
previousCanvas.removeEventListener('webglcontextlost', renderer._residentGpuContextLostHandler);
|
|
1091
|
+
previousCanvas.removeEventListener('webglcontextrestored', renderer._residentGpuContextRestoredHandler);
|
|
1092
|
+
}
|
|
1093
|
+
const lost = () => {
|
|
1094
|
+
renderer._residentGpuContextLost = true;
|
|
1095
|
+
invalidateResidentGpuWarm(renderer);
|
|
1096
|
+
};
|
|
1097
|
+
const restored = () => {
|
|
1098
|
+
renderer._residentGpuContextLost = false;
|
|
1099
|
+
invalidateResidentGpuWarm(renderer);
|
|
1100
|
+
setTimeout(() => {
|
|
1101
|
+
const state = residentLinePrewarmStates.get(renderer);
|
|
1102
|
+
if (state && renderer?._disposed !== true) queueResidentGpuWarm(state);
|
|
1103
|
+
}, 0);
|
|
1104
|
+
};
|
|
1105
|
+
canvas.addEventListener('webglcontextlost', lost);
|
|
1106
|
+
canvas.addEventListener('webglcontextrestored', restored);
|
|
1107
|
+
renderer._residentGpuContextCanvas = canvas;
|
|
1108
|
+
renderer._residentGpuContextLostHandler = lost;
|
|
1109
|
+
renderer._residentGpuContextRestoredHandler = restored;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
function renderResidentWarmScene(webglRenderer, THREE, warmScene, warmCamera) {
|
|
1113
|
+
const gl = webglRenderer?.getContext?.();
|
|
1114
|
+
if (!gl || gl.isContextLost?.() === true) return false;
|
|
1115
|
+
if (typeof webglRenderer.getRenderTarget !== 'function' || typeof webglRenderer.setRenderTarget !== 'function' ||
|
|
1116
|
+
typeof webglRenderer.render !== 'function' || !THREE?.WebGLRenderTarget) return null;
|
|
1117
|
+
const previousTarget = webglRenderer.getRenderTarget();
|
|
1118
|
+
const previousFace = webglRenderer.getActiveCubeFace?.() ?? 0;
|
|
1119
|
+
const previousMip = webglRenderer.getActiveMipmapLevel?.() ?? 0;
|
|
1120
|
+
const warmTarget = new THREE.WebGLRenderTarget(1, 1, { depthBuffer: false, stencilBuffer: false });
|
|
1121
|
+
if (warmTarget.texture) {
|
|
1122
|
+
warmTarget.texture.generateMipmaps = false;
|
|
1123
|
+
const encoding = previousTarget?.texture?.encoding ?? webglRenderer.outputEncoding;
|
|
1124
|
+
if (encoding != null) warmTarget.texture.encoding = encoding;
|
|
1125
|
+
}
|
|
1126
|
+
try {
|
|
1127
|
+
webglRenderer.setRenderTarget(warmTarget);
|
|
1128
|
+
webglRenderer.render(warmScene, warmCamera);
|
|
1129
|
+
return gl.isContextLost?.() !== true;
|
|
1130
|
+
} finally {
|
|
1131
|
+
try {
|
|
1132
|
+
webglRenderer.setRenderTarget(previousTarget, previousFace, previousMip);
|
|
1133
|
+
} finally {
|
|
1134
|
+
warmTarget.dispose?.();
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
305
1137
|
}
|
|
306
1138
|
|
|
307
1139
|
function retryResidentGpuWarm(state) {
|
|
@@ -324,6 +1156,9 @@
|
|
|
324
1156
|
return;
|
|
325
1157
|
}
|
|
326
1158
|
const webglRenderer = renderer?.renderer || null;
|
|
1159
|
+
ensureResidentGpuContextTracking(renderer);
|
|
1160
|
+
const gl = webglRenderer?.getContext?.();
|
|
1161
|
+
if (renderer?._residentGpuContextLost === true || gl?.isContextLost?.() === true) return;
|
|
327
1162
|
const gpuKey = getResidentGpuKey(renderer);
|
|
328
1163
|
if (!webglRenderer || renderer._residentGpuWarmKey === gpuKey) return;
|
|
329
1164
|
if (renderer._hasPendingImageAtlasWork?.() === true) {
|
|
@@ -340,6 +1175,7 @@
|
|
|
340
1175
|
retryResidentGpuWarm(state);
|
|
341
1176
|
return;
|
|
342
1177
|
}
|
|
1178
|
+
if (renderer?._residentGpuContextLost === true || webglRenderer?.getContext?.()?.isContextLost?.() === true) return;
|
|
343
1179
|
try {
|
|
344
1180
|
if (renderer.lineDataTexture) webglRenderer.initTexture?.(renderer.lineDataTexture);
|
|
345
1181
|
if (renderer.imageAtlasTexture && Number(renderer.imageAtlasSlots?.size || 0) > 0) {
|
|
@@ -349,18 +1185,25 @@
|
|
|
349
1185
|
const THREE = globalThis.THREE;
|
|
350
1186
|
if (THREE?.Scene && typeof webglRenderer.compile === 'function' && state.module?.camera) {
|
|
351
1187
|
const warmScene = new THREE.Scene();
|
|
352
|
-
|
|
353
|
-
renderer.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
1188
|
+
try {
|
|
1189
|
+
[renderer.instancedMesh, renderer.instancedBorderLineMesh, renderer.instancedLineMesh,
|
|
1190
|
+
renderer.instancedHaloMesh, renderer.instancedConsoleMesh, renderer.instancedImageMesh]
|
|
1191
|
+
.filter(Boolean)
|
|
1192
|
+
.forEach(mesh => {
|
|
1193
|
+
const clone = mesh.clone?.();
|
|
1194
|
+
if (!clone) return;
|
|
1195
|
+
clone.visible = true;
|
|
1196
|
+
clone.frustumCulled = false;
|
|
1197
|
+
warmScene.add(clone);
|
|
1198
|
+
});
|
|
1199
|
+
const warmCamera = state.module.camera.clone?.() || state.module.camera;
|
|
1200
|
+
webglRenderer.compile(warmScene, warmCamera);
|
|
1201
|
+
const offscreenResult = renderResidentWarmScene(webglRenderer, THREE, warmScene, warmCamera);
|
|
1202
|
+
if (offscreenResult === false) return;
|
|
1203
|
+
renderer._residentGpuWarmOffscreenComplete = offscreenResult === true;
|
|
1204
|
+
} finally {
|
|
1205
|
+
warmScene.clear?.();
|
|
1206
|
+
}
|
|
364
1207
|
}
|
|
365
1208
|
renderer._residentGpuWarmKey = getResidentGpuKey(renderer);
|
|
366
1209
|
renderer._residentGpuWarmComplete = true;
|
|
@@ -381,6 +1224,7 @@
|
|
|
381
1224
|
|
|
382
1225
|
function scheduleResidentLinePrewarm(renderer, module, nodeObjectsById) {
|
|
383
1226
|
if (!renderer || !module || !nodeObjectsById?.values || module.isLoading === true) return;
|
|
1227
|
+
scheduleResidentCssLayoutWarm(renderer, module, nodeObjectsById);
|
|
384
1228
|
const key = `${Number(renderer._instancesDirtySerial || 0)}:${Number(nodeObjectsById.size || 0)}`;
|
|
385
1229
|
let state = residentLinePrewarmStates.get(renderer);
|
|
386
1230
|
if (!state || state.key !== key || state.nodeObjectsById !== nodeObjectsById) {
|
|
@@ -395,7 +1239,7 @@
|
|
|
395
1239
|
prepareImageAtlasCapacity(renderer, imageCandidateIds.size);
|
|
396
1240
|
state = {
|
|
397
1241
|
renderer, module, nodeObjectsById, key, entries, cursor: 0, prepared: 0,
|
|
398
|
-
scheduled: false, complete: false, gpuScheduled: false, gpuRetryTimer: null, gpuFailureCount: 0,
|
|
1242
|
+
scheduled: false, retryTimer: null, complete: false, gpuScheduled: false, gpuRetryTimer: null, gpuFailureCount: 0,
|
|
399
1243
|
imagePass: 0, imageCandidateIds, imagePreparedIds: new Set(), pendingImageEntries: []
|
|
400
1244
|
};
|
|
401
1245
|
residentLinePrewarmStates.set(renderer, state);
|
|
@@ -420,7 +1264,10 @@
|
|
|
420
1264
|
}
|
|
421
1265
|
}
|
|
422
1266
|
queueResidentLinePrewarm(state);
|
|
423
|
-
if (state.complete)
|
|
1267
|
+
if (state.complete) {
|
|
1268
|
+
prepareIdleResidentImageInstances(state);
|
|
1269
|
+
queueResidentGpuWarm(state);
|
|
1270
|
+
}
|
|
424
1271
|
}
|
|
425
1272
|
|
|
426
1273
|
function areResidentLinesPrepared(renderer, nodeObjectsById, nodeIds) {
|
|
@@ -511,6 +1358,46 @@
|
|
|
511
1358
|
return Number(values[Math.max(0, Math.ceil(values.length * ratio) - 1)].toFixed(2));
|
|
512
1359
|
}
|
|
513
1360
|
|
|
1361
|
+
function getImageAtlasProbe(renderer) {
|
|
1362
|
+
const canvas = renderer?.imageAtlasCanvas || null;
|
|
1363
|
+
const readyEntry = Array.from(renderer?.imageAtlasSlots?.entries?.() || [])
|
|
1364
|
+
.find(([, slot]) => slot?.ready === true) || null;
|
|
1365
|
+
if (!canvas || !readyEntry) return '-';
|
|
1366
|
+
try {
|
|
1367
|
+
const slot = readyEntry[1];
|
|
1368
|
+
const columns = Number(renderer.imageAtlasColumns || 1);
|
|
1369
|
+
const tile = Math.max(1, Math.floor(Number(canvas.width || 1) / columns));
|
|
1370
|
+
const col = Number(slot.slotIndex || 0) % columns;
|
|
1371
|
+
const row = Math.floor(Number(slot.slotIndex || 0) / columns);
|
|
1372
|
+
const context = canvas.getContext?.('2d', { alpha: false }) || null;
|
|
1373
|
+
const pixel = context?.getImageData?.(
|
|
1374
|
+
Math.min(canvas.width - 1, Math.floor(col * tile + tile * 0.5)),
|
|
1375
|
+
Math.min(canvas.height - 1, Math.floor(row * tile + tile * 0.5)), 1, 1)?.data;
|
|
1376
|
+
let colored = 0;
|
|
1377
|
+
let sampled = 0;
|
|
1378
|
+
for (const [, candidate] of Array.from(renderer.imageAtlasSlots.entries()).slice(0, 24)) {
|
|
1379
|
+
if (candidate?.ready !== true) continue;
|
|
1380
|
+
const candidateCol = Number(candidate.slotIndex || 0) % columns;
|
|
1381
|
+
const candidateRow = Math.floor(Number(candidate.slotIndex || 0) / columns);
|
|
1382
|
+
const sample = context?.getImageData?.(
|
|
1383
|
+
Math.min(canvas.width - 1, Math.floor(candidateCol * tile + tile * 0.5)),
|
|
1384
|
+
Math.min(canvas.height - 1, Math.floor(candidateRow * tile + tile * 0.5)), 1, 1)?.data;
|
|
1385
|
+
if (sample) {
|
|
1386
|
+
sampled++;
|
|
1387
|
+
if (Math.abs(sample[0] - 238) + Math.abs(sample[1] - 242) + Math.abs(sample[2] - 247) > 12) colored++;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
const cpuUv = Array.from(renderer?.imageInstanceData?.uvRects || []).slice(0, 4)
|
|
1391
|
+
.map(value => Number(value || 0).toFixed(4)).join(',');
|
|
1392
|
+
const uvAttr = renderer?.instancedImageMesh?.geometry?.getAttribute?.('instanceUvRect') || null;
|
|
1393
|
+
const gpuUv = uvAttr && uvAttr.count > 0
|
|
1394
|
+
? [uvAttr.getX(0), uvAttr.getY(0), uvAttr.getZ(0), uvAttr.getW(0)]
|
|
1395
|
+
.map(value => Number(value || 0).toFixed(4)).join(',')
|
|
1396
|
+
: '-';
|
|
1397
|
+
return pixel ? `${pixel[0]},${pixel[1]},${pixel[2]} · color ${colored}/${sampled} · uv ${cpuUv}/${gpuUv}` : '-';
|
|
1398
|
+
} catch { return 'blocked'; }
|
|
1399
|
+
}
|
|
1400
|
+
|
|
514
1401
|
function getDiagnostics(renderer) {
|
|
515
1402
|
const state = renderer ? frameSampleStates.get(renderer) : null;
|
|
516
1403
|
let stableFullResSampleCount = 0;
|
|
@@ -528,14 +1415,43 @@
|
|
|
528
1415
|
visibilityP95Ms: percentile(state, 'visibilityMs', 0.95),
|
|
529
1416
|
viewSyncP95Ms: percentile(state, 'viewSyncMs', 0.95),
|
|
530
1417
|
css3dRenderP95Ms: percentile(state, 'css3dRenderMs', 0.95),
|
|
1418
|
+
fullResCssStableReuseCount: Number(renderer?._fullResCssStableReuseCount || 0),
|
|
1419
|
+
cssMediaFrameDomReuseCount,
|
|
1420
|
+
cssMediaFrameDomApplyCount,
|
|
531
1421
|
residentLinePrewarmCount: Number(renderer?._residentLinePrewarmCount || 0),
|
|
1422
|
+
residentLineBufferPrewarmCount: Number(renderer?._residentLineBufferPrewarmCount || 0),
|
|
1423
|
+
residentIdleBuildCount: Number(renderer?._residentIdleBuildCount || 0),
|
|
532
1424
|
residentImagePrewarmCount: Number(renderer?._residentImagePrewarmCount || 0),
|
|
533
1425
|
residentImagePrewarmCandidateCount: Number(renderer?._residentImagePrewarmCandidateCount || 0),
|
|
534
1426
|
residentImageBufferReuseCount: Number(renderer?._residentImageBufferReuseCount || 0),
|
|
1427
|
+
residentImageIdlePatchCount: Number(renderer?._residentImageIdlePatchCount || 0),
|
|
1428
|
+
residentImageInstanceCount: Number(renderer?.instancedImageMesh?.geometry?.instanceCount || 0),
|
|
1429
|
+
residentImageMeshVisible: renderer?.instancedImageMesh?.visible === true,
|
|
1430
|
+
residentImageAtlasReadyCount: Array.from(renderer?.imageAtlasSlots?.values?.() || [])
|
|
1431
|
+
.filter(slot => slot?.ready === true).length,
|
|
1432
|
+
residentImageAtlasProbe: getImageAtlasProbe(renderer),
|
|
1433
|
+
residentBuildPhase: String(renderer?._residentBuildPhase || ''),
|
|
1434
|
+
residentFullBuildCount: Number(renderer?._residentFullBuildCount || 0),
|
|
1435
|
+
residentLastFullBuildReason: String(renderer?._lastResidentFullBuildReason || ''),
|
|
1436
|
+
residentInstancesDirtyReason: renderer?._instancesDirty === true
|
|
1437
|
+
? String(renderer?._instancesDirtyReason || 'unknown')
|
|
1438
|
+
: '',
|
|
1439
|
+
residentInstancesDirtySerial: Number(renderer?._instancesDirtySerial || 0),
|
|
1440
|
+
residentLastNodeCount: Number(renderer?._lastNodeCount || 0),
|
|
1441
|
+
residentEligibleTextLikeCount: Number(renderer?._cachedEligibleTextLikeCount || 0),
|
|
1442
|
+
residentBufferNodeCount: Number(renderer?.instanceData?.nodeIds?.length || 0),
|
|
1443
|
+
residentCssParkCount: Number(renderer?._residentCssParkCount || 0),
|
|
1444
|
+
residentCssRestoreCount: Number(renderer?._residentCssRestoreCount || 0),
|
|
1445
|
+
residentCssRestoreMissCount: Number(renderer?._residentCssRestoreMissCount || 0),
|
|
1446
|
+
residentCssLayoutWarmCount: Number(renderer?._residentCssLayoutWarmCount || 0),
|
|
1447
|
+
residentStableLineReuseCount: Number(renderer?._residentStableLineReuseCount || 0),
|
|
1448
|
+
residentBoostClearCount: Number(renderer?._residentBoostClearCount || 0),
|
|
535
1449
|
lineTextureRows: Number(renderer?.lineTextureRows || 0),
|
|
536
1450
|
residentGpuWarmComplete: !!renderer &&
|
|
537
1451
|
renderer._hasPendingImageAtlasWork?.() !== true &&
|
|
538
1452
|
renderer._residentGpuWarmKey === getResidentGpuKey(renderer),
|
|
1453
|
+
residentGpuBufferWarmComplete: !!renderer && renderer._residentGpuWarmOffscreenComplete === true &&
|
|
1454
|
+
renderer._residentGpuWarmKey === getResidentGpuKey(renderer),
|
|
539
1455
|
residentAtlasWarmComplete: !!renderer && Number(renderer.imageAtlasSlots?.size || 0) > 0 &&
|
|
540
1456
|
renderer._hasPendingImageAtlasWork?.() !== true &&
|
|
541
1457
|
Number(renderer._residentImageAtlasWarmVersion ?? -1) === Number(renderer.imageAtlasTexture?.version || 0)
|
|
@@ -547,9 +1463,16 @@
|
|
|
547
1463
|
frameSampleStates.delete(renderer);
|
|
548
1464
|
renderer._fullResStablePlanSkipCount = 0;
|
|
549
1465
|
renderer._lastFullResStablePlanSkipped = false;
|
|
1466
|
+
renderer._fullResCssStableReuseCount = 0;
|
|
1467
|
+
cssMediaFrameDomReuseCount = 0;
|
|
1468
|
+
cssMediaFrameDomApplyCount = 0;
|
|
550
1469
|
}
|
|
551
1470
|
|
|
552
1471
|
window.MindMapRenderPlan = Object.freeze({
|
|
1472
|
+
configureImageAtlasTexture,
|
|
1473
|
+
getImageAtlasOutputColorChunk,
|
|
1474
|
+
syncCommittedResidentTextCount,
|
|
1475
|
+
clearFullResImageVisuals,
|
|
553
1476
|
buildFullResKey,
|
|
554
1477
|
shouldSkipStableFullRes,
|
|
555
1478
|
commitStableFullRes,
|
|
@@ -559,9 +1482,28 @@
|
|
|
559
1482
|
areResidentLinesPrepared,
|
|
560
1483
|
initialLineTextureRows,
|
|
561
1484
|
ensureLineTextureCapacity,
|
|
1485
|
+
renderResidentWarmScene,
|
|
562
1486
|
prepareImageAtlasCapacity,
|
|
563
1487
|
fallbackBatch,
|
|
1488
|
+
reuseCssMediaFrameDom,
|
|
1489
|
+
reuseStableVisibleCss,
|
|
1490
|
+
reuseActiveCssMediaFallback,
|
|
1491
|
+
hasAnimatedGifCssFallbackCandidates,
|
|
1492
|
+
hasResidentDirtyWork,
|
|
1493
|
+
hasPendingNearCssWarmup,
|
|
564
1494
|
reusePreparedImageInstances,
|
|
1495
|
+
prepareIdleResidentImageInstances,
|
|
1496
|
+
stagePreparedResidentLineRow,
|
|
1497
|
+
commitPreparedResidentLineRows,
|
|
1498
|
+
prepareIdleResidentBuffers,
|
|
1499
|
+
beginResidentCssTransition,
|
|
1500
|
+
cachePreparedResidentCss,
|
|
1501
|
+
scheduleResidentCssLayoutWarm,
|
|
1502
|
+
parkFullResCss,
|
|
1503
|
+
parkReadyResidentImage,
|
|
1504
|
+
restoreParkedFullResCss,
|
|
1505
|
+
completeFullResTransition,
|
|
1506
|
+
ensureResidentLineDetails,
|
|
565
1507
|
beginFrame,
|
|
566
1508
|
recordFrame,
|
|
567
1509
|
getDiagnostics,
|