@mindexec/cli 0.2.430 → 0.2.432
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 +4 -4
- package/scripts/npm-fresh-install-smoke.mjs +216 -0
- package/wwwroot/_content/MindExecution.Shared/css/mind-map-overrides.css +5 -35
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +9 -5
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +64 -92
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-render-plan.js +572 -0
- package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +67 -10
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.hdpod01n2v.dll → MindExecution.Plugins.Concept.slcp5au0e8.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.bcxkqs35nn.dll → MindExecution.Plugins.PlanMaster.nk8wgsetbw.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.gg4bv7zo0e.dll → MindExecution.Plugins.YouTube.rrrfswr6up.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.acb35gyigd.dll → MindExecution.Shared.23xj2d2olw.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.6grqlsq22z.dll → MindExecution.Web.4a5lf7nem7.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +11 -11
- package/wwwroot/index.html +6 -5
- package/wwwroot/service-worker-assets.js +21 -17
- package/wwwroot/service-worker.js +1 -1
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const BUILD_ID = '20260712-stable-fullres-plan-v12';
|
|
5
|
+
const FRAME_SAMPLE_LIMIT = 240;
|
|
6
|
+
const INITIAL_LINE_TEXTURE_ROWS = 1024;
|
|
7
|
+
const GPU_WARM_RETRY_DELAY_MS = 120;
|
|
8
|
+
const IMAGE_ATLAS_TILE_SIZE = 128;
|
|
9
|
+
const frameSampleStates = new WeakMap();
|
|
10
|
+
const residentLinePrewarmStates = new WeakMap();
|
|
11
|
+
const VIEW_SYNC_SECTION_KEYS = [
|
|
12
|
+
'fullResSetup', 'fullResImages', 'fullResCssQueue', 'fullResHandoff', 'fullResOther',
|
|
13
|
+
'lodCleanup', 'lodNodeScan', 'lodResidentApply', 'lodImageInstances',
|
|
14
|
+
'lodPositionPatch', 'lodFallbacks', 'lodOther'
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
function isFullResMotionOptimizationActive(module) {
|
|
18
|
+
return (module?._viewSyncMotionActive === true ||
|
|
19
|
+
module?.isPanning === true ||
|
|
20
|
+
module?.isZooming === true ||
|
|
21
|
+
module?._fullResMotionFrozen === true) &&
|
|
22
|
+
module?.isDraggingNode !== true &&
|
|
23
|
+
module?.isDraggingMultipleNodes !== true &&
|
|
24
|
+
module?.isResizing !== true &&
|
|
25
|
+
module?.isWindowResizing !== true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function buildFullResKey(
|
|
29
|
+
lodBand,
|
|
30
|
+
visibilityVersion,
|
|
31
|
+
selectionKey,
|
|
32
|
+
nodeCount,
|
|
33
|
+
visibleCount,
|
|
34
|
+
nearVisibleCount,
|
|
35
|
+
allowedCssCount,
|
|
36
|
+
css3dEnabled,
|
|
37
|
+
module,
|
|
38
|
+
renderer) {
|
|
39
|
+
return [
|
|
40
|
+
String(lodBand || ''),
|
|
41
|
+
Number(visibilityVersion || 0),
|
|
42
|
+
String(selectionKey || ''),
|
|
43
|
+
Number(nodeCount || 0),
|
|
44
|
+
Number(visibleCount || 0),
|
|
45
|
+
Number(nearVisibleCount || 0),
|
|
46
|
+
Number(allowedCssCount || 0),
|
|
47
|
+
css3dEnabled === false ? 'css3d:off' : 'css3d:on',
|
|
48
|
+
String(module?.draggedNodeId || ''),
|
|
49
|
+
String(module?._textOverlayV2State?.editing?.nodeId || ''),
|
|
50
|
+
String(module?._editingOverlayState?.nodeId || ''),
|
|
51
|
+
String(module?._textOverlayV2State?.selectionNodeId || ''),
|
|
52
|
+
String(renderer?._getCurrentHoveredNodeId?.(module) || ''),
|
|
53
|
+
isFullResMotionOptimizationActive(module) ? 'motion:on' : 'motion:off'
|
|
54
|
+
].join('|');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function hasPendingFullResWork(renderer, module, bandChanged, cssReadinessDrift) {
|
|
58
|
+
return !renderer || !module ||
|
|
59
|
+
bandChanged === true ||
|
|
60
|
+
cssReadinessDrift === true ||
|
|
61
|
+
renderer._hasCss3dQueueItems?.() === true ||
|
|
62
|
+
Number(renderer._css3dQueuedMap?.size || 0) > 0 ||
|
|
63
|
+
renderer._css3dProcessing === true ||
|
|
64
|
+
Number(renderer._nearEntryBoostFrames || 0) > 0 ||
|
|
65
|
+
renderer._fullResHandoffActive === true ||
|
|
66
|
+
module._fullResMotionFrozen === true ||
|
|
67
|
+
module._cssParentRepairNeeded === true ||
|
|
68
|
+
module._css3dVisualChangedThisFrame === true ||
|
|
69
|
+
module._css3dVisualChangedSinceLastRender === true ||
|
|
70
|
+
Number(module._cssTransformDirtyIds?.size || 0) > 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function shouldSkipStableFullRes(renderer, module, key, bandChanged) {
|
|
74
|
+
const canSkip = !!key &&
|
|
75
|
+
renderer?._lastNearCssNoWorkKey === key &&
|
|
76
|
+
hasPendingFullResWork(renderer, module, bandChanged, false) !== true;
|
|
77
|
+
|
|
78
|
+
if (renderer) {
|
|
79
|
+
renderer._lastFullResStablePlanSkipped = canSkip;
|
|
80
|
+
if (canSkip) {
|
|
81
|
+
renderer._fullResStablePlanSkipCount = Number(renderer._fullResStablePlanSkipCount || 0) + 1;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return canSkip;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function commitStableFullRes(renderer, module, key, bandChanged, cssReadinessDrift) {
|
|
89
|
+
if (!key || renderer?._lastNearCssNoWorkKey !== key ||
|
|
90
|
+
hasPendingFullResWork(renderer, module, bandChanged, cssReadinessDrift)) {
|
|
91
|
+
if (renderer) renderer._lastFullResStablePlanSkipped = false;
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
renderer._lastNearCssNoWorkKey = key;
|
|
96
|
+
renderer._lastFullResStablePlanSkipped = false;
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getLineModelSource(model) {
|
|
101
|
+
return model?._visibleContent ?? model?.response ?? model?.Response ??
|
|
102
|
+
model?.content ?? model?.Content ?? model?.text ?? model?.Text ?? '';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getPreparedLineData(renderer, entry, width, height) {
|
|
106
|
+
const prepared = entry?._lodResidentPreparedLine || null;
|
|
107
|
+
const model = entry?.model || null;
|
|
108
|
+
const nodeId = model?.id || model?.Id || '';
|
|
109
|
+
const element = entry?.cssObject?.element || null;
|
|
110
|
+
if (!prepared || !model || !nodeId ||
|
|
111
|
+
prepared.data !== renderer?.lineDataCache?.get?.(nodeId) ||
|
|
112
|
+
prepared.model !== model ||
|
|
113
|
+
prepared.width !== Number(width || 0) ||
|
|
114
|
+
prepared.height !== Number(height || 0) ||
|
|
115
|
+
prepared.source !== getLineModelSource(model) ||
|
|
116
|
+
prepared.prompt !== (model?.prompt ?? model?.Prompt ?? '') ||
|
|
117
|
+
prepared.elementClass !== String(element?.className || '') ||
|
|
118
|
+
prepared.rootClass !== String(globalThis.document?.documentElement?.className || '') ||
|
|
119
|
+
prepared.viewportWidth !== Number(globalThis.innerWidth || 0) ||
|
|
120
|
+
prepared.viewportHeight !== Number(globalThis.innerHeight || 0)) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
return prepared.data;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function rememberPreparedLine(renderer, entry, width, height, data) {
|
|
127
|
+
const model = entry?.model || null;
|
|
128
|
+
const element = entry?.cssObject?.element || null;
|
|
129
|
+
if (!model || !data) return data || null;
|
|
130
|
+
entry._lodResidentPreparedLine = {
|
|
131
|
+
data,
|
|
132
|
+
model,
|
|
133
|
+
width: Number(width || 0),
|
|
134
|
+
height: Number(height || 0),
|
|
135
|
+
source: getLineModelSource(model),
|
|
136
|
+
prompt: model?.prompt ?? model?.Prompt ?? '',
|
|
137
|
+
elementClass: String(element?.className || ''),
|
|
138
|
+
rootClass: String(globalThis.document?.documentElement?.className || ''),
|
|
139
|
+
viewportWidth: Number(globalThis.innerWidth || 0),
|
|
140
|
+
viewportHeight: Number(globalThis.innerHeight || 0)
|
|
141
|
+
};
|
|
142
|
+
return data;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function resolveResidentLineData(renderer, entry, width, height, allowExact, maxSamples, lineHeight, padding) {
|
|
146
|
+
const prepared = getPreparedLineData(renderer, entry, width, height);
|
|
147
|
+
if (prepared) return prepared;
|
|
148
|
+
const model = entry?.model || null;
|
|
149
|
+
if (!renderer || !model) return null;
|
|
150
|
+
if (allowExact === true) {
|
|
151
|
+
return rememberPreparedLine(renderer, entry, width, height,
|
|
152
|
+
renderer._getLineDataForNode?.(model, entry.lodSeed, width, height, entry));
|
|
153
|
+
}
|
|
154
|
+
renderer._residentLineFallbackUsed = true;
|
|
155
|
+
const safeLineHeight = Math.max(1, Number(lineHeight || 1));
|
|
156
|
+
const safePadding = Math.max(0, Number(padding || 0));
|
|
157
|
+
const maxLines = Math.max(1, Math.min(
|
|
158
|
+
Number(maxSamples || 1),
|
|
159
|
+
Math.floor(Math.max(safeLineHeight, Number(height || 0) - safePadding * 2) / safeLineHeight)
|
|
160
|
+
));
|
|
161
|
+
const fallback = renderer._computeFallbackLineData?.(entry.lodSeed, maxLines) || { lineCount: 0, lineLengths: [] };
|
|
162
|
+
return {
|
|
163
|
+
lineCount: Number(fallback.lineCount || 0),
|
|
164
|
+
lineLengths: fallback.lineLengths || [],
|
|
165
|
+
lineHeightPx: safeLineHeight,
|
|
166
|
+
paddingX: safePadding,
|
|
167
|
+
paddingY: safePadding
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function isPrewarmInteractionActive(module) {
|
|
172
|
+
return module?.isPanning === true || module?.isZooming === true ||
|
|
173
|
+
module?.isDraggingNode === true || module?.isDraggingMultipleNodes === true ||
|
|
174
|
+
module?.isResizing === true || module?.isWindowResizing === true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function prepareImageAtlasCapacity(renderer, imageCount) {
|
|
178
|
+
if (!renderer?.imageAtlasCanvas || Number(renderer.imageAtlasSlots?.size || 0) > 0) return false;
|
|
179
|
+
let columns = 8;
|
|
180
|
+
const targetSlots = Math.max(1, Number(imageCount || 0) * 2);
|
|
181
|
+
while (columns < 32 && columns * columns < targetSlots) columns *= 2;
|
|
182
|
+
const size = columns * IMAGE_ATLAS_TILE_SIZE;
|
|
183
|
+
renderer.imageAtlasColumns = columns;
|
|
184
|
+
renderer.imageAtlasSize = size;
|
|
185
|
+
renderer.imageAtlasMaxSlots = columns * columns;
|
|
186
|
+
if (renderer.imageAtlasCanvas.width === size && renderer.imageAtlasCanvas.height === size) return false;
|
|
187
|
+
renderer.imageAtlasCanvas.width = size;
|
|
188
|
+
renderer.imageAtlasCanvas.height = size;
|
|
189
|
+
const context = renderer.imageAtlasCanvas.getContext?.('2d', { alpha: false }) || null;
|
|
190
|
+
if (context) {
|
|
191
|
+
context.fillStyle = '#eef2f7';
|
|
192
|
+
context.fillRect(0, 0, size, size);
|
|
193
|
+
}
|
|
194
|
+
if (renderer.imageAtlasTexture) renderer.imageAtlasTexture.needsUpdate = true;
|
|
195
|
+
renderer._residentGpuWarmKey = '';
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function fallbackBatch(renderer, fallbackIds, limit = 12) {
|
|
200
|
+
const ids = Array.from(fallbackIds || []);
|
|
201
|
+
const safeLimit = Math.max(1, Number(limit || 1));
|
|
202
|
+
if (ids.length <= safeLimit) return ids;
|
|
203
|
+
const cursor = Math.max(0, Number(renderer?._residentFallbackCleanupCursor || 0)) % ids.length;
|
|
204
|
+
const batch = [];
|
|
205
|
+
for (let i = 0; i < safeLimit; i++) batch.push(ids[(cursor + i) % ids.length]);
|
|
206
|
+
if (renderer) renderer._residentFallbackCleanupCursor = (cursor + safeLimit) % ids.length;
|
|
207
|
+
return batch;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function reusePreparedImageInstances(renderer, state) {
|
|
211
|
+
if (renderer?.isInLODMode !== false || renderer?._imageInstancesDirtyReason !== 'image-slot-invalidated' ||
|
|
212
|
+
state?.imageCandidateIds?.size !== state?.imagePreparedIds?.size) return false;
|
|
213
|
+
const priorIds = Array.isArray(renderer.imageInstanceData?.nodeIds) ? renderer.imageInstanceData.nodeIds : [];
|
|
214
|
+
if (priorIds.length !== state.imagePreparedIds.size) return false;
|
|
215
|
+
for (let i = 0; i < priorIds.length; i++) {
|
|
216
|
+
const nodeId = priorIds[i];
|
|
217
|
+
if (!state.imagePreparedIds.has(nodeId) || renderer.imageAtlasSlots?.get?.(nodeId)?.ready !== true) return false;
|
|
218
|
+
}
|
|
219
|
+
renderer._clearImageInstancesDirty?.();
|
|
220
|
+
renderer._residentImageBufferReuseCount = Number(renderer._residentImageBufferReuseCount || 0) + 1;
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function queueResidentLinePrewarm(state) {
|
|
225
|
+
if (!state || state.scheduled || state.complete) return;
|
|
226
|
+
state.scheduled = true;
|
|
227
|
+
const run = deadline => {
|
|
228
|
+
state.scheduled = false;
|
|
229
|
+
if (residentLinePrewarmStates.get(state.renderer) !== state || state.renderer?._disposed === true ||
|
|
230
|
+
state.renderer?._module !== state.module ||
|
|
231
|
+
state.module?.nodeObjectsById !== state.nodeObjectsById ||
|
|
232
|
+
state.module?.isLoading === true ||
|
|
233
|
+
state.key !== `${Number(state.renderer?._instancesDirtySerial || 0)}:${Number(state.nodeObjectsById.size || 0)}` ||
|
|
234
|
+
isPrewarmInteractionActive(state.module)) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (!state.entries) state.entries = Array.from(state.nodeObjectsById.values());
|
|
238
|
+
const startedAt = performance.now();
|
|
239
|
+
let processed = 0;
|
|
240
|
+
while (state.cursor < state.entries.length && processed < 4) {
|
|
241
|
+
const entry = state.entries[state.cursor++];
|
|
242
|
+
const model = entry?.model || null;
|
|
243
|
+
const contentType = String(model?.contentType ?? model?.ContentType ?? '').toLowerCase();
|
|
244
|
+
if (model && !['image', 'video', 'youtube', 'pdf', 'audio', 'webpage', 'iframe'].includes(contentType)) {
|
|
245
|
+
const width = Number(model.width || 400);
|
|
246
|
+
const height = Number(model.height || 200);
|
|
247
|
+
if (entry.lodSeed === undefined) entry.lodSeed = Math.random() * 100;
|
|
248
|
+
if (!getPreparedLineData(state.renderer, entry, width, height)) {
|
|
249
|
+
rememberPreparedLine(state.renderer, entry, width, height,
|
|
250
|
+
state.renderer._getLineDataForNode?.(model, entry.lodSeed, width, height, entry));
|
|
251
|
+
}
|
|
252
|
+
state.prepared++;
|
|
253
|
+
} else if (model && contentType === 'image') {
|
|
254
|
+
const nodeId = String(model.id || model.Id || '');
|
|
255
|
+
if (nodeId) state.imageCandidateIds.add(nodeId);
|
|
256
|
+
const slot = state.imagePass > 0 ? state.renderer._ensureImageLodThumbnail?.(entry) || null : null;
|
|
257
|
+
if (slot?.ready === true) {
|
|
258
|
+
if (nodeId) state.imagePreparedIds.add(nodeId);
|
|
259
|
+
} else {
|
|
260
|
+
state.pendingImageEntries.push(entry);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
processed++;
|
|
264
|
+
if (performance.now() - startedAt >= 3 && Number(deadline?.timeRemaining?.() || 0) < 1) break;
|
|
265
|
+
}
|
|
266
|
+
if (state.cursor >= state.entries.length) {
|
|
267
|
+
if (state.pendingImageEntries.length > 0 && state.imagePass < 20) {
|
|
268
|
+
const isFirstImagePass = state.imagePass === 0;
|
|
269
|
+
if (isFirstImagePass) prepareImageAtlasCapacity(state.renderer, state.imageCandidateIds.size);
|
|
270
|
+
state.entries = Array.from(new Set(state.pendingImageEntries));
|
|
271
|
+
state.pendingImageEntries.length = 0;
|
|
272
|
+
state.cursor = 0;
|
|
273
|
+
state.imagePass++;
|
|
274
|
+
if (isFirstImagePass) {
|
|
275
|
+
queueResidentLinePrewarm(state);
|
|
276
|
+
} else {
|
|
277
|
+
setTimeout(() => {
|
|
278
|
+
if (residentLinePrewarmStates.get(state.renderer) === state) queueResidentLinePrewarm(state);
|
|
279
|
+
}, 250);
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
state.complete = true;
|
|
284
|
+
state.renderer._residentLinePrewarmCount = state.prepared;
|
|
285
|
+
state.renderer._residentImagePrewarmCount = state.imagePreparedIds.size;
|
|
286
|
+
state.renderer._residentImagePrewarmCandidateCount = state.imageCandidateIds.size;
|
|
287
|
+
state.renderer._residentImagePrewarmComplete = state.pendingImageEntries.length === 0;
|
|
288
|
+
if (state.renderer.isInLODMode === true && state.renderer._lineDetailsPatchPending === true) {
|
|
289
|
+
state.renderer._markLineDetailsDirty?.();
|
|
290
|
+
}
|
|
291
|
+
queueResidentGpuWarm(state);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
queueResidentLinePrewarm(state);
|
|
295
|
+
};
|
|
296
|
+
if (typeof globalThis.requestIdleCallback === 'function') {
|
|
297
|
+
globalThis.requestIdleCallback(run, { timeout: 120 });
|
|
298
|
+
} else {
|
|
299
|
+
setTimeout(() => run({ timeRemaining: () => 3, didTimeout: true }), 16);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function getResidentGpuKey(renderer) {
|
|
304
|
+
return `${Number(renderer?.lineDataTexture?.version || 0)}:${Number(renderer?.imageAtlasTexture?.version || 0)}:${Number(renderer?.lineTextureRows || 0)}`;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function retryResidentGpuWarm(state) {
|
|
308
|
+
if (!state || state.gpuRetryTimer) return;
|
|
309
|
+
state.gpuRetryTimer = setTimeout(() => {
|
|
310
|
+
state.gpuRetryTimer = null;
|
|
311
|
+
if (residentLinePrewarmStates.get(state.renderer) === state) queueResidentGpuWarm(state);
|
|
312
|
+
}, GPU_WARM_RETRY_DELAY_MS);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function queueResidentGpuWarm(state) {
|
|
316
|
+
if (!state?.complete || state.gpuScheduled) return;
|
|
317
|
+
const renderer = state.renderer;
|
|
318
|
+
if (residentLinePrewarmStates.get(renderer) !== state || renderer?._disposed === true ||
|
|
319
|
+
renderer?._module !== state.module || state.module?.nodeObjectsById !== state.nodeObjectsById ||
|
|
320
|
+
state.module?.isLoading === true ||
|
|
321
|
+
state.key !== `${Number(renderer?._instancesDirtySerial || 0)}:${Number(state.nodeObjectsById.size || 0)}`) return;
|
|
322
|
+
if (isPrewarmInteractionActive(state.module)) {
|
|
323
|
+
retryResidentGpuWarm(state);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const webglRenderer = renderer?.renderer || null;
|
|
327
|
+
const gpuKey = getResidentGpuKey(renderer);
|
|
328
|
+
if (!webglRenderer || renderer._residentGpuWarmKey === gpuKey) return;
|
|
329
|
+
if (renderer._hasPendingImageAtlasWork?.() === true) {
|
|
330
|
+
retryResidentGpuWarm(state);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
state.gpuScheduled = true;
|
|
334
|
+
const run = () => {
|
|
335
|
+
state.gpuScheduled = false;
|
|
336
|
+
if (residentLinePrewarmStates.get(renderer) !== state || renderer?._disposed === true ||
|
|
337
|
+
renderer?._module !== state.module || state.module?.nodeObjectsById !== state.nodeObjectsById ||
|
|
338
|
+
state.module?.isLoading === true || state.key !== `${Number(renderer._instancesDirtySerial || 0)}:${Number(state.nodeObjectsById.size || 0)}`) return;
|
|
339
|
+
if (isPrewarmInteractionActive(state.module) || renderer._hasPendingImageAtlasWork?.() === true) {
|
|
340
|
+
retryResidentGpuWarm(state);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
try {
|
|
344
|
+
if (renderer.lineDataTexture) webglRenderer.initTexture?.(renderer.lineDataTexture);
|
|
345
|
+
if (renderer.imageAtlasTexture && Number(renderer.imageAtlasSlots?.size || 0) > 0) {
|
|
346
|
+
webglRenderer.initTexture?.(renderer.imageAtlasTexture);
|
|
347
|
+
renderer._residentImageAtlasWarmVersion = Number(renderer.imageAtlasTexture.version || 0);
|
|
348
|
+
}
|
|
349
|
+
const THREE = globalThis.THREE;
|
|
350
|
+
if (THREE?.Scene && typeof webglRenderer.compile === 'function' && state.module?.camera) {
|
|
351
|
+
const warmScene = new THREE.Scene();
|
|
352
|
+
[renderer.instancedMesh, renderer.instancedBorderLineMesh, renderer.instancedLineMesh,
|
|
353
|
+
renderer.instancedHaloMesh, renderer.instancedConsoleMesh, renderer.instancedImageMesh]
|
|
354
|
+
.filter(Boolean)
|
|
355
|
+
.forEach(mesh => {
|
|
356
|
+
const clone = mesh.clone?.();
|
|
357
|
+
if (!clone) return;
|
|
358
|
+
clone.visible = true;
|
|
359
|
+
clone.frustumCulled = false;
|
|
360
|
+
warmScene.add(clone);
|
|
361
|
+
});
|
|
362
|
+
webglRenderer.compile(warmScene, state.module.camera);
|
|
363
|
+
warmScene.clear?.();
|
|
364
|
+
}
|
|
365
|
+
renderer._residentGpuWarmKey = getResidentGpuKey(renderer);
|
|
366
|
+
renderer._residentGpuWarmComplete = true;
|
|
367
|
+
reusePreparedImageInstances(renderer, state);
|
|
368
|
+
state.gpuFailureCount = 0;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
console.warn('[RenderPlan] Resident GPU warmup deferred.', error);
|
|
371
|
+
state.gpuFailureCount = Number(state.gpuFailureCount || 0) + 1;
|
|
372
|
+
if (state.gpuFailureCount <= 3) retryResidentGpuWarm(state);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
if (typeof globalThis.requestIdleCallback === 'function') {
|
|
376
|
+
globalThis.requestIdleCallback(run, { timeout: 300 });
|
|
377
|
+
} else {
|
|
378
|
+
setTimeout(run, 32);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function scheduleResidentLinePrewarm(renderer, module, nodeObjectsById) {
|
|
383
|
+
if (!renderer || !module || !nodeObjectsById?.values || module.isLoading === true) return;
|
|
384
|
+
const key = `${Number(renderer._instancesDirtySerial || 0)}:${Number(nodeObjectsById.size || 0)}`;
|
|
385
|
+
let state = residentLinePrewarmStates.get(renderer);
|
|
386
|
+
if (!state || state.key !== key || state.nodeObjectsById !== nodeObjectsById) {
|
|
387
|
+
const entries = Array.from(nodeObjectsById.values());
|
|
388
|
+
const imageCandidateIds = new Set();
|
|
389
|
+
for (let i = 0; i < entries.length; i++) {
|
|
390
|
+
const model = entries[i]?.model || null;
|
|
391
|
+
if (String(model?.contentType ?? model?.ContentType ?? '').toLowerCase() !== 'image') continue;
|
|
392
|
+
const nodeId = String(model?.id || model?.Id || '');
|
|
393
|
+
if (nodeId) imageCandidateIds.add(nodeId);
|
|
394
|
+
}
|
|
395
|
+
prepareImageAtlasCapacity(renderer, imageCandidateIds.size);
|
|
396
|
+
state = {
|
|
397
|
+
renderer, module, nodeObjectsById, key, entries, cursor: 0, prepared: 0,
|
|
398
|
+
scheduled: false, complete: false, gpuScheduled: false, gpuRetryTimer: null, gpuFailureCount: 0,
|
|
399
|
+
imagePass: 0, imageCandidateIds, imagePreparedIds: new Set(), pendingImageEntries: []
|
|
400
|
+
};
|
|
401
|
+
residentLinePrewarmStates.set(renderer, state);
|
|
402
|
+
}
|
|
403
|
+
if (state.complete && renderer.isInLODMode === false &&
|
|
404
|
+
renderer._imageInstancesDirtyReason === 'image-slot-invalidated') {
|
|
405
|
+
const staleImageEntries = [];
|
|
406
|
+
for (const nodeId of state.imageCandidateIds) {
|
|
407
|
+
if (renderer.imageAtlasSlots?.get?.(nodeId)?.ready === true) continue;
|
|
408
|
+
const entry = nodeObjectsById.get?.(nodeId) || null;
|
|
409
|
+
if (entry) {
|
|
410
|
+
state.imagePreparedIds.delete(nodeId);
|
|
411
|
+
staleImageEntries.push(entry);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (staleImageEntries.length > 0) {
|
|
415
|
+
state.entries = staleImageEntries;
|
|
416
|
+
state.cursor = 0;
|
|
417
|
+
state.complete = false;
|
|
418
|
+
state.imagePass = 1;
|
|
419
|
+
state.pendingImageEntries.length = 0;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
queueResidentLinePrewarm(state);
|
|
423
|
+
if (state.complete) queueResidentGpuWarm(state);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function areResidentLinesPrepared(renderer, nodeObjectsById, nodeIds) {
|
|
427
|
+
if (!renderer || !nodeObjectsById?.get || !Array.isArray(nodeIds)) return false;
|
|
428
|
+
for (let i = 0; i < nodeIds.length; i++) {
|
|
429
|
+
const entry = nodeObjectsById.get(nodeIds[i]);
|
|
430
|
+
const model = entry?.model || null;
|
|
431
|
+
if (!model || !getPreparedLineData(renderer, entry, model.width || 400, model.height || 200)) return false;
|
|
432
|
+
}
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function initialLineTextureRows(maxInstances) {
|
|
437
|
+
return Math.min(Math.max(1, Number(maxInstances || 1)), INITIAL_LINE_TEXTURE_ROWS);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function ensureLineTextureCapacity(renderer, requiredCount, width) {
|
|
441
|
+
const currentRows = Number(renderer?.lineTextureRows || 0);
|
|
442
|
+
const maxRows = Math.max(1, Number(renderer?.maxInstances || requiredCount || 1));
|
|
443
|
+
if (!renderer || Number(requiredCount || 0) <= currentRows || currentRows >= maxRows) return false;
|
|
444
|
+
let nextRows = Math.max(INITIAL_LINE_TEXTURE_ROWS, currentRows || 1);
|
|
445
|
+
while (nextRows < requiredCount && nextRows < maxRows) nextRows *= 2;
|
|
446
|
+
nextRows = Math.min(nextRows, maxRows);
|
|
447
|
+
const THREE = globalThis.THREE;
|
|
448
|
+
if (!THREE?.DataTexture) return false;
|
|
449
|
+
const rowWidth = Math.max(1, Number(width || 1));
|
|
450
|
+
const data = new Uint8Array(nextRows * rowWidth);
|
|
451
|
+
data.set(renderer.lineDataArray?.subarray?.(0, data.length) || []);
|
|
452
|
+
const previous = renderer.lineDataTexture || null;
|
|
453
|
+
const texture = new THREE.DataTexture(data, rowWidth, nextRows, THREE.RedFormat, THREE.UnsignedByteType);
|
|
454
|
+
texture.minFilter = previous?.minFilter ?? THREE.NearestFilter;
|
|
455
|
+
texture.magFilter = previous?.magFilter ?? THREE.NearestFilter;
|
|
456
|
+
texture.wrapS = previous?.wrapS ?? THREE.ClampToEdgeWrapping;
|
|
457
|
+
texture.wrapT = previous?.wrapT ?? THREE.ClampToEdgeWrapping;
|
|
458
|
+
texture.needsUpdate = true;
|
|
459
|
+
renderer.lineDataArray = data;
|
|
460
|
+
renderer.lineDataTexture = texture;
|
|
461
|
+
renderer.lineTextureRows = nextRows;
|
|
462
|
+
renderer._residentGpuWarmKey = '';
|
|
463
|
+
const uniforms = renderer.instancedLineMesh?.material?.uniforms || null;
|
|
464
|
+
if (uniforms?.uLineDataTex) uniforms.uLineDataTex.value = texture;
|
|
465
|
+
if (uniforms?.uLineDataSize?.value?.set) uniforms.uLineDataSize.value.set(rowWidth, nextRows);
|
|
466
|
+
previous?.dispose?.();
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function getFrameSampleState(renderer) {
|
|
471
|
+
let state = frameSampleStates.get(renderer);
|
|
472
|
+
if (!state) {
|
|
473
|
+
state = { samples: new Array(FRAME_SAMPLE_LIMIT), cursor: 0, count: 0 };
|
|
474
|
+
frameSampleStates.set(renderer, state);
|
|
475
|
+
}
|
|
476
|
+
return state;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function recordFrame(renderer, profile) {
|
|
480
|
+
if (!renderer || !profile) return;
|
|
481
|
+
const state = getFrameSampleState(renderer);
|
|
482
|
+
const sections = profile.sections || {};
|
|
483
|
+
let viewSyncMs = 0;
|
|
484
|
+
for (let i = 0; i < VIEW_SYNC_SECTION_KEYS.length; i++) {
|
|
485
|
+
viewSyncMs += Number(sections[VIEW_SYNC_SECTION_KEYS[i]] || 0);
|
|
486
|
+
}
|
|
487
|
+
const sample = state.samples[state.cursor] || {};
|
|
488
|
+
sample.frameMs = Number(profile.durationMs || 0);
|
|
489
|
+
sample.visibilityMs = Number(sections.visibility || 0);
|
|
490
|
+
sample.viewSyncMs = viewSyncMs;
|
|
491
|
+
sample.css3dRenderMs = Number(sections.css3dRender || 0);
|
|
492
|
+
sample.stableFullResSkipped = renderer._lastFullResStablePlanSkipped === true;
|
|
493
|
+
state.samples[state.cursor] = sample;
|
|
494
|
+
state.cursor = (state.cursor + 1) % FRAME_SAMPLE_LIMIT;
|
|
495
|
+
state.count = Math.min(FRAME_SAMPLE_LIMIT, state.count + 1);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
function beginFrame(renderer) {
|
|
499
|
+
if (renderer) renderer._lastFullResStablePlanSkipped = false;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function percentile(state, field, ratio) {
|
|
503
|
+
if (!state?.count) return 0;
|
|
504
|
+
const values = [];
|
|
505
|
+
for (let i = 0; i < state.count; i++) {
|
|
506
|
+
const value = Number(state.samples[i]?.[field] || 0);
|
|
507
|
+
if (Number.isFinite(value)) values.push(value);
|
|
508
|
+
}
|
|
509
|
+
if (values.length === 0) return 0;
|
|
510
|
+
values.sort((a, b) => a - b);
|
|
511
|
+
return Number(values[Math.max(0, Math.ceil(values.length * ratio) - 1)].toFixed(2));
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function getDiagnostics(renderer) {
|
|
515
|
+
const state = renderer ? frameSampleStates.get(renderer) : null;
|
|
516
|
+
let stableFullResSampleCount = 0;
|
|
517
|
+
for (let i = 0; i < Number(state?.count || 0); i++) {
|
|
518
|
+
if (state.samples[i]?.stableFullResSkipped === true) stableFullResSampleCount++;
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
build: BUILD_ID,
|
|
522
|
+
stableFullResSkipCount: Number(renderer?._fullResStablePlanSkipCount || 0),
|
|
523
|
+
skippedLastPlan: renderer?._lastFullResStablePlanSkipped === true,
|
|
524
|
+
sampleCount: Number(state?.count || 0),
|
|
525
|
+
stableFullResSampleCount,
|
|
526
|
+
frameP50Ms: percentile(state, 'frameMs', 0.50),
|
|
527
|
+
frameP95Ms: percentile(state, 'frameMs', 0.95),
|
|
528
|
+
visibilityP95Ms: percentile(state, 'visibilityMs', 0.95),
|
|
529
|
+
viewSyncP95Ms: percentile(state, 'viewSyncMs', 0.95),
|
|
530
|
+
css3dRenderP95Ms: percentile(state, 'css3dRenderMs', 0.95),
|
|
531
|
+
residentLinePrewarmCount: Number(renderer?._residentLinePrewarmCount || 0),
|
|
532
|
+
residentImagePrewarmCount: Number(renderer?._residentImagePrewarmCount || 0),
|
|
533
|
+
residentImagePrewarmCandidateCount: Number(renderer?._residentImagePrewarmCandidateCount || 0),
|
|
534
|
+
residentImageBufferReuseCount: Number(renderer?._residentImageBufferReuseCount || 0),
|
|
535
|
+
lineTextureRows: Number(renderer?.lineTextureRows || 0),
|
|
536
|
+
residentGpuWarmComplete: !!renderer &&
|
|
537
|
+
renderer._hasPendingImageAtlasWork?.() !== true &&
|
|
538
|
+
renderer._residentGpuWarmKey === getResidentGpuKey(renderer),
|
|
539
|
+
residentAtlasWarmComplete: !!renderer && Number(renderer.imageAtlasSlots?.size || 0) > 0 &&
|
|
540
|
+
renderer._hasPendingImageAtlasWork?.() !== true &&
|
|
541
|
+
Number(renderer._residentImageAtlasWarmVersion ?? -1) === Number(renderer.imageAtlasTexture?.version || 0)
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function resetDiagnostics(renderer) {
|
|
546
|
+
if (!renderer) return;
|
|
547
|
+
frameSampleStates.delete(renderer);
|
|
548
|
+
renderer._fullResStablePlanSkipCount = 0;
|
|
549
|
+
renderer._lastFullResStablePlanSkipped = false;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
window.MindMapRenderPlan = Object.freeze({
|
|
553
|
+
buildFullResKey,
|
|
554
|
+
shouldSkipStableFullRes,
|
|
555
|
+
commitStableFullRes,
|
|
556
|
+
scheduleResidentLinePrewarm,
|
|
557
|
+
resolveResidentLineData,
|
|
558
|
+
getPreparedLineData,
|
|
559
|
+
areResidentLinesPrepared,
|
|
560
|
+
initialLineTextureRows,
|
|
561
|
+
ensureLineTextureCapacity,
|
|
562
|
+
prepareImageAtlasCapacity,
|
|
563
|
+
fallbackBatch,
|
|
564
|
+
reusePreparedImageInstances,
|
|
565
|
+
beginFrame,
|
|
566
|
+
recordFrame,
|
|
567
|
+
getDiagnostics,
|
|
568
|
+
resetDiagnostics
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
window.MindCanvasBuildInfo?.registerPart?.('renderPlan', BUILD_ID);
|
|
572
|
+
})();
|
|
@@ -31,19 +31,76 @@
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function CSS3DRenderer(){
|
|
34
|
-
var _width, _height
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
|
|
34
|
+
var _width, _height, _widthHalf, _heightHalf;
|
|
35
|
+
var cache = { camera:{ fov:0, style:'' }, objects: new WeakMap() };
|
|
36
|
+
var domElement = document.createElement('div');
|
|
37
|
+
domElement.style.overflow = 'hidden';
|
|
38
|
+
this.domElement = domElement;
|
|
39
|
+
var cameraElement = document.createElement('div');
|
|
40
|
+
cameraElement.style.webkitTransformStyle = cameraElement.style.transformStyle = 'preserve-3d';
|
|
41
|
+
cameraElement.style.pointerEvents = 'none';
|
|
42
|
+
domElement.appendChild(cameraElement);
|
|
43
|
+
|
|
38
44
|
this.getSize = function(){ return { width:_width, height:_height }; };
|
|
39
45
|
this.getCameraElement = function(){ return cameraElement; };
|
|
40
|
-
this.setSize = function(width, height){
|
|
46
|
+
this.setSize = function(width, height){
|
|
47
|
+
_width=width; _height=height; _widthHalf=_width/2; _heightHalf=_height/2;
|
|
48
|
+
domElement.style.width=width+'px'; domElement.style.height=height+'px';
|
|
49
|
+
cameraElement.style.width=width+'px'; cameraElement.style.height=height+'px';
|
|
50
|
+
};
|
|
51
|
+
|
|
41
52
|
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
|
-
function getObjectCSSMatrix(matrix){ var e=matrix.elements;
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
function getObjectCSSMatrix(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])+')'; }
|
|
54
|
+
function hasMatrixChanged(elements, values){
|
|
55
|
+
if (!values) return true;
|
|
56
|
+
for (var i=0;i<16;i++) if (epsilon(elements[i])!==values[i]) return true;
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
function copyMatrix(elements, values){
|
|
60
|
+
var next=values || new Float64Array(16);
|
|
61
|
+
for (var i=0;i<16;i++) next[i]=epsilon(elements[i]);
|
|
62
|
+
return next;
|
|
63
|
+
}
|
|
64
|
+
function renderObject(object){
|
|
65
|
+
if (object.isCSS3DObject){
|
|
66
|
+
var visible=object.visible===true;
|
|
67
|
+
var display=visible ? '' : 'none';
|
|
68
|
+
var element=object.element;
|
|
69
|
+
var cached=cache.objects.get(object);
|
|
70
|
+
if (cached===undefined){
|
|
71
|
+
cached={ element:null, matrix:null, display:null };
|
|
72
|
+
cache.objects.set(object,cached);
|
|
73
|
+
}
|
|
74
|
+
var elementChanged=cached.element!==element;
|
|
75
|
+
var becameVisible=visible && cached.display==='none';
|
|
76
|
+
if (visible && (elementChanged || becameVisible || hasMatrixChanged(object.matrixWorld.elements,cached.matrix))){
|
|
77
|
+
var style=getObjectCSSMatrix(object.matrixWorld);
|
|
78
|
+
element.style.webkitTransform=element.style.transform=style;
|
|
79
|
+
cached.matrix=copyMatrix(object.matrixWorld.elements,cached.matrix);
|
|
80
|
+
}
|
|
81
|
+
if (elementChanged || cached.display!==display) element.style.display=display;
|
|
82
|
+
cached.element=element;
|
|
83
|
+
cached.display=display;
|
|
84
|
+
if (element.parentNode!==cameraElement) cameraElement.appendChild(element);
|
|
85
|
+
}
|
|
86
|
+
for (var i=0,l=object.children.length;i<l;i++) renderObject(object.children[i]);
|
|
87
|
+
}
|
|
88
|
+
function renderCameraOnly(renderer, camera, matrixWorldIsCurrent){
|
|
89
|
+
var fov=camera.projectionMatrix.elements[5]*_heightHalf;
|
|
90
|
+
if (cache.camera.fov!==fov){
|
|
91
|
+
renderer.domElement.style.webkitPerspective=renderer.domElement.style.perspective=fov+'px';
|
|
92
|
+
cache.camera.fov=fov;
|
|
93
|
+
}
|
|
94
|
+
if (matrixWorldIsCurrent!==true && camera.parent===null) camera.updateMatrixWorld();
|
|
95
|
+
var cameraCSSMatrix='translateZ('+fov+'px)'+getCameraCSSMatrix(camera.matrixWorldInverse);
|
|
96
|
+
var style=cameraCSSMatrix+'translate('+_widthHalf+'px,'+_heightHalf+'px)';
|
|
97
|
+
if (cache.camera.style!==style){
|
|
98
|
+
cameraElement.style.webkitTransform=cameraElement.style.transform=style;
|
|
99
|
+
cache.camera.style=style;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.renderCamera = function(camera, matrixWorldIsCurrent){ renderCameraOnly(this, camera, matrixWorldIsCurrent); };
|
|
103
|
+
this.render = function(scene, camera){ if (scene.autoUpdate===true) scene.updateMatrixWorld(); renderCameraOnly(this, camera, false); renderObject(scene); };
|
|
47
104
|
}
|
|
48
105
|
|
|
49
106
|
window.CSS3DObject = CSS3DObject; window.CSS3DSprite = CSS3DSprite; window.CSS3DRenderer = CSS3DRenderer;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|