@mindexec/cli 0.2.444 → 0.2.446
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 +6 -3
- package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
- package/remote-hub.js +170 -5
- package/scripts/remote-fast-live-rate-smoke.mjs +1 -0
- package/server.js +12 -12
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +165 -10
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +47 -58
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +4 -24
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-pipeline.js +31 -18
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-remote-codecs.js +6 -3
- package/wwwroot/_framework/{MindExecution.Core.4moacskf64.dll → MindExecution.Core.djyzj5mxyk.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.pa251cfsz4.dll → MindExecution.Kernel.6e5cj9aijz.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.dxyuwmxv1s.dll → MindExecution.Plugins.Admin.siulh9tfrf.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.7uj5erqhhn.dll → MindExecution.Plugins.Business.8cjtrc7qd3.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.108rmsxc96.dll → MindExecution.Plugins.Concept.rpp78mc75u.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.ccsy3g0fe5.dll → MindExecution.Plugins.Directory.wfv0ff9v4u.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.1vjpuoe9ff.dll → MindExecution.Plugins.PlanMaster.jdppnbd6g4.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.q8ml98phj9.dll → MindExecution.Plugins.YouTube.a43f2q3pkw.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.2pywq19zjy.dll → MindExecution.Shared.gwtyj0e9lw.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.qucbls1wfr.dll → MindExecution.Web.j3zaapcxtt.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +28 -28
- package/wwwroot/service-worker.js +1 -1
|
@@ -9,6 +9,7 @@ window.MindMapInteractions = (function () {
|
|
|
9
9
|
const PRIMARY_CLICK_DELAY_MS = 280;
|
|
10
10
|
const BACKGROUND_PRIMARY_CLICK_DELAY_MS = 320;
|
|
11
11
|
const eventHandlers = new WeakMap();
|
|
12
|
+
const pointerHitContexts = new WeakMap();
|
|
12
13
|
const _tmpDragPos = new THREE.Vector3();
|
|
13
14
|
const _tmpMultiDragPos = new THREE.Vector3();
|
|
14
15
|
const BROWSER_SELECTION_LOCK_CLASS = 'mindcanvas-browser-selection-locked';
|
|
@@ -1288,21 +1289,18 @@ window.MindMapInteractions = (function () {
|
|
|
1288
1289
|
const meshes = [];
|
|
1289
1290
|
let residentHit = null;
|
|
1290
1291
|
if (module.raycaster.ray.intersectPlane(module.plane, module.intersectPoint)) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
meshes.push(glObject);
|
|
1297
|
-
}
|
|
1298
|
-
});
|
|
1292
|
+
const nearbyMeshes = getNearbyMeshes(module, module.intersectPoint);
|
|
1293
|
+
meshes.push(...nearbyMeshes);
|
|
1294
|
+
meshes._hitTestCandidatesAvailable = nearbyMeshes._hitTestCandidatesAvailable === true;
|
|
1295
|
+
if (meshes.length === 0 && meshes._hitTestCandidatesAvailable !== true && module.nodeObjectsById?.size > 0) {
|
|
1296
|
+
appendFallbackMeshes(module, module.intersectPoint, meshes);
|
|
1299
1297
|
}
|
|
1300
1298
|
residentHit = module.lodRenderer?.pickResidentNodeAtWorldPoint?.(module.intersectPoint) || null;
|
|
1301
1299
|
}
|
|
1302
1300
|
const topHit = getTopIntersectionHit(module, module.raycaster.intersectObjects(meshes, true));
|
|
1303
1301
|
const topNodeId = resolveNodeIdFromHitObject(topHit?.object);
|
|
1304
1302
|
const topPriority = topHit ? getIntersectionInteractionPriority(module, topHit) : -Infinity;
|
|
1305
|
-
const cssHit =
|
|
1303
|
+
const cssHit = getPointerCssHit(module, e);
|
|
1306
1304
|
if (cssHit?.nodeId && (!topHit || (cssHit.nodeId !== topNodeId && (cssHit.priority ?? -Infinity) >= topPriority))) {
|
|
1307
1305
|
return cssHit.nodeId;
|
|
1308
1306
|
}
|
|
@@ -1931,7 +1929,6 @@ window.MindMapInteractions = (function () {
|
|
|
1931
1929
|
let bestPriority = -Infinity;
|
|
1932
1930
|
const worldPoint = getWorldPoint(module, clientX, clientY);
|
|
1933
1931
|
const candidateIds = getCssFallbackCandidateIds(module, worldPoint);
|
|
1934
|
-
|
|
1935
1932
|
for (let i = 0; i < candidateIds.length; i++) {
|
|
1936
1933
|
const nodeId = candidateIds[i];
|
|
1937
1934
|
const entry = module.nodeObjectsById.get(nodeId);
|
|
@@ -1971,7 +1968,6 @@ window.MindMapInteractions = (function () {
|
|
|
1971
1968
|
let bestHit = null;
|
|
1972
1969
|
let bestPriority = -Infinity;
|
|
1973
1970
|
const candidateIds = getCssFallbackCandidateIds(module, worldPoint);
|
|
1974
|
-
|
|
1975
1971
|
for (let i = 0; i < candidateIds.length; i++) {
|
|
1976
1972
|
const nodeId = candidateIds[i];
|
|
1977
1973
|
const entry = module.nodeObjectsById.get(nodeId);
|
|
@@ -2134,6 +2130,7 @@ window.MindMapInteractions = (function () {
|
|
|
2134
2130
|
}
|
|
2135
2131
|
|
|
2136
2132
|
function getHitTestCandidateNodeIds(module, point, options = {}) {
|
|
2133
|
+
if (!module?.nodeObjectsById || !point) return null;
|
|
2137
2134
|
const normalizedCellRadius = Math.max(0, Math.min(3, Math.round(Number(options.cellRadius || 1))));
|
|
2138
2135
|
module?.logicWorkerBridge?.primeHitTestCandidates?.(module, {
|
|
2139
2136
|
point,
|
|
@@ -2148,6 +2145,7 @@ window.MindMapInteractions = (function () {
|
|
|
2148
2145
|
return cachedCandidateIds;
|
|
2149
2146
|
}
|
|
2150
2147
|
|
|
2148
|
+
if (!module.spatialGrid) return null;
|
|
2151
2149
|
return collectLocalHitTestCandidateNodeIds(module, point, normalizedCellRadius);
|
|
2152
2150
|
}
|
|
2153
2151
|
|
|
@@ -2188,10 +2186,14 @@ window.MindMapInteractions = (function () {
|
|
|
2188
2186
|
function getNearbyMeshes(module, point, options = {}) {
|
|
2189
2187
|
const candidateIds = getHitTestCandidateNodeIds(module, point, options);
|
|
2190
2188
|
const meshes = [];
|
|
2189
|
+
meshes._hitTestCandidatesAvailable = Array.isArray(candidateIds);
|
|
2191
2190
|
appendMeshesForHitTestCandidateIds(module, candidateIds, meshes, options);
|
|
2192
2191
|
return meshes;
|
|
2193
2192
|
}
|
|
2194
2193
|
|
|
2194
|
+
function appendFallbackMeshes(module, point, meshes) {
|
|
2195
|
+
(getCssFallbackCandidateIds(module, point) || []).forEach(id => { const g = module.nodeObjectsById.get(id)?.glObject; if (g && (g.isMesh || g.children?.length > 0)) meshes.push(g); });
|
|
2196
|
+
}
|
|
2195
2197
|
function buildSelectionRectFromWorldPoints(worldStartPos, worldEndPos) {
|
|
2196
2198
|
if (!worldStartPos || !worldEndPos) {
|
|
2197
2199
|
return null;
|
|
@@ -2337,11 +2339,19 @@ window.MindMapInteractions = (function () {
|
|
|
2337
2339
|
const candidateIds = worldPoint
|
|
2338
2340
|
? getHitTestCandidateNodeIds(module, worldPoint, { visibleOnly: false })
|
|
2339
2341
|
: [];
|
|
2340
|
-
if (Array.isArray(candidateIds)
|
|
2342
|
+
if (Array.isArray(candidateIds)) {
|
|
2341
2343
|
return candidateIds;
|
|
2342
2344
|
}
|
|
2343
2345
|
|
|
2344
|
-
|
|
2346
|
+
const fallbackIds = new Set();
|
|
2347
|
+
const addId = value => { const id = String(value || '').trim(); if (id && module.nodeObjectsById.has(id)) fallbackIds.add(id); };
|
|
2348
|
+
module._visibleIds?.forEach?.(addId);
|
|
2349
|
+
module._prevVisibleIds?.forEach?.(addId);
|
|
2350
|
+
addId(module.selectedNodeIdJs);
|
|
2351
|
+
module.multiSelectedNodeIds?.forEach?.(addId);
|
|
2352
|
+
addId(module.draggedNodeId);
|
|
2353
|
+
module.container?.querySelectorAll?.('[data-node-id]')?.forEach?.(element => addId(element.dataset?.nodeId));
|
|
2354
|
+
return Array.from(fallbackIds);
|
|
2345
2355
|
}
|
|
2346
2356
|
// ▲▲▲ [New] ▲▲▲
|
|
2347
2357
|
|
|
@@ -2964,13 +2974,11 @@ window.MindMapInteractions = (function () {
|
|
|
2964
2974
|
function getGuardedTargetNodeId(module, target, event) {
|
|
2965
2975
|
const nodeId = getTargetNodeId(target);
|
|
2966
2976
|
if (!nodeId || !event) {
|
|
2967
|
-
const topCssHit = event
|
|
2968
|
-
? findCssNodeHitAtClientPoint(module, event.clientX, event.clientY)
|
|
2969
|
-
: null;
|
|
2977
|
+
const topCssHit = event ? getPointerCssHit(module, event) : null;
|
|
2970
2978
|
return topCssHit?.nodeId || nodeId;
|
|
2971
2979
|
}
|
|
2972
2980
|
|
|
2973
|
-
const topCssHit =
|
|
2981
|
+
const topCssHit = getPointerCssHit(module, event);
|
|
2974
2982
|
if (topCssHit?.nodeId && topCssHit.nodeId !== nodeId) {
|
|
2975
2983
|
return topCssHit.nodeId;
|
|
2976
2984
|
}
|
|
@@ -2979,7 +2987,15 @@ window.MindMapInteractions = (function () {
|
|
|
2979
2987
|
? null
|
|
2980
2988
|
: nodeId;
|
|
2981
2989
|
}
|
|
2982
|
-
|
|
2990
|
+
function getPointerCssHit(module, event) {
|
|
2991
|
+
if (!event || !module) return null;
|
|
2992
|
+
let context = pointerHitContexts.get(event);
|
|
2993
|
+
if (!context || context.module !== module) {
|
|
2994
|
+
context = { module, cssHit: findCssNodeHitAtClientPoint(module, event.clientX, event.clientY) };
|
|
2995
|
+
pointerHitContexts.set(event, context);
|
|
2996
|
+
}
|
|
2997
|
+
return context.cssHit;
|
|
2998
|
+
}
|
|
2983
2999
|
function getMountedEmbedCanvasDragTarget(module, target, event) {
|
|
2984
3000
|
if (!module || !(target instanceof Element)) {
|
|
2985
3001
|
return null;
|
|
@@ -3364,26 +3380,24 @@ window.MindMapInteractions = (function () {
|
|
|
3364
3380
|
return;
|
|
3365
3381
|
}
|
|
3366
3382
|
|
|
3367
|
-
const selectedIds = new Set();
|
|
3368
|
-
if (module.selectedNodeIdJs) {
|
|
3369
|
-
selectedIds.add(String(module.selectedNodeIdJs));
|
|
3370
|
-
}
|
|
3383
|
+
const selectedIds = new Set(module.selectedNodeIdJs ? [String(module.selectedNodeIdJs)] : []);
|
|
3371
3384
|
module.multiSelectedNodeIds?.forEach?.(id => selectedIds.add(String(id)));
|
|
3372
3385
|
|
|
3373
|
-
module.
|
|
3374
|
-
|
|
3375
|
-
if (contentType !== 'embed' || !entry?.cssObject?.element) {
|
|
3376
|
-
return;
|
|
3377
|
-
}
|
|
3386
|
+
const previousIds = module._embedInteractivityNodeIds instanceof Set ? module._embedInteractivityNodeIds : new Set();
|
|
3387
|
+
if (previousIds.size === selectedIds.size && [...selectedIds].every(id => previousIds.has(id))) return;
|
|
3378
3388
|
|
|
3379
|
-
|
|
3389
|
+
const changedIds = new Set([...previousIds, ...selectedIds]);
|
|
3390
|
+
changedIds.forEach(nodeId => {
|
|
3391
|
+
const entry = module.nodeObjectsById.get(nodeId);
|
|
3392
|
+
if (String(entry?.model?.contentType ?? entry?.model?.ContentType ?? '').toLowerCase() !== 'embed' || !entry?.cssObject?.element) return;
|
|
3393
|
+
const isSelected = selectedIds.has(nodeId);
|
|
3380
3394
|
window.MindMapCss3DManager.syncCss3dEmbedInteractivity(entry.cssObject.element, {
|
|
3381
3395
|
isInteractive: isSelected,
|
|
3382
3396
|
isSelected
|
|
3383
3397
|
});
|
|
3384
3398
|
});
|
|
3399
|
+
module._embedInteractivityNodeIds = selectedIds;
|
|
3385
3400
|
}
|
|
3386
|
-
|
|
3387
3401
|
function switchPreviousSelectedNoteToWebGL(module, respectHighMode = true) {
|
|
3388
3402
|
if (!module?.selectedNodeIdJs) return;
|
|
3389
3403
|
const prevEntry = module.nodeObjectsById?.get(module.selectedNodeIdJs);
|
|
@@ -4235,7 +4249,6 @@ window.MindMapInteractions = (function () {
|
|
|
4235
4249
|
}
|
|
4236
4250
|
|
|
4237
4251
|
// ▼▼▼ [Debug] Click timing measurement ▼▼▼
|
|
4238
|
-
const clickT0 = performance.now();
|
|
4239
4252
|
// ▲▲▲ [Debug] ▲▲▲
|
|
4240
4253
|
|
|
4241
4254
|
updatePointer(module, e);
|
|
@@ -4245,43 +4258,28 @@ window.MindMapInteractions = (function () {
|
|
|
4245
4258
|
const meshesToIntersect = [];
|
|
4246
4259
|
|
|
4247
4260
|
// ▼▼▼ [Debug] ▼▼▼
|
|
4248
|
-
const clickT1 = performance.now();
|
|
4249
|
-
let gridCellsChecked = 0;
|
|
4250
|
-
let nodesChecked = 0;
|
|
4251
4261
|
let residentLodHit = null;
|
|
4252
4262
|
// ▲▲▲ [Debug] ▲▲▲
|
|
4253
4263
|
|
|
4254
4264
|
if (module.raycaster.ray.intersectPlane(module.plane, module.intersectPoint)) {
|
|
4255
4265
|
const nearby = getNearbyMeshes(module, module.intersectPoint);
|
|
4256
4266
|
meshesToIntersect.push(...nearby);
|
|
4267
|
+
meshesToIntersect._hitTestCandidatesAvailable = nearby._hitTestCandidatesAvailable === true;
|
|
4257
4268
|
|
|
4258
4269
|
// ▼▼▼ [Fix] Fallback: spatial grid가 비어있으면 전체 노드 검색 ▼▼▼
|
|
4259
|
-
if (meshesToIntersect.length === 0 && module.nodeObjectsById.size > 0) {
|
|
4260
|
-
|
|
4261
|
-
module.nodeObjectsById.forEach((entry) => {
|
|
4262
|
-
const glObject = entry?.glObject;
|
|
4263
|
-
if (!glObject) {
|
|
4264
|
-
return;
|
|
4265
|
-
}
|
|
4266
|
-
|
|
4267
|
-
if (glObject.isMesh || (Array.isArray(glObject.children) && glObject.children.length > 0)) {
|
|
4268
|
-
meshesToIntersect.push(glObject);
|
|
4269
|
-
}
|
|
4270
|
-
});
|
|
4270
|
+
if (meshesToIntersect.length === 0 && meshesToIntersect._hitTestCandidatesAvailable !== true && module.nodeObjectsById.size > 0) {
|
|
4271
|
+
appendFallbackMeshes(module, module.intersectPoint, meshesToIntersect);
|
|
4271
4272
|
residentLodHit = module.lodRenderer?.pickResidentNodeAtWorldPoint?.(module.intersectPoint) || null;
|
|
4272
4273
|
}
|
|
4273
4274
|
// ▲▲▲ [Fix] ▲▲▲
|
|
4274
4275
|
}
|
|
4275
4276
|
|
|
4276
4277
|
// ▼▼▼ [Debug] ▼▼▼
|
|
4277
|
-
const clickT2 = performance.now();
|
|
4278
4278
|
// ▲▲▲ [Debug] ▲▲▲
|
|
4279
4279
|
|
|
4280
4280
|
const intersects = module.raycaster.intersectObjects(meshesToIntersect, true);
|
|
4281
4281
|
|
|
4282
4282
|
// ▼▼▼ [Debug] ▼▼▼
|
|
4283
|
-
const clickT3 = performance.now();
|
|
4284
|
-
console.log(`[Click Timing] setup=${(clickT1 - clickT0).toFixed(2)}ms | grid(${gridCellsChecked}cells, ${nodesChecked}nodes, ${meshesToIntersect.length}meshes)=${(clickT2 - clickT1).toFixed(2)}ms | raycast=${(clickT3 - clickT2).toFixed(2)}ms | TOTAL=${(clickT3 - clickT0).toFixed(2)}ms`);
|
|
4285
4283
|
// ▲▲▲ [Debug] ▲▲▲
|
|
4286
4284
|
|
|
4287
4285
|
const topIntersect = getTopIntersectionHit(module, intersects);
|
|
@@ -4289,7 +4287,7 @@ window.MindMapInteractions = (function () {
|
|
|
4289
4287
|
const topIntersectPriority = topIntersect
|
|
4290
4288
|
? getIntersectionInteractionPriority(module, topIntersect)
|
|
4291
4289
|
: -Infinity;
|
|
4292
|
-
const cssFallbackHit =
|
|
4290
|
+
const cssFallbackHit = getPointerCssHit(module, e);
|
|
4293
4291
|
const cssFallbackPriority = cssFallbackHit?.priority ?? -Infinity;
|
|
4294
4292
|
const shouldPreferCssFallback =
|
|
4295
4293
|
!!cssFallbackHit?.nodeId &&
|
|
@@ -4308,15 +4306,6 @@ window.MindMapInteractions = (function () {
|
|
|
4308
4306
|
if (topIntersect && !shouldPreferCssFallback) {
|
|
4309
4307
|
let clickedMesh = topIntersect.object;
|
|
4310
4308
|
|
|
4311
|
-
// ▼▼▼ [Debug] Raycast Hit Log ▼▼▼
|
|
4312
|
-
console.log('[onMouseDown] Raycast Hits:', intersects.map(i => ({
|
|
4313
|
-
name: i.object.name,
|
|
4314
|
-
type: i.object.type,
|
|
4315
|
-
nodeId: i.object.userData?.nodeId || i.object.parent?.userData?.nodeId,
|
|
4316
|
-
distance: i.distance.toFixed(2),
|
|
4317
|
-
visible: i.object.visible, // 추가 확인
|
|
4318
|
-
parentVisible: i.object.parent?.visible // 부모 가시성 확인
|
|
4319
|
-
})));
|
|
4320
4309
|
// ▲▲▲ [Debug] ▲▲▲
|
|
4321
4310
|
|
|
4322
4311
|
// ▼▼▼ [FIX] 클릭된 대상이 'body'(히트박스)라면 부모 그룹을 선택하도록 강제 보정 ▼▼▼
|
|
@@ -4226,30 +4226,10 @@
|
|
|
4226
4226
|
}
|
|
4227
4227
|
// ▲▲▲ [Optimization] ▲▲▲
|
|
4228
4228
|
|
|
4229
|
-
//
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
const otherWrapper = otherEntry.cssObject.element;
|
|
4235
|
-
// 다른 노드들의 텍스트 선택 비활성화
|
|
4236
|
-
const contentEls = otherWrapper.querySelectorAll(NODE_TEXT_SELECTION_SELECTORS);
|
|
4237
|
-
contentEls.forEach(el => {
|
|
4238
|
-
el.style.userSelect = 'none';
|
|
4239
|
-
el.style.webkitUserSelect = 'none';
|
|
4240
|
-
});
|
|
4241
|
-
});
|
|
4242
|
-
// ▲▲▲ [Fix] ▲▲▲
|
|
4243
|
-
|
|
4244
|
-
// ▼▼▼ [Fix] 현재 노드의 텍스트 선택 활성화 ▼▼▼
|
|
4245
|
-
const currentWrapper = nodeEntry.cssObject.element;
|
|
4246
|
-
if (currentWrapper) {
|
|
4247
|
-
const contentEls = currentWrapper.querySelectorAll(NODE_TEXT_SELECTION_SELECTORS);
|
|
4248
|
-
contentEls.forEach(el => {
|
|
4249
|
-
el.style.userSelect = 'text';
|
|
4250
|
-
el.style.webkitUserSelect = 'text';
|
|
4251
|
-
});
|
|
4252
|
-
}
|
|
4229
|
+
// CSS3D text selection ownership is updated as a previous/next delta.
|
|
4230
|
+
// The manager patches only those two wrappers instead of walking the
|
|
4231
|
+
// complete node map on every CSS3D promotion.
|
|
4232
|
+
window.MindMapCss3DManager?.setNativeTextSelectionOwnerClass?.(module, nodeId);
|
|
4253
4233
|
// ▲▲▲ [Fix] ▲▲▲
|
|
4254
4234
|
|
|
4255
4235
|
// Sync CSS3D scroll position with WebGL/model scrollOffset (ratio-based).
|
|
@@ -146,9 +146,10 @@
|
|
|
146
146
|
|
|
147
147
|
// ▼▼▼ [Perf] Render queue (time-sliced) ▼▼▼
|
|
148
148
|
const renderQueue = [];
|
|
149
|
-
const renderQueueSet = new Set();
|
|
150
|
-
let renderQueueScheduled = false;
|
|
151
|
-
let renderModuleRef = null;
|
|
149
|
+
const renderQueueSet = new Set();
|
|
150
|
+
let renderQueueScheduled = false;
|
|
151
|
+
let renderModuleRef = null;
|
|
152
|
+
let renderQueueDirty = false;
|
|
152
153
|
const RENDER_BUDGET_MS = 8;
|
|
153
154
|
let renderSeq = 0;
|
|
154
155
|
|
|
@@ -178,9 +179,10 @@
|
|
|
178
179
|
function enqueueRender(module, nodeId) {
|
|
179
180
|
if (!nodeId) return;
|
|
180
181
|
renderModuleRef = module;
|
|
181
|
-
if (!renderQueueSet.has(nodeId)) {
|
|
182
|
-
renderQueue.push({ nodeId, priority: computeRenderPriority(module, nodeId), seq: renderSeq++ });
|
|
183
|
-
renderQueueSet.add(nodeId);
|
|
182
|
+
if (!renderQueueSet.has(nodeId)) {
|
|
183
|
+
renderQueue.push({ nodeId, priority: computeRenderPriority(module, nodeId), seq: renderSeq++ });
|
|
184
|
+
renderQueueSet.add(nodeId);
|
|
185
|
+
renderQueueDirty = true;
|
|
184
186
|
}
|
|
185
187
|
scheduleRenderQueue();
|
|
186
188
|
}
|
|
@@ -195,12 +197,15 @@
|
|
|
195
197
|
const start = performance.now();
|
|
196
198
|
|
|
197
199
|
// 우선순위 정렬 (가시/선택/거리)
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
if (renderQueueDirty) {
|
|
201
|
+
if (renderQueue.length > 1) {
|
|
202
|
+
renderQueue.sort((a, b) => (b.priority - a.priority) || (b.seq - a.seq));
|
|
203
|
+
}
|
|
204
|
+
renderQueueDirty = false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
while (renderQueue.length > 0) {
|
|
208
|
+
const item = renderQueue.pop();
|
|
204
209
|
const nodeId = item.nodeId;
|
|
205
210
|
renderQueueSet.delete(nodeId);
|
|
206
211
|
if (renderModuleRef) {
|
|
@@ -224,7 +229,8 @@
|
|
|
224
229
|
// ▲▲▲ [New] ▲▲▲
|
|
225
230
|
|
|
226
231
|
// ▼▼▼ [Perf] Deferred disposal to avoid GC/driver spikes ▼▼▼
|
|
227
|
-
const disposeQueue = [];
|
|
232
|
+
const disposeQueue = [];
|
|
233
|
+
let disposeQueueHead = 0;
|
|
228
234
|
let disposeScheduled = false;
|
|
229
235
|
const DISPOSE_BUDGET_MS = 6; // soft budget per frame
|
|
230
236
|
|
|
@@ -246,8 +252,8 @@
|
|
|
246
252
|
|
|
247
253
|
function processDisposeQueue(deadline) {
|
|
248
254
|
const start = performance.now();
|
|
249
|
-
while (disposeQueue.length
|
|
250
|
-
const item = disposeQueue
|
|
255
|
+
while (disposeQueueHead < disposeQueue.length) {
|
|
256
|
+
const item = disposeQueue[disposeQueueHead++];
|
|
251
257
|
try { item.dispose(); } catch { }
|
|
252
258
|
|
|
253
259
|
if (deadline && typeof deadline.timeRemaining === 'function') {
|
|
@@ -258,9 +264,16 @@
|
|
|
258
264
|
}
|
|
259
265
|
|
|
260
266
|
disposeScheduled = false;
|
|
261
|
-
if (disposeQueue.length
|
|
262
|
-
|
|
263
|
-
|
|
267
|
+
if (disposeQueueHead >= disposeQueue.length) {
|
|
268
|
+
disposeQueue.length = 0;
|
|
269
|
+
disposeQueueHead = 0;
|
|
270
|
+
} else if (disposeQueue.length - disposeQueueHead > 64) {
|
|
271
|
+
disposeQueue.splice(0, disposeQueueHead);
|
|
272
|
+
disposeQueueHead = 0;
|
|
273
|
+
}
|
|
274
|
+
if (disposeQueueHead < disposeQueue.length) {
|
|
275
|
+
scheduleDispose();
|
|
276
|
+
}
|
|
264
277
|
}
|
|
265
278
|
// ▲▲▲ [Perf] ▲▲▲
|
|
266
279
|
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
return true;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
function ensureDecoder(canvas, frame, state) {
|
|
101
|
+
function ensureDecoder(canvas, frame, state, onPaint) {
|
|
102
102
|
if (typeof VideoDecoder !== 'function' || typeof EncodedVideoChunk !== 'function') {
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
@@ -106,6 +106,8 @@
|
|
|
106
106
|
const width = Number(frame.width || 0) || canvas.width || 1920;
|
|
107
107
|
const height = Number(frame.height || 0) || canvas.height || 1080;
|
|
108
108
|
const key = `${width}x${height}`;
|
|
109
|
+
state.onPaint = onPaint;
|
|
110
|
+
state.latestFrame = frame;
|
|
109
111
|
if (state.decoder && state.width === width && state.height === height) {
|
|
110
112
|
return state.decoder;
|
|
111
113
|
}
|
|
@@ -126,6 +128,7 @@
|
|
|
126
128
|
const context = canvas.getContext('2d', { alpha: false, desynchronized: true });
|
|
127
129
|
context?.drawImage(videoFrame, 0, 0, canvas.width, canvas.height);
|
|
128
130
|
state.lastPaintAt = performance.now();
|
|
131
|
+
try { state.onPaint?.(canvas, state.latestFrame || frame); } catch (error) { emit('remote.h264.paintCallbackFailed', { error: error?.message || String(error || '') }); }
|
|
129
132
|
emit('remote.h264.paint', { frameSeq: state.lastSeq, width: canvas.width, height: canvas.height });
|
|
130
133
|
} finally {
|
|
131
134
|
videoFrame.close?.();
|
|
@@ -154,7 +157,7 @@
|
|
|
154
157
|
return decoder;
|
|
155
158
|
}
|
|
156
159
|
|
|
157
|
-
async function decode(canvas, frame) {
|
|
160
|
+
async function decode(canvas, frame, onPaint) {
|
|
158
161
|
const payload = frame?._remoteFleetPayloadBlob;
|
|
159
162
|
if (!canvas || !payload) {
|
|
160
163
|
return false;
|
|
@@ -168,7 +171,7 @@
|
|
|
168
171
|
const seq = Number(frame.streamFrameSeq || frame.frameSeq || 0) || 0;
|
|
169
172
|
if (seq > 0 && seq <= state.lastSeq) return true;
|
|
170
173
|
state.lastSeq = seq;
|
|
171
|
-
const decoder = ensureDecoder(canvas, frame, state);
|
|
174
|
+
const decoder = ensureDecoder(canvas, frame, state, onPaint);
|
|
172
175
|
if (!decoder || decoder.state === 'closed') return false;
|
|
173
176
|
if (state.pending >= MAX_DECODE_QUEUE) {
|
|
174
177
|
emit('remote.h264.drop', { reason: 'decode-queue', frameSeq: seq });
|
package/wwwroot/_framework/{MindExecution.Core.4moacskf64.dll → MindExecution.Core.djyzj5mxyk.dll}
RENAMED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/wwwroot/_framework/{MindExecution.Web.qucbls1wfr.dll → MindExecution.Web.j3zaapcxtt.dll}
RENAMED
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-o6tmG5oGpl7vciF713W3t451harGm461qOhCvK87lOE=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -122,16 +122,16 @@
|
|
|
122
122
|
"System.brmz7yk5qh.dll": "System.dll",
|
|
123
123
|
"netstandard.b50t77veor.dll": "netstandard.dll",
|
|
124
124
|
"System.Private.CoreLib.g6ztz7cmo2.dll": "System.Private.CoreLib.dll",
|
|
125
|
-
"MindExecution.Core.
|
|
126
|
-
"MindExecution.Kernel.
|
|
127
|
-
"MindExecution.Plugins.Admin.
|
|
128
|
-
"MindExecution.Plugins.Business.
|
|
129
|
-
"MindExecution.Plugins.Concept.
|
|
130
|
-
"MindExecution.Plugins.Directory.
|
|
131
|
-
"MindExecution.Plugins.PlanMaster.
|
|
132
|
-
"MindExecution.Plugins.YouTube.
|
|
133
|
-
"MindExecution.Shared.
|
|
134
|
-
"MindExecution.Web.
|
|
125
|
+
"MindExecution.Core.djyzj5mxyk.dll": "MindExecution.Core.dll",
|
|
126
|
+
"MindExecution.Kernel.6e5cj9aijz.dll": "MindExecution.Kernel.dll",
|
|
127
|
+
"MindExecution.Plugins.Admin.siulh9tfrf.dll": "MindExecution.Plugins.Admin.dll",
|
|
128
|
+
"MindExecution.Plugins.Business.8cjtrc7qd3.dll": "MindExecution.Plugins.Business.dll",
|
|
129
|
+
"MindExecution.Plugins.Concept.rpp78mc75u.dll": "MindExecution.Plugins.Concept.dll",
|
|
130
|
+
"MindExecution.Plugins.Directory.wfv0ff9v4u.dll": "MindExecution.Plugins.Directory.dll",
|
|
131
|
+
"MindExecution.Plugins.PlanMaster.jdppnbd6g4.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
132
|
+
"MindExecution.Plugins.YouTube.a43f2q3pkw.dll": "MindExecution.Plugins.YouTube.dll",
|
|
133
|
+
"MindExecution.Shared.gwtyj0e9lw.dll": "MindExecution.Shared.dll",
|
|
134
|
+
"MindExecution.Web.j3zaapcxtt.dll": "MindExecution.Web.dll",
|
|
135
135
|
"dotnet.native.566r55w3xu.js": "dotnet.native.js",
|
|
136
136
|
"dotnet.native.x6q5aixc38.wasm": "dotnet.native.wasm",
|
|
137
137
|
"dotnet.js": "dotnet.js",
|
|
@@ -276,18 +276,18 @@
|
|
|
276
276
|
"System.Xml.XDocument.sn51jas17n.dll": "sha256-GNI2kFgFmPTwzuzwUn8gxK+AzGLUWRJFdg9JzIbrybQ=",
|
|
277
277
|
"System.brmz7yk5qh.dll": "sha256-CfM2miyj1KHApFmqMdLYWio3S/jrdON2pW9Xr2nTwlo=",
|
|
278
278
|
"netstandard.b50t77veor.dll": "sha256-//jQGOXjb8ET8WtXgOJrAxLx6E7zDJ5RjRRutwkvmxo=",
|
|
279
|
-
"MindExecution.Core.
|
|
280
|
-
"MindExecution.Kernel.
|
|
281
|
-
"MindExecution.Plugins.Business.
|
|
282
|
-
"MindExecution.Plugins.Concept.
|
|
283
|
-
"MindExecution.Plugins.PlanMaster.
|
|
284
|
-
"MindExecution.Shared.
|
|
285
|
-
"MindExecution.Web.
|
|
279
|
+
"MindExecution.Core.djyzj5mxyk.dll": "sha256-mWD5B7qIqi95K+2PlXhtVYKTU0NXvGjFUMZIIKhgOJM=",
|
|
280
|
+
"MindExecution.Kernel.6e5cj9aijz.dll": "sha256-soI6Vf+R5EO4br1BPNT8w1Dojx0MrwEpnoU3hlN/Jo4=",
|
|
281
|
+
"MindExecution.Plugins.Business.8cjtrc7qd3.dll": "sha256-KKJ9wMXw9lRRp8Yej3hIx2A/KlT4IMnCNvE6nC15NHc=",
|
|
282
|
+
"MindExecution.Plugins.Concept.rpp78mc75u.dll": "sha256-EeJ9pPy1kMPUMU1/VZq086s7Rpx8Kl8JNJin/q8CCk0=",
|
|
283
|
+
"MindExecution.Plugins.PlanMaster.jdppnbd6g4.dll": "sha256-tx9+RxTaAfdk4GoSZt3mj8tZfGOwNAlK/JMf0NyrkUY=",
|
|
284
|
+
"MindExecution.Shared.gwtyj0e9lw.dll": "sha256-4N4HdjdoXtRylfVW6OYliAy9JOlx67Vudw/CbXjCZDs=",
|
|
285
|
+
"MindExecution.Web.j3zaapcxtt.dll": "sha256-0eGBQjTRRbbCk0PMweH2fX57WJ/z8Nj2h8IRCvURzUI="
|
|
286
286
|
},
|
|
287
287
|
"lazyAssembly": {
|
|
288
|
-
"MindExecution.Plugins.Admin.
|
|
289
|
-
"MindExecution.Plugins.Directory.
|
|
290
|
-
"MindExecution.Plugins.YouTube.
|
|
288
|
+
"MindExecution.Plugins.Admin.siulh9tfrf.dll": "sha256-xJKUGBrCw9pX8r+5p5uCn5oEikqnBhhN8PQk1UQXvwk=",
|
|
289
|
+
"MindExecution.Plugins.Directory.wfv0ff9v4u.dll": "sha256-LPqtVKjGSWJC9OfNV3Sc/ohbNBfwPMkt/fvpx4nMRnQ=",
|
|
290
|
+
"MindExecution.Plugins.YouTube.a43f2q3pkw.dll": "sha256-duhXTTnMwRKd8YPDL5IkWyunMITVbxMbk0xWZXdaTPU="
|
|
291
291
|
}
|
|
292
292
|
},
|
|
293
293
|
"cacheBootResources": true,
|
package/wwwroot/index.html
CHANGED
|
@@ -579,7 +579,7 @@
|
|
|
579
579
|
}
|
|
580
580
|
|
|
581
581
|
const base = '_content/MindExecution.Shared/js/';
|
|
582
|
-
const scriptVersion = '
|
|
582
|
+
const scriptVersion = '20260724-near-css3d-input-optimization-v939';
|
|
583
583
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
584
584
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
585
585
|
const criticalScripts = [
|