@neta-art/cohub 11.5.1 → 12.1.0
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/dist/board/editor/animation.js +2 -1
- package/dist/board/editor/creation.js +1 -1
- package/dist/board/editor/document-edits.d.ts +1 -1
- package/dist/board/editor/document-edits.js +1 -19
- package/dist/board/editor/document.js +2 -1
- package/dist/board/editor/index.d.ts +2 -1
- package/dist/board/editor/index.js +2 -1
- package/dist/board/editor/snapshots.js +11 -13
- package/dist/board/export/scene.js +1 -0
- package/dist/board/model/client-geometry.d.ts +22 -0
- package/dist/board/model/client-geometry.js +94 -0
- package/dist/board/model/document-share.d.ts +5 -0
- package/dist/board/model/document-share.js +27 -0
- package/dist/board/model/index.d.ts +5 -4
- package/dist/board/model/index.js +4 -3
- package/dist/board/model/items/create.d.ts +5 -1
- package/dist/board/model/items/create.js +29 -58
- package/dist/board/model/items/index.d.ts +2 -2
- package/dist/board/model/items/index.js +2 -2
- package/dist/board/model/items/registry.js +2 -5
- package/dist/board/model/json.d.ts +4 -0
- package/dist/board/model/json.js +22 -0
- package/dist/board/model/media-playback.d.ts +6 -3
- package/dist/board/player/index.d.ts +6 -2
- package/dist/board/player/index.js +33 -15
- package/dist/board/render/card-tag.d.ts +0 -1
- package/dist/board/render/card-tag.js +15 -17
- package/dist/board/render/index.d.ts +3 -3
- package/dist/board/render/index.js +3 -3
- package/dist/board/render/renderers/arrow-card-renderer.js +8 -6
- package/dist/board/render/renderers/audio-card-renderer.js +10 -6
- package/dist/board/render/renderers/base-card-renderer.d.ts +1 -1
- package/dist/board/render/renderers/base-card-renderer.js +2 -3
- package/dist/board/render/renderers/board-renderer-registry.d.ts +6 -2
- package/dist/board/render/renderers/custom-card-renderer.js +23 -18
- package/dist/board/render/renderers/file-card-renderer.js +14 -9
- package/dist/board/render/renderers/frame-card-renderer.js +7 -4
- package/dist/board/render/renderers/image-card-renderer.js +13 -49
- package/dist/board/render/renderers/model-card-renderer.js +4 -1
- package/dist/board/render/renderers/shape-card-renderer.js +8 -6
- package/dist/board/render/renderers/task-card-renderer.js +13 -10
- package/dist/board/render/renderers/text-card-renderer.js +7 -5
- package/dist/board/render/renderers/unknown-card-renderer.js +8 -6
- package/dist/board/render/renderers/video-card-renderer.js +19 -18
- package/dist/board/render/script-host.d.ts +2 -0
- package/dist/board/render/script-host.js +44 -9
- package/dist/board/render/script-resolution.d.ts +4 -0
- package/dist/board/render/script-resolution.js +18 -0
- package/dist/board/render/surface.d.ts +9 -2
- package/dist/board/render/surface.js +15 -1
- package/dist/board/render/text-resolution.d.ts +4 -7
- package/dist/board/render/text-resolution.js +20 -22
- package/dist/board/replica/index.js +4 -1
- package/dist/board/stage/assets.d.ts +12 -8
- package/dist/board/stage/assets.js +173 -88
- package/dist/board/stage/canvas-size.d.ts +18 -0
- package/dist/board/stage/canvas-size.js +31 -0
- package/dist/board/stage/index.d.ts +3 -3
- package/dist/board/stage/index.js +3 -3
- package/dist/board/stage/lru.d.ts +3 -2
- package/dist/board/stage/lru.js +8 -4
- package/dist/board/stage/pointer.d.ts +1 -1
- package/dist/board/stage/pointer.js +4 -5
- package/dist/board/stage/scene.d.ts +8 -1
- package/dist/board/stage/scene.js +72 -10
- package/dist/board/stage/stage.d.ts +1 -0
- package/dist/board/stage/stage.js +151 -63
- package/dist/board/stage/text-resolution-tracker.d.ts +8 -0
- package/dist/board/stage/text-resolution-tracker.js +33 -0
- package/dist/board/stage/views.d.ts +7 -2
- package/dist/board/stage/views.js +50 -21
- package/dist/chunks/environment.d.ts +16 -2
- package/dist/index.js +65 -22
- package/dist/protocol/dist/board-constants.js +56 -1
- package/dist/protocol/dist/board-layout.d.ts +8 -1
- package/dist/protocol/dist/board-layout.js +16 -4
- package/dist/protocol/dist/board-model.js +13 -19
- package/dist/protocol/dist/board-schema.d.ts +52 -0
- package/dist/protocol/dist/board-schema.js +8 -0
- package/dist/protocol/dist/core/media.js +1 -0
- package/dist/protocol/dist/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getBoardResolution } from "../render/text-resolution.js";
|
|
2
|
+
//#region src/board/stage/canvas-size.ts
|
|
3
|
+
function measureBoardCanvasBox(entry, density) {
|
|
4
|
+
const css = entry.contentBoxSize?.[0];
|
|
5
|
+
const device = entry.devicePixelContentBoxSize?.[0];
|
|
6
|
+
return {
|
|
7
|
+
width: css?.inlineSize ?? entry.contentRect.width,
|
|
8
|
+
height: css?.blockSize ?? entry.contentRect.height,
|
|
9
|
+
density,
|
|
10
|
+
device: device ? {
|
|
11
|
+
width: device.inlineSize,
|
|
12
|
+
height: device.blockSize
|
|
13
|
+
} : null
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function boardCanvasSize(box, density) {
|
|
17
|
+
const resolution = getBoardResolution(box, density);
|
|
18
|
+
const { device } = box;
|
|
19
|
+
if (device && box.density === density && resolution === density) return {
|
|
20
|
+
width: device.width / density,
|
|
21
|
+
height: device.height / density,
|
|
22
|
+
resolution
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
width: box.width,
|
|
26
|
+
height: box.height,
|
|
27
|
+
resolution
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { boardCanvasSize, measureBoardCanvasBox };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DEFAULT_LRU_BUDGET, LruBudget, LruEntry, selectLruEvictions } from "./lru.js";
|
|
1
|
+
import { COMPACT_LRU_BUDGET, DEFAULT_LRU_BUDGET, LruBudget, LruEntry, selectLruEvictions } from "./lru.js";
|
|
2
2
|
import { BoardImageTexturePool, boardImageTexturePool, createBoardImageTexturePool, loadBoardImageTexture, unloadBoardImageTexture } from "./texture-pool.js";
|
|
3
|
-
import { BoardAssetManager, BoardAssetManagerOptions, BoardModelPreviewRequest, BoardModelPreviews, boardAssetKey, createBoardAssetManager } from "./assets.js";
|
|
3
|
+
import { BoardAssetManager, BoardAssetManagerOptions, BoardModelPreviewRequest, BoardModelPreviews, boardAssetKey, boardTextureEdge, createBoardAssetManager } from "./assets.js";
|
|
4
4
|
import { toBoardPointerEvent } from "./pointer.js";
|
|
5
5
|
import { createBoardPointerGestures } from "./pointer-gestures.js";
|
|
6
6
|
import { BoardLiveStroke, BoardScene, BoardSceneNode, SceneSyncInput, createBoardScene } from "./scene.js";
|
|
7
7
|
import { BoardItemView, BoardItemViewContext, BoardItemViewInstance, BoardItemViewLayer, createBoardItemViewLayer } from "./views.js";
|
|
8
8
|
import { BoardStage, BoardStageOptions, BoardStagePointerPhase, BoardStageTheme, mountBoardStage } from "./stage.js";
|
|
9
9
|
import { BoardOverlayInput, drawBoardOverlay, expandFrame } from "./overlay.js";
|
|
10
|
-
export { BoardAssetManager, BoardAssetManagerOptions, BoardImageTexturePool, BoardItemView, BoardItemViewContext, BoardItemViewInstance, BoardItemViewLayer, BoardLiveStroke, BoardModelPreviewRequest, BoardModelPreviews, BoardOverlayInput, BoardScene, BoardSceneNode, BoardStage, BoardStageOptions, BoardStagePointerPhase, BoardStageTheme, DEFAULT_LRU_BUDGET, LruBudget, LruEntry, SceneSyncInput, boardAssetKey, boardImageTexturePool, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardPointerGestures, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
10
|
+
export { BoardAssetManager, BoardAssetManagerOptions, BoardImageTexturePool, BoardItemView, BoardItemViewContext, BoardItemViewInstance, BoardItemViewLayer, BoardLiveStroke, BoardModelPreviewRequest, BoardModelPreviews, BoardOverlayInput, BoardScene, BoardSceneNode, BoardStage, BoardStageOptions, BoardStagePointerPhase, BoardStageTheme, COMPACT_LRU_BUDGET, DEFAULT_LRU_BUDGET, LruBudget, LruEntry, SceneSyncInput, boardAssetKey, boardImageTexturePool, boardTextureEdge, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardPointerGestures, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DEFAULT_LRU_BUDGET, selectLruEvictions } from "./lru.js";
|
|
1
|
+
import { COMPACT_LRU_BUDGET, DEFAULT_LRU_BUDGET, selectLruEvictions } from "./lru.js";
|
|
2
2
|
import { boardImageTexturePool, createBoardImageTexturePool, loadBoardImageTexture, unloadBoardImageTexture } from "./texture-pool.js";
|
|
3
|
-
import { boardAssetKey, createBoardAssetManager } from "./assets.js";
|
|
3
|
+
import { boardAssetKey, boardTextureEdge, createBoardAssetManager } from "./assets.js";
|
|
4
4
|
import { toBoardPointerEvent } from "./pointer.js";
|
|
5
5
|
import { createBoardPointerGestures } from "./pointer-gestures.js";
|
|
6
6
|
import { createBoardScene } from "./scene.js";
|
|
7
7
|
import { drawBoardOverlay, expandFrame } from "./overlay.js";
|
|
8
8
|
import { createBoardItemViewLayer } from "./views.js";
|
|
9
9
|
import { mountBoardStage } from "./stage.js";
|
|
10
|
-
export { DEFAULT_LRU_BUDGET, boardAssetKey, boardImageTexturePool, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardPointerGestures, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
10
|
+
export { COMPACT_LRU_BUDGET, DEFAULT_LRU_BUDGET, boardAssetKey, boardImageTexturePool, boardTextureEdge, createBoardAssetManager, createBoardImageTexturePool, createBoardItemViewLayer, createBoardPointerGestures, createBoardScene, drawBoardOverlay, expandFrame, loadBoardImageTexture, mountBoardStage, selectLruEvictions, toBoardPointerEvent, unloadBoardImageTexture };
|
|
@@ -20,8 +20,9 @@ type LruBudget = {
|
|
|
20
20
|
maxCount: number;
|
|
21
21
|
maxBytes: number;
|
|
22
22
|
};
|
|
23
|
-
/** Default cooling-pool ceiling:
|
|
23
|
+
/** Default cooling-pool ceiling: 512 images or ~192 MB of GPU memory. */
|
|
24
24
|
declare const DEFAULT_LRU_BUDGET: LruBudget;
|
|
25
|
+
declare const COMPACT_LRU_BUDGET: LruBudget;
|
|
25
26
|
/**
|
|
26
27
|
* Given the unreferenced (cooling) entries and a budget, return the keys to
|
|
27
28
|
* evict — oldest first — so the remaining pool fits within both limits. Returns
|
|
@@ -29,4 +30,4 @@ declare const DEFAULT_LRU_BUDGET: LruBudget;
|
|
|
29
30
|
*/
|
|
30
31
|
declare function selectLruEvictions(entries: LruEntry[], budget: LruBudget): string[];
|
|
31
32
|
//#endregion
|
|
32
|
-
export { DEFAULT_LRU_BUDGET, LruBudget, LruEntry, selectLruEvictions };
|
|
33
|
+
export { COMPACT_LRU_BUDGET, DEFAULT_LRU_BUDGET, LruBudget, LruEntry, selectLruEvictions };
|
package/dist/board/stage/lru.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
//#region src/board/stage/lru.ts
|
|
2
|
-
/** Default cooling-pool ceiling:
|
|
2
|
+
/** Default cooling-pool ceiling: 512 images or ~192 MB of GPU memory. */
|
|
3
3
|
const DEFAULT_LRU_BUDGET = {
|
|
4
|
-
maxCount:
|
|
5
|
-
maxBytes:
|
|
4
|
+
maxCount: 512,
|
|
5
|
+
maxBytes: 201326592
|
|
6
|
+
};
|
|
7
|
+
const COMPACT_LRU_BUDGET = {
|
|
8
|
+
maxCount: 256,
|
|
9
|
+
maxBytes: 100663296
|
|
6
10
|
};
|
|
7
11
|
/**
|
|
8
12
|
* Given the unreferenced (cooling) entries and a budget, return the keys to
|
|
@@ -26,4 +30,4 @@ function selectLruEvictions(entries, budget) {
|
|
|
26
30
|
return evict;
|
|
27
31
|
}
|
|
28
32
|
//#endregion
|
|
29
|
-
export { DEFAULT_LRU_BUDGET, selectLruEvictions };
|
|
33
|
+
export { COMPACT_LRU_BUDGET, DEFAULT_LRU_BUDGET, selectLruEvictions };
|
|
@@ -3,6 +3,6 @@ import "../model/index.js";
|
|
|
3
3
|
import { BoardPointerEvent } from "../editor/interaction.js";
|
|
4
4
|
import "../editor/index.js";
|
|
5
5
|
//#region src/board/stage/pointer.d.ts
|
|
6
|
-
declare function toBoardPointerEvent(event: PointerEvent, rect: DOMRect, camera: BoardViewport, coalesce?: boolean): BoardPointerEvent;
|
|
6
|
+
declare function toBoardPointerEvent(event: PointerEvent, rect: DOMRect | HTMLElement, camera: BoardViewport, coalesce?: boolean): BoardPointerEvent;
|
|
7
7
|
//#endregion
|
|
8
8
|
export { toBoardPointerEvent };
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { pointToWorld, screenPoint } from "../model/geometry.js";
|
|
2
|
+
import { elementClientToLocal } from "../model/client-geometry.js";
|
|
2
3
|
//#region src/board/stage/pointer.ts
|
|
3
4
|
function pressureOf(event) {
|
|
4
5
|
return event.pointerType === "pen" && event.pressure > 0 ? event.pressure : .5;
|
|
5
6
|
}
|
|
6
|
-
function screenOf(event, rect) {
|
|
7
|
-
return screenPoint(event.clientX - rect.left, event.clientY - rect.top);
|
|
8
|
-
}
|
|
9
7
|
function toBoardPointerEvent(event, rect, camera, coalesce = false) {
|
|
10
|
-
const
|
|
8
|
+
const local = "getBoundingClientRect" in rect ? elementClientToLocal(rect) : (x, y) => screenPoint(x - rect.left, y - rect.top);
|
|
9
|
+
const screen = local(event.clientX, event.clientY);
|
|
11
10
|
const coalesced = coalesce ? event.getCoalescedEvents?.() : void 0;
|
|
12
11
|
const samples = coalesced && coalesced.length > 1 ? coalesced.map((sample) => ({
|
|
13
|
-
world: pointToWorld(
|
|
12
|
+
world: pointToWorld(local(sample.clientX, sample.clientY), camera),
|
|
14
13
|
pressure: pressureOf(sample)
|
|
15
14
|
})) : void 0;
|
|
16
15
|
return {
|
|
@@ -24,6 +24,10 @@ type SceneSyncInput = {
|
|
|
24
24
|
structureVersion: number;
|
|
25
25
|
geometryVersion: number;
|
|
26
26
|
gestureActive: boolean;
|
|
27
|
+
focus?: {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
};
|
|
27
31
|
};
|
|
28
32
|
type BoardSceneNode = {
|
|
29
33
|
item: BoardSceneItem;
|
|
@@ -32,6 +36,9 @@ type BoardSceneNode = {
|
|
|
32
36
|
type BoardScene = {
|
|
33
37
|
sync: (input: SceneSyncInput) => void;
|
|
34
38
|
getNode: (itemId: string) => BoardSceneNode | null;
|
|
39
|
+
holders: (key: string) => ReadonlySet<string>;
|
|
40
|
+
readonly liveVersion: number;
|
|
41
|
+
liveIds: () => ReadonlySet<string>;
|
|
35
42
|
readonly animated: boolean;
|
|
36
43
|
tick: (clock: number) => number | null;
|
|
37
44
|
destroy: (context: BoardRenderContext) => void;
|
|
@@ -40,7 +47,7 @@ declare function createBoardScene(options: {
|
|
|
40
47
|
world: Container;
|
|
41
48
|
overlay: Graphics;
|
|
42
49
|
getRenderer: BoardCardRendererResolver;
|
|
43
|
-
|
|
50
|
+
requestFrame?: () => void;
|
|
44
51
|
}): BoardScene;
|
|
45
52
|
//#endregion
|
|
46
53
|
export { BoardLiveStroke, BoardScene, BoardSceneNode, SceneSyncInput, createBoardScene };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseBoardItem } from "../../protocol/dist/board-model.js";
|
|
2
2
|
import { drawPointsBounds } from "../../protocol/dist/board-layout.js";
|
|
3
|
+
import { textZoomBucket } from "../render/text-resolution.js";
|
|
3
4
|
import { clippingAncestor, isClippingFrame, syncClipGroup } from "../render/clip.js";
|
|
4
5
|
import { Graphics } from "pixi.js";
|
|
5
6
|
//#region src/board/stage/scene.ts
|
|
@@ -7,11 +8,13 @@ const FAR_LAYER_ENTER = 450;
|
|
|
7
8
|
const FAR_LAYER_EXIT = 350;
|
|
8
9
|
const FAR_PASS_BATCH = 240;
|
|
9
10
|
const FAR_LIVE_LIMIT = 64;
|
|
11
|
+
const RESOLUTION_BATCH = 32;
|
|
10
12
|
const Z_FAR_LAYER = -1;
|
|
11
13
|
const Z_LIFTED = 1e9;
|
|
12
14
|
const Z_LIVE_STROKE = Number.MAX_SAFE_INTEGER - 1;
|
|
13
15
|
const Z_OVERLAY = Number.MAX_SAFE_INTEGER;
|
|
14
16
|
const POOL_LIMIT_PER_RENDERER = 48;
|
|
17
|
+
const EMPTY_IDS = /* @__PURE__ */ new Set();
|
|
15
18
|
function idSetSignature(ids) {
|
|
16
19
|
let hash = ids.size;
|
|
17
20
|
for (const id of ids) {
|
|
@@ -31,20 +34,34 @@ function createBoardScene(options) {
|
|
|
31
34
|
const tickingIds = /* @__PURE__ */ new Set();
|
|
32
35
|
const pools = /* @__PURE__ */ new Map();
|
|
33
36
|
const heldKeys = /* @__PURE__ */ new Map();
|
|
37
|
+
const holders = /* @__PURE__ */ new Map();
|
|
34
38
|
let orderById = /* @__PURE__ */ new Map();
|
|
35
39
|
let farSig = null;
|
|
36
40
|
let farActive = false;
|
|
37
41
|
let lastStructureVersion = -1;
|
|
38
42
|
let lastZoom = NaN;
|
|
43
|
+
let lastResolution = "";
|
|
44
|
+
const pendingResolution = /* @__PURE__ */ new Set();
|
|
45
|
+
let liveVersion = 0;
|
|
39
46
|
let lifted = /* @__PURE__ */ new Set();
|
|
40
47
|
const liveStrokes = /* @__PURE__ */ new Map();
|
|
41
|
-
function setHeldKey(context, cardId,
|
|
48
|
+
function setHeldKey(context, cardId, item) {
|
|
49
|
+
const desiredKey = item ? context.assetKey(item) : null;
|
|
42
50
|
const heldKey = heldKeys.get(cardId) ?? null;
|
|
43
51
|
if (desiredKey === heldKey) return;
|
|
44
|
-
if (heldKey)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
if (heldKey) {
|
|
53
|
+
context.releaseTexture(heldKey);
|
|
54
|
+
const ids = holders.get(heldKey);
|
|
55
|
+
ids?.delete(cardId);
|
|
56
|
+
if (ids?.size === 0) holders.delete(heldKey);
|
|
57
|
+
}
|
|
58
|
+
if (desiredKey && item) {
|
|
59
|
+
heldKeys.set(cardId, desiredKey);
|
|
60
|
+
const ids = holders.get(desiredKey);
|
|
61
|
+
if (ids) ids.add(cardId);
|
|
62
|
+
else holders.set(desiredKey, /* @__PURE__ */ new Set([cardId]));
|
|
63
|
+
context.acquireTexture(desiredKey, item);
|
|
64
|
+
} else heldKeys.delete(cardId);
|
|
48
65
|
}
|
|
49
66
|
function takeFromPool(rendererId) {
|
|
50
67
|
const pool = pools.get(rendererId);
|
|
@@ -54,6 +71,7 @@ function createBoardScene(options) {
|
|
|
54
71
|
function recycle(id, entry, context, destroyed) {
|
|
55
72
|
setHeldKey(context, id, null);
|
|
56
73
|
cards.delete(id);
|
|
74
|
+
pendingResolution.delete(id);
|
|
57
75
|
animatedIds.delete(id);
|
|
58
76
|
tickingIds.delete(id);
|
|
59
77
|
if (destroyed) return;
|
|
@@ -119,7 +137,7 @@ function createBoardScene(options) {
|
|
|
119
137
|
scriptRevision: context.scripts?.revision?.(item.id) ?? 0
|
|
120
138
|
};
|
|
121
139
|
cards.set(item.id, entry);
|
|
122
|
-
setHeldKey(context, item.id,
|
|
140
|
+
setHeldKey(context, item.id, item);
|
|
123
141
|
renderer.zoom?.(container, context.zoom);
|
|
124
142
|
return entry;
|
|
125
143
|
}
|
|
@@ -167,7 +185,7 @@ function createBoardScene(options) {
|
|
|
167
185
|
}
|
|
168
186
|
if (index < ids.length) {
|
|
169
187
|
farFrame = requestAnimationFrame(step);
|
|
170
|
-
if (target === farFront) options.
|
|
188
|
+
if (target === farFront) options.requestFrame?.();
|
|
171
189
|
return;
|
|
172
190
|
}
|
|
173
191
|
if (target === farBack) {
|
|
@@ -180,7 +198,7 @@ function createBoardScene(options) {
|
|
|
180
198
|
farFront.visible = farActive;
|
|
181
199
|
farPainted = true;
|
|
182
200
|
farRunning = false;
|
|
183
|
-
options.
|
|
201
|
+
options.requestFrame?.();
|
|
184
202
|
if (farQueued) runFarPass();
|
|
185
203
|
};
|
|
186
204
|
step();
|
|
@@ -277,6 +295,11 @@ function createBoardScene(options) {
|
|
|
277
295
|
}
|
|
278
296
|
function sync(input) {
|
|
279
297
|
const { items, scene, context, getItem, visibleIds, pinnedIds, globalSig, structureVersion, geometryVersion, gestureActive } = input;
|
|
298
|
+
const resolution = `${textZoomBucket(context.zoom)}:${context.textResolution}`;
|
|
299
|
+
if (resolution !== lastResolution) {
|
|
300
|
+
lastResolution = resolution;
|
|
301
|
+
queueResolution(input.focus);
|
|
302
|
+
}
|
|
280
303
|
const structureChanged = structureVersion !== lastStructureVersion;
|
|
281
304
|
if (structureChanged) {
|
|
282
305
|
lastStructureVersion = structureVersion;
|
|
@@ -304,7 +327,14 @@ function createBoardScene(options) {
|
|
|
304
327
|
if (farActive) {
|
|
305
328
|
const { orderedIds, unbatched } = visibleFacts(input);
|
|
306
329
|
for (const id of unbatched) wanted.add(id);
|
|
307
|
-
let
|
|
330
|
+
let retained = 0;
|
|
331
|
+
if (!farPainted) {
|
|
332
|
+
for (const id of cards.keys()) if ((!visibleIds || visibleIds.has(id)) && !farCovered.has(id) && !wanted.has(id)) {
|
|
333
|
+
wanted.add(id);
|
|
334
|
+
retained++;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
let budget = Math.max(0, FAR_LIVE_LIMIT - retained);
|
|
308
338
|
for (const id of orderedIds) {
|
|
309
339
|
if (budget === 0) break;
|
|
310
340
|
if (farCovered.has(id) || wanted.has(id)) continue;
|
|
@@ -346,13 +376,16 @@ function createBoardScene(options) {
|
|
|
346
376
|
entry.hovered = hovered;
|
|
347
377
|
entry.resizing = resizing;
|
|
348
378
|
entry.globalSig = globalSig;
|
|
349
|
-
setHeldKey(context, id,
|
|
379
|
+
setHeldKey(context, id, item);
|
|
350
380
|
if (changed) {
|
|
351
381
|
entry.renderer.update(entry.container, item, context);
|
|
352
382
|
entry.container.alpha = scene.opacity(id);
|
|
353
383
|
if (entry.renderer.tick) tickingIds.add(id);
|
|
384
|
+
pendingResolution.delete(id);
|
|
354
385
|
}
|
|
355
386
|
}
|
|
387
|
+
refreshResolution(context);
|
|
388
|
+
if (liveSetChanged) liveVersion += 1;
|
|
356
389
|
if (structureChanged || liveSetChanged) syncClips(scene);
|
|
357
390
|
if (context.zoom !== lastZoom) {
|
|
358
391
|
lastZoom = context.zoom;
|
|
@@ -363,6 +396,27 @@ function createBoardScene(options) {
|
|
|
363
396
|
if (structureChanged || farModeChanged || liveSetChanged || liftChanged) applyChildOrder(scene);
|
|
364
397
|
syncLiveStrokes(input);
|
|
365
398
|
}
|
|
399
|
+
function queueResolution(focus) {
|
|
400
|
+
const ids = [...cards].filter(([, entry]) => entry.renderer.resolution);
|
|
401
|
+
if (focus) {
|
|
402
|
+
const distance = ({ item: { frame } }) => (frame.x + frame.width / 2 - focus.x) ** 2 + (frame.y + frame.height / 2 - focus.y) ** 2;
|
|
403
|
+
ids.sort(([, a], [, b]) => distance(a) - distance(b));
|
|
404
|
+
}
|
|
405
|
+
pendingResolution.clear();
|
|
406
|
+
for (const [id] of ids) pendingResolution.add(id);
|
|
407
|
+
}
|
|
408
|
+
function refreshResolution(context) {
|
|
409
|
+
let budget = RESOLUTION_BATCH;
|
|
410
|
+
for (const id of pendingResolution) {
|
|
411
|
+
if (budget-- === 0) break;
|
|
412
|
+
pendingResolution.delete(id);
|
|
413
|
+
const entry = cards.get(id);
|
|
414
|
+
if (!entry) continue;
|
|
415
|
+
entry.renderer.resolution?.(entry.container, entry.item, context);
|
|
416
|
+
if (entry.renderer.tick) tickingIds.add(id);
|
|
417
|
+
}
|
|
418
|
+
if (pendingResolution.size) options.requestFrame?.();
|
|
419
|
+
}
|
|
366
420
|
function tick(clock) {
|
|
367
421
|
let next = null;
|
|
368
422
|
for (const id of tickingIds) {
|
|
@@ -391,6 +445,7 @@ function createBoardScene(options) {
|
|
|
391
445
|
pools.clear();
|
|
392
446
|
for (const key of heldKeys.values()) context.releaseTexture(key);
|
|
393
447
|
heldKeys.clear();
|
|
448
|
+
holders.clear();
|
|
394
449
|
orderById = /* @__PURE__ */ new Map();
|
|
395
450
|
for (const entry of clips.values()) entry.group.destroy({ children: true });
|
|
396
451
|
clips.clear();
|
|
@@ -402,6 +457,8 @@ function createBoardScene(options) {
|
|
|
402
457
|
visibleMemo = null;
|
|
403
458
|
lastStructureVersion = -1;
|
|
404
459
|
lastZoom = NaN;
|
|
460
|
+
lastResolution = "";
|
|
461
|
+
pendingResolution.clear();
|
|
405
462
|
}
|
|
406
463
|
return {
|
|
407
464
|
sync,
|
|
@@ -412,6 +469,11 @@ function createBoardScene(options) {
|
|
|
412
469
|
container: entry.container
|
|
413
470
|
} : null;
|
|
414
471
|
},
|
|
472
|
+
holders: (key) => holders.get(key) ?? EMPTY_IDS,
|
|
473
|
+
get liveVersion() {
|
|
474
|
+
return liveVersion;
|
|
475
|
+
},
|
|
476
|
+
liveIds: () => new Set(cards.keys()),
|
|
415
477
|
get animated() {
|
|
416
478
|
return animatedIds.size > 0;
|
|
417
479
|
},
|
|
@@ -56,6 +56,7 @@ type BoardStageOptions = {
|
|
|
56
56
|
height: number;
|
|
57
57
|
}) => void;
|
|
58
58
|
onVisibleChange?: (ids: ReadonlySet<string> | null) => void;
|
|
59
|
+
onLiveChange?: (ids: ReadonlySet<string>) => void;
|
|
59
60
|
safeRect?: () => Rect;
|
|
60
61
|
scriptCapabilities?: Record<string, (id: string, input: unknown) => Promise<unknown>>;
|
|
61
62
|
};
|