@neta-art/cohub 9.0.1 → 11.0.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/README.md +108 -102
- package/dist/board/editor/align.d.ts +11 -0
- package/dist/board/editor/align.js +72 -0
- package/dist/board/editor/animation.d.ts +17 -0
- package/dist/board/editor/animation.js +187 -0
- package/dist/board/editor/camera.d.ts +32 -0
- package/dist/board/editor/camera.js +137 -0
- package/dist/board/editor/clipboard.d.ts +41 -0
- package/dist/board/editor/clipboard.js +129 -0
- package/dist/board/editor/connection-ports.d.ts +19 -0
- package/dist/board/editor/connection-ports.js +85 -0
- package/dist/board/editor/context.d.ts +111 -0
- package/dist/board/editor/context.js +30 -0
- package/dist/board/editor/copy.d.ts +17 -0
- package/dist/board/editor/copy.js +121 -0
- package/dist/board/editor/creation.d.ts +51 -0
- package/dist/board/editor/creation.js +225 -0
- package/dist/board/editor/deletion.d.ts +9 -0
- package/dist/board/editor/deletion.js +90 -0
- package/dist/board/editor/document-edits.d.ts +22 -0
- package/dist/board/editor/document-edits.js +193 -0
- package/dist/board/editor/document.d.ts +41 -0
- package/dist/board/editor/document.js +302 -0
- package/dist/board/editor/editor.d.ts +225 -0
- package/dist/board/editor/editor.js +439 -0
- package/dist/board/editor/index.d.ts +18 -0
- package/dist/board/editor/index.js +12 -0
- package/dist/board/editor/interaction.d.ts +115 -0
- package/dist/board/editor/interaction.js +584 -0
- package/dist/board/editor/query.d.ts +27 -0
- package/dist/board/editor/query.js +203 -0
- package/dist/board/editor/remote.d.ts +11 -0
- package/dist/board/editor/remote.js +55 -0
- package/dist/board/editor/selection-transform.d.ts +24 -0
- package/dist/board/editor/selection-transform.js +81 -0
- package/dist/board/editor/selection.d.ts +33 -0
- package/dist/board/editor/selection.js +197 -0
- package/dist/board/editor/snapping.d.ts +33 -0
- package/dist/board/editor/snapping.js +75 -0
- package/dist/board/editor/snapshots.d.ts +27 -0
- package/dist/board/editor/snapshots.js +132 -0
- package/dist/board/editor/spatial.d.ts +41 -0
- package/dist/board/editor/spatial.js +191 -0
- package/dist/board/editor/state.d.ts +12 -0
- package/dist/board/editor/state.js +49 -0
- package/dist/board/editor/tool.d.ts +10 -0
- package/dist/board/editor/tool.js +19 -0
- package/dist/board/editor/wheel.d.ts +5 -0
- package/dist/board/editor/wheel.js +17 -0
- package/dist/board/export/index.d.ts +28 -6
- package/dist/board/export/index.js +47 -13
- package/dist/board/export/node/index.d.ts +56 -0
- package/dist/board/{headless → export/node}/index.js +26 -21
- package/dist/board/export/node/scripts.d.ts +16 -0
- package/dist/board/export/node/scripts.js +258 -0
- package/dist/board/export/scene.d.ts +8 -5
- package/dist/board/export/scene.js +24 -9
- package/dist/board/{animation.d.ts → model/animation.d.ts} +8 -5
- package/dist/board/{animation.js → model/animation.js} +37 -10
- package/dist/board/{core → model}/arrow-geometry.d.ts +2 -2
- package/dist/board/{core → model}/arrow-geometry.js +2 -2
- package/dist/board/model/authoring.d.ts +20 -0
- package/dist/board/model/authoring.js +185 -0
- package/dist/board/{core → model}/draw-geometry.d.ts +2 -2
- package/dist/board/{core → model}/draw-geometry.js +1 -1
- package/dist/board/model/draw-input.d.ts +14 -0
- package/dist/board/model/draw-input.js +28 -0
- package/dist/board/{core → model}/export-assets.d.ts +1 -1
- package/dist/board/{core → model}/export-assets.js +1 -1
- package/dist/board/{core → model}/export-plan.d.ts +2 -2
- package/dist/board/{core → model}/export-plan.js +3 -2
- package/dist/board/{core → model}/file-preview.d.ts +1 -1
- package/dist/board/{core → model}/file-preview.js +2 -2
- package/dist/board/{core → model}/file-snapshot.d.ts +1 -1
- package/dist/board/{core → model}/file-snapshot.js +4 -3
- package/dist/board/{geometry.d.ts → model/geometry.d.ts} +3 -3
- package/dist/board/{geometry.js → model/geometry.js} +1 -1
- package/dist/board/{image-key.d.ts → model/image-key.d.ts} +2 -2
- package/dist/board/{image-key.js → model/image-key.js} +7 -3
- package/dist/board/model/index.d.ts +42 -0
- package/dist/board/model/index.js +39 -0
- package/dist/board/model/items/builtin.d.ts +5 -0
- package/dist/board/model/items/builtin.js +119 -0
- package/dist/board/model/items/create.d.ts +61 -0
- package/dist/board/model/items/create.js +272 -0
- package/dist/board/model/items/definition.d.ts +35 -0
- package/dist/board/model/items/definition.js +18 -0
- package/dist/board/model/items/id.d.ts +5 -0
- package/dist/board/model/items/id.js +11 -0
- package/dist/board/model/items/index.d.ts +6 -0
- package/dist/board/model/items/index.js +6 -0
- package/dist/board/model/items/registry.d.ts +35 -0
- package/dist/board/model/items/registry.js +84 -0
- package/dist/board/{media-playback.d.ts → model/media-playback.d.ts} +4 -3
- package/dist/board/{media-playback.js → model/media-playback.js} +15 -5
- package/dist/board/{media.d.ts → model/media.d.ts} +1 -1
- package/dist/board/{media.js → model/media.js} +8 -2
- package/dist/board/{core → model}/palette.d.ts +1 -1
- package/dist/board/{core → model}/palette.js +1 -1
- package/dist/board/{presets.d.ts → model/presets.d.ts} +3 -3
- package/dist/board/{presets.js → model/presets.js} +1 -1
- package/dist/board/{replay.d.ts → model/replay.d.ts} +5 -5
- package/dist/board/{replay.js → model/replay.js} +2 -2
- package/dist/board/model/sampling.d.ts +19 -0
- package/dist/board/model/sampling.js +96 -0
- package/dist/board/{core → model}/scene.d.ts +1 -1
- package/dist/board/{core → model}/scene.js +1 -1
- package/dist/board/model/script-example.d.ts +4 -0
- package/dist/board/model/script-example.js +21 -0
- package/dist/board/model/script-hit.d.ts +10 -0
- package/dist/board/model/script-hit.js +52 -0
- package/dist/board/model/script-index.d.ts +7 -0
- package/dist/board/model/script-index.js +15 -0
- package/dist/board/model/script-scene.d.ts +24 -0
- package/dist/board/model/script-scene.js +267 -0
- package/dist/board/model/script.d.ts +105 -0
- package/dist/board/model/script.js +1 -0
- package/dist/board/model/shape-types.d.ts +8 -0
- package/dist/board/model/shape-types.js +8 -0
- package/dist/board/{task.d.ts → model/task.d.ts} +4 -4
- package/dist/board/{task.js → model/task.js} +3 -3
- package/dist/board/{core → model}/text-metrics.d.ts +1 -1
- package/dist/board/{core → model}/text-metrics.js +1 -1
- package/dist/board/{core → model}/tool-styles.d.ts +1 -1
- package/dist/board/{core → model}/tool-styles.js +1 -1
- package/dist/board/{runtime/board-player.d.ts → player/index.d.ts} +2 -2
- package/dist/board/{runtime/board-player.js → player/index.js} +5 -4
- package/dist/board/render/board-background.d.ts +1 -1
- package/dist/board/render/clip.d.ts +1 -1
- package/dist/board/render/css-color.d.ts +6 -1
- package/dist/board/render/css-color.js +34 -20
- package/dist/board/render/diagnostics.d.ts +20 -0
- package/dist/board/render/diagnostics.js +117 -0
- package/dist/board/render/index.d.ts +9 -6
- package/dist/board/render/index.js +10 -7
- package/dist/board/render/media-interaction.d.ts +2 -2
- package/dist/board/render/media-interaction.js +1 -1
- package/dist/board/render/palette.d.ts +3 -2
- package/dist/board/render/palette.js +7 -3
- package/dist/board/render/renderers/arrow-card-renderer.js +4 -3
- package/dist/board/render/renderers/audio-card-renderer.js +2 -1
- package/dist/board/render/renderers/board-renderer-registry.d.ts +20 -10
- package/dist/board/render/renderers/board-renderer-registry.js +17 -17
- package/dist/board/render/renderers/custom-card-renderer.d.ts +5 -0
- package/dist/board/render/renderers/{sketch-card-renderer.js → custom-card-renderer.js} +16 -15
- package/dist/board/render/renderers/draw-card-renderer.js +4 -3
- package/dist/board/render/renderers/effect-card-renderer.js +22 -5
- package/dist/board/render/renderers/far-plate.js +1 -1
- package/dist/board/render/renderers/file-card-renderer.d.ts +1 -1
- package/dist/board/render/renderers/file-card-renderer.js +2 -2
- package/dist/board/render/renderers/frame-card-renderer.js +30 -14
- package/dist/board/render/renderers/image-card-renderer.d.ts +1 -1
- package/dist/board/render/renderers/image-card-renderer.js +43 -4
- package/dist/board/render/renderers/shape-card-renderer.js +11 -28
- package/dist/board/render/renderers/task-card-renderer.js +1 -1
- package/dist/board/render/renderers/text-card-renderer.js +6 -4
- package/dist/board/render/renderers/unknown-card-renderer.js +1 -0
- package/dist/board/render/renderers/video-card-renderer.d.ts +1 -1
- package/dist/board/render/renderers/video-card-renderer.js +2 -1
- package/dist/board/render/sampling.d.ts +22 -0
- package/dist/board/render/sampling.js +21 -0
- package/dist/board/render/script-export.d.ts +11 -0
- package/dist/board/render/script-export.js +86 -0
- package/dist/board/render/script-host.d.ts +31 -0
- package/dist/board/render/script-host.js +421 -0
- package/dist/board/render/script-modules.d.ts +2 -0
- package/dist/board/render/script-modules.js +2 -0
- package/dist/board/render/script-runtime.d.ts +29 -0
- package/dist/board/render/script-runtime.js +213 -0
- package/dist/board/render/script-sandbox.d.ts +4 -0
- package/dist/board/render/script-sandbox.js +173 -0
- package/dist/board/render/stroke.d.ts +3 -2
- package/dist/board/render/stroke.js +23 -2
- package/dist/board/render/text-measurement.js +2 -2
- package/dist/board/replica/index.d.ts +70 -0
- package/dist/board/replica/index.js +276 -0
- package/dist/board/stage/assets.d.ts +41 -0
- package/dist/board/stage/assets.js +355 -0
- package/dist/board/stage/index.d.ts +8 -0
- package/dist/board/stage/index.js +8 -0
- package/dist/board/stage/lru.d.ts +32 -0
- package/dist/board/stage/lru.js +29 -0
- package/dist/board/stage/maintenance.d.ts +5 -0
- package/dist/board/stage/maintenance.js +11 -0
- package/dist/board/stage/pointer.d.ts +8 -0
- package/dist/board/stage/pointer.js +33 -0
- package/dist/board/stage/scene.d.ts +85 -0
- package/dist/board/stage/scene.js +515 -0
- package/dist/board/stage/script-pointer.d.ts +19 -0
- package/dist/board/stage/script-pointer.js +35 -0
- package/dist/board/stage/stage.d.ts +76 -0
- package/dist/board/stage/stage.js +774 -0
- package/dist/board/stage/texture-pool.d.ts +24 -0
- package/dist/board/stage/texture-pool.js +153 -0
- package/dist/board/stage/views.d.ts +38 -0
- package/dist/board/stage/views.js +93 -0
- package/dist/chunks/environment.d.ts +289 -23
- package/dist/chunks/host-bridge.d.ts +2 -2
- package/dist/chunks/http.d.ts +185 -71
- package/dist/chunks/http.js +368 -269
- package/dist/chunks/transport.js +3 -1
- package/dist/chunks/websocket.d.ts +9 -1
- package/dist/chunks/websocket.js +16 -2
- package/dist/host-bridge.js +2 -1
- package/dist/http.d.ts +2 -2
- package/dist/index.d.ts +182 -4
- package/dist/index.js +1393 -129
- package/dist/media.d.ts +1 -10
- package/dist/media.js +16 -27
- package/dist/protocol/dist/board-assets.d.ts +1 -0
- package/dist/protocol/dist/board-constants.js +2 -2
- package/dist/protocol/dist/board-model.d.ts +201 -11
- package/dist/protocol/dist/board-model.js +33 -14
- package/dist/protocol/dist/board-patch.js +3 -2
- package/dist/protocol/dist/board-schema.d.ts +4 -2
- package/dist/protocol/dist/board-schema.js +18 -4
- package/dist/protocol/dist/board-script-modules.d.ts +25 -0
- package/dist/protocol/dist/board-script-modules.js +127 -0
- package/dist/protocol/dist/board.d.ts +28 -2
- package/dist/protocol/dist/board.js +3 -1
- package/dist/protocol/dist/core/media.d.ts +5 -0
- package/dist/protocol/dist/core/media.js +39 -0
- package/dist/protocol/dist/display/index.d.ts +1 -0
- package/dist/protocol/dist/index.d.ts +7 -5
- package/dist/protocol/dist/realtime/types.d.ts +1 -0
- package/dist/protocol/dist/rtc/index.d.ts +1 -0
- package/dist/types.d.ts +1 -1
- package/package.json +21 -8
- package/dist/board/core/shape-definition.d.ts +0 -23
- package/dist/board/core/shape-definition.js +0 -45
- package/dist/board/core/shape-types.d.ts +0 -38
- package/dist/board/core/shape-types.js +0 -22
- package/dist/board/headless/index.d.ts +0 -55
- package/dist/board/headless/sketch.d.ts +0 -19
- package/dist/board/headless/sketch.js +0 -146
- package/dist/board/index.d.ts +0 -30
- package/dist/board/index.js +0 -29
- package/dist/board/render/renderers/sketch-card-renderer.d.ts +0 -5
- package/dist/board/render/sketch-host.d.ts +0 -14
- package/dist/board/render/sketch-host.js +0 -216
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { buildBoardScene } from "../model/scene.js";
|
|
2
|
+
import { resolveBoardAnimationCamera } from "../model/sampling.js";
|
|
3
|
+
import { normalizeBoardDocument, planBoardExport } from "../model/export-plan.js";
|
|
4
4
|
import { parseBoardCssColor } from "../render/css-color.js";
|
|
5
5
|
import { defaultBoardPalette } from "../render/palette.js";
|
|
6
|
+
import { createBoardRenderSampler } from "../render/sampling.js";
|
|
6
7
|
import { ensureBoardTextMeasurement } from "../render/text-measurement.js";
|
|
7
8
|
import { createBoardExportScene } from "./scene.js";
|
|
8
9
|
import { Rectangle } from "pixi.js";
|
|
@@ -14,20 +15,51 @@ function resolveBackground(background, palette, document, colorScheme) {
|
|
|
14
15
|
const css = typeof declared === "object" ? declared[colorScheme] : declared;
|
|
15
16
|
return css ? parseBoardCssColor(css) ?? palette.bg : palette.bg;
|
|
16
17
|
}
|
|
17
|
-
function
|
|
18
|
+
function prepareBoardExport(input, options = {}) {
|
|
18
19
|
ensureBoardTextMeasurement();
|
|
19
|
-
const base = normalizeBoardDocument(input);
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const base = options.sampler ? input : normalizeBoardDocument(input);
|
|
21
|
+
if (options.camera && options.region && options.region.kind !== "all") throw new Error("Camera export cannot be combined with a fixed region.");
|
|
22
|
+
if (options.camera && !options.at) throw new Error("Camera export needs an animation time.");
|
|
23
|
+
if (options.camera && ![options.camera.width, options.camera.height].every((n) => Number.isSafeInteger(n) && n > 0)) throw new Error("Camera dimensions must be positive integers.");
|
|
24
|
+
const sampler = options.at ? options.sampler ?? createBoardRenderSampler(base, options.at.animation ?? null, options) : void 0;
|
|
25
|
+
const sample = options.at ? sampler?.at(options.at.time) : void 0;
|
|
26
|
+
const sampled = sample?.document ?? base;
|
|
27
|
+
const document = options.scripts?.document?.(sampled, options.at?.time ?? 0) ?? sampled;
|
|
28
|
+
const scene = document === sampled ? sample?.scene ?? buildBoardScene(document) : buildBoardScene(document);
|
|
29
|
+
const camera = options.camera ? resolveBoardAnimationCamera(sample?.evaluation.camera ?? {}, (id) => scene.get(id)?.frame, options.camera, options.at?.time ?? 0) : void 0;
|
|
30
|
+
const region = camera && options.camera ? {
|
|
31
|
+
kind: "rect",
|
|
32
|
+
rect: {
|
|
33
|
+
x: -camera.x / camera.zoom,
|
|
34
|
+
y: -camera.y / camera.zoom,
|
|
35
|
+
width: options.camera.width / camera.zoom,
|
|
36
|
+
height: options.camera.height / camera.zoom
|
|
37
|
+
}
|
|
38
|
+
} : options.region ?? { kind: "all" };
|
|
22
39
|
const plan = planBoardExport({
|
|
23
40
|
scene,
|
|
24
|
-
region
|
|
25
|
-
scale: options.scale,
|
|
26
|
-
padding: options.padding,
|
|
41
|
+
region,
|
|
42
|
+
scale: camera?.zoom ?? options.scale,
|
|
43
|
+
padding: camera ? 0 : options.padding,
|
|
27
44
|
maxEdge: options.maxEdge,
|
|
28
45
|
maxPixels: options.maxPixels
|
|
29
46
|
});
|
|
30
|
-
if (
|
|
47
|
+
if (plan && camera && options.camera) {
|
|
48
|
+
const ratio = plan.clamped ? plan.scale / camera.zoom : 1;
|
|
49
|
+
plan.width = Math.max(1, Math.floor(options.camera.width * ratio));
|
|
50
|
+
plan.height = Math.max(1, Math.floor(options.camera.height * ratio));
|
|
51
|
+
}
|
|
52
|
+
return plan ? {
|
|
53
|
+
document,
|
|
54
|
+
scene,
|
|
55
|
+
plan,
|
|
56
|
+
sampler
|
|
57
|
+
} : null;
|
|
58
|
+
}
|
|
59
|
+
function renderBoardExport(renderer, input, options = {}) {
|
|
60
|
+
const prepared = prepareBoardExport(input, options);
|
|
61
|
+
if (!prepared) return null;
|
|
62
|
+
const { document, scene, plan, sampler } = prepared;
|
|
31
63
|
const colorScheme = options.colorScheme ?? "dark";
|
|
32
64
|
const palette = {
|
|
33
65
|
...defaultBoardPalette(colorScheme),
|
|
@@ -38,14 +70,16 @@ function renderBoardExport(renderer, input, options = {}) {
|
|
|
38
70
|
scene,
|
|
39
71
|
items: plan.items,
|
|
40
72
|
time: options.at?.time ?? 0,
|
|
73
|
+
frameAt: sampler?.frameAt,
|
|
41
74
|
world: plan.world,
|
|
42
75
|
scale: plan.scale,
|
|
43
76
|
colorScheme,
|
|
44
77
|
palette,
|
|
45
78
|
colors: options.colors,
|
|
46
79
|
textures: options.textures,
|
|
47
|
-
|
|
80
|
+
scripts: options.scripts,
|
|
48
81
|
assetKey: options.assetKey,
|
|
82
|
+
renderers: options.renderers,
|
|
49
83
|
background: resolveBackground(options.background, palette, document, colorScheme),
|
|
50
84
|
backgroundImage: options.backgroundImage
|
|
51
85
|
});
|
|
@@ -88,4 +122,4 @@ function describeBoardExportWarning(warning) {
|
|
|
88
122
|
}
|
|
89
123
|
}
|
|
90
124
|
//#endregion
|
|
91
|
-
export { createBoardExportScene, describeBoardExportWarning, renderBoardExport };
|
|
125
|
+
export { createBoardExportScene, describeBoardExportWarning, prepareBoardExport, renderBoardExport };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { BoardDocument } from "../../../protocol/dist/board-model.js";
|
|
2
|
+
import "../../../protocol/dist/index.js";
|
|
3
|
+
import { BoardScriptHost } from "../../render/renderers/board-renderer-registry.js";
|
|
4
|
+
import { BoardExportOptions, BoardExportResult } from "../index.js";
|
|
5
|
+
import { createNodeBoardScriptHost } from "./scripts.js";
|
|
6
|
+
import { Renderer } from "pixi.js";
|
|
7
|
+
//#region src/board/export/node/index.d.ts
|
|
8
|
+
type NodeCanvasModule = {
|
|
9
|
+
createCanvas: (width: number, height: number) => unknown;
|
|
10
|
+
Image: new () => unknown;
|
|
11
|
+
GlobalFonts: {
|
|
12
|
+
registerFromPath: (path: string, name?: string) => unknown;
|
|
13
|
+
has: (name: string) => boolean;
|
|
14
|
+
setAlias?: (fontName: string, alias: string) => boolean;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
type BoardNodeFont = {
|
|
18
|
+
path: string;
|
|
19
|
+
family?: string;
|
|
20
|
+
};
|
|
21
|
+
type BoardNodeRendererOptions = {
|
|
22
|
+
fonts?: BoardNodeFont[];
|
|
23
|
+
canvasModule?: NodeCanvasModule;
|
|
24
|
+
};
|
|
25
|
+
type BoardNodeTexture = {
|
|
26
|
+
readonly __boardTexture: unique symbol;
|
|
27
|
+
destroy: (destroySource?: boolean) => void;
|
|
28
|
+
};
|
|
29
|
+
type BoardNodeRenderer = {
|
|
30
|
+
renderer: Renderer;
|
|
31
|
+
canvasModule: NodeCanvasModule;
|
|
32
|
+
decodeImage: (bytes: Uint8Array, mimeType?: string) => Promise<BoardNodeTexture>;
|
|
33
|
+
destroy: () => void;
|
|
34
|
+
};
|
|
35
|
+
declare function createNodeBoardRenderer(options?: BoardNodeRendererOptions): Promise<BoardNodeRenderer>;
|
|
36
|
+
type BoardNodeExportFormat = "png" | "jpeg" | "webp";
|
|
37
|
+
type BoardNodeExportOptions = Omit<BoardExportOptions, "textures" | "backgroundImage"> & {
|
|
38
|
+
textures?: Map<string, BoardNodeTexture>;
|
|
39
|
+
backgroundImage?: {
|
|
40
|
+
texture: BoardNodeTexture;
|
|
41
|
+
fit: "cover" | "contain" | "repeat";
|
|
42
|
+
position: "center" | "top" | "bottom" | "left" | "right";
|
|
43
|
+
opacity: number;
|
|
44
|
+
};
|
|
45
|
+
scripts?: BoardScriptHost;
|
|
46
|
+
format?: BoardNodeExportFormat;
|
|
47
|
+
quality?: number;
|
|
48
|
+
};
|
|
49
|
+
type BoardNodeExportResult = Omit<BoardExportResult, "canvas"> & {
|
|
50
|
+
bytes: Uint8Array;
|
|
51
|
+
format: BoardNodeExportFormat;
|
|
52
|
+
};
|
|
53
|
+
declare function boardImageMimeType(format: BoardNodeExportFormat): string;
|
|
54
|
+
declare function exportBoardImageBytes(renderer: BoardNodeRenderer, document: BoardDocument, options?: BoardNodeExportOptions): BoardNodeExportResult | null;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { BoardNodeExportFormat, BoardNodeExportOptions, BoardNodeExportResult, BoardNodeFont, BoardNodeRenderer, BoardNodeRendererOptions, BoardNodeTexture, NodeCanvasModule, boardImageMimeType, createNodeBoardRenderer, createNodeBoardScriptHost, exportBoardImageBytes };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import { installBoardTextMeasurement } from "
|
|
3
|
-
import { renderBoardExport } from "../
|
|
4
|
-
import {
|
|
1
|
+
import "../../../protocol/dist/board-constants.js";
|
|
2
|
+
import { installBoardTextMeasurement } from "../../render/text-measurement.js";
|
|
3
|
+
import { renderBoardExport } from "../index.js";
|
|
4
|
+
import { createNodeBoardScriptHost } from "./scripts.js";
|
|
5
5
|
import { CanvasGraphicsContextSystem, CanvasGraphicsPipe, CanvasRenderer, CanvasRendererTextSystem, CanvasTextPipe, CanvasTextSystem, DOMAdapter, GraphicsContextSystem, GraphicsPipe, ImageSource, Texture, extensions } from "pixi.js";
|
|
6
|
-
//#region src/board/
|
|
6
|
+
//#region src/board/export/node/index.ts
|
|
7
7
|
const SYSTEM_UI_FAMILIES = [
|
|
8
8
|
"Noto Sans",
|
|
9
9
|
"DejaVu Sans",
|
|
@@ -61,7 +61,7 @@ function installAnimationFrameShim() {
|
|
|
61
61
|
globals.cancelAnimationFrame = void 0;
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
async function
|
|
64
|
+
async function createNodeBoardRenderer(options = {}) {
|
|
65
65
|
const canvasModule = options.canvasModule ?? await loadCanvasModule();
|
|
66
66
|
extensions.add(CanvasGraphicsPipe, GraphicsPipe, CanvasGraphicsContextSystem, GraphicsContextSystem, CanvasRendererTextSystem, CanvasTextSystem, CanvasTextPipe);
|
|
67
67
|
for (const font of options.fonts ?? []) canvasModule.GlobalFonts.registerFromPath(font.path, font.family ?? "Geist");
|
|
@@ -78,14 +78,14 @@ async function createBoardHeadlessRenderer(options = {}) {
|
|
|
78
78
|
getCanvasRenderingContext2D: () => createCanvas(1, 1).getContext("2d").constructor,
|
|
79
79
|
getWebGLRenderingContext: () => WEBGL_PROBE_STUB,
|
|
80
80
|
getNavigator: () => ({
|
|
81
|
-
userAgent: "cohub-board-
|
|
81
|
+
userAgent: "cohub-board-node",
|
|
82
82
|
gpu: null
|
|
83
83
|
}),
|
|
84
84
|
getBaseUrl: () => "file://",
|
|
85
85
|
getFontFaceSet: () => null,
|
|
86
86
|
fetch: (url, init) => fetch(url, init),
|
|
87
87
|
parseXML: () => {
|
|
88
|
-
throw new Error("XML parsing is not available in
|
|
88
|
+
throw new Error("XML parsing is not available in Node board export.");
|
|
89
89
|
}
|
|
90
90
|
});
|
|
91
91
|
installBoardTextMeasurement();
|
|
@@ -127,14 +127,14 @@ const MIME = {
|
|
|
127
127
|
jpeg: "image/jpeg",
|
|
128
128
|
webp: "image/webp"
|
|
129
129
|
};
|
|
130
|
-
function
|
|
130
|
+
function boardImageMimeType(format) {
|
|
131
131
|
return MIME[format];
|
|
132
132
|
}
|
|
133
|
-
function exportBoardImageBytes(
|
|
134
|
-
const { format = "png", quality = .92, textures,
|
|
135
|
-
const result = renderBoardExport(
|
|
133
|
+
function exportBoardImageBytes(renderer, document, options = {}) {
|
|
134
|
+
const { format = "png", quality = .92, textures, scripts, backgroundImage, ...rest } = options;
|
|
135
|
+
const result = renderBoardExport(renderer.renderer, document, {
|
|
136
136
|
...rest,
|
|
137
|
-
...
|
|
137
|
+
...scripts ? { scripts } : {},
|
|
138
138
|
...textures ? { textures } : {},
|
|
139
139
|
...backgroundImage ? { backgroundImage: {
|
|
140
140
|
...backgroundImage,
|
|
@@ -143,13 +143,18 @@ function exportBoardImageBytes(headless, document, options = {}) {
|
|
|
143
143
|
});
|
|
144
144
|
if (!result) return null;
|
|
145
145
|
const canvas = result.canvas;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
146
|
+
try {
|
|
147
|
+
const bytes = format === "png" ? canvas.toBuffer(MIME.png) : canvas.toBuffer(MIME[format], Math.round(quality * 100));
|
|
148
|
+
return {
|
|
149
|
+
bytes: new Uint8Array(bytes),
|
|
150
|
+
plan: result.plan,
|
|
151
|
+
warnings: result.warnings,
|
|
152
|
+
format
|
|
153
|
+
};
|
|
154
|
+
} finally {
|
|
155
|
+
canvas.width = 1;
|
|
156
|
+
canvas.height = 1;
|
|
157
|
+
}
|
|
153
158
|
}
|
|
154
159
|
//#endregion
|
|
155
|
-
export {
|
|
160
|
+
export { boardImageMimeType, createNodeBoardRenderer, createNodeBoardScriptHost, exportBoardImageBytes };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BoardSceneItem } from "../../model/scene.js";
|
|
2
|
+
import { BoardScriptHost } from "../../render/renderers/board-renderer-registry.js";
|
|
3
|
+
import { BoardNodeRenderer } from "./index.js";
|
|
4
|
+
//#region src/board/export/node/scripts.d.ts
|
|
5
|
+
type BoardNodeScriptOptions = {
|
|
6
|
+
readModule(src: string): Promise<string>;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
readTimeoutMs?: number;
|
|
9
|
+
};
|
|
10
|
+
declare function createNodeBoardScriptHost(renderer: BoardNodeRenderer, options: BoardNodeScriptOptions): BoardScriptHost & {
|
|
11
|
+
prepare(items: readonly BoardSceneItem[], times: readonly number[], zoom: number): Promise<void>;
|
|
12
|
+
clearFrames(): void;
|
|
13
|
+
destroy(): void;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { BoardNodeScriptOptions, createNodeBoardScriptHost };
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { boardScriptScope, composeBoardScriptItems } from "../../model/script-scene.js";
|
|
2
|
+
import { buildBoardScene } from "../../model/scene.js";
|
|
3
|
+
import { createBoardScriptModuleReader, loadBoardScriptSources } from "../../../protocol/dist/board-script-modules.js";
|
|
4
|
+
import { createScriptRuntime } from "../../render/script-runtime.js";
|
|
5
|
+
import { Worker } from "node:worker_threads";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
//#region src/board/export/node/scripts.ts
|
|
8
|
+
const WORKER = `
|
|
9
|
+
const {parentPort, workerData} = require('node:worker_threads');
|
|
10
|
+
const {createContext, Script, SourceTextModule} = require('node:vm');
|
|
11
|
+
const {createCanvas} = require(workerData.canvasModule);
|
|
12
|
+
const instances = new Map();
|
|
13
|
+
const graphs = new Map();
|
|
14
|
+
const update = new Script('__runtime.update(JSON.parse(__inputJson)); __runtime.step(__time)');
|
|
15
|
+
const draw = new Script('__runtime.draw(__drawing)');
|
|
16
|
+
const output = new Script('JSON.stringify(__runtime.output())');
|
|
17
|
+
const dispose = new Script('__runtime.destroy()');
|
|
18
|
+
function release(id) {
|
|
19
|
+
const entry=instances.get(id);instances.delete(id);
|
|
20
|
+
if(entry) {try {dispose.runInContext(entry.context,{timeout:workerData.timeout});} catch {}}
|
|
21
|
+
}
|
|
22
|
+
async function create(data) {
|
|
23
|
+
const context = createContext({console:{log(){},warn(){},error(){}},structuredClone},{codeGeneration:{strings:false,wasm:false}});
|
|
24
|
+
new Script("const __name=(value,name)=>Object.defineProperty(value,'name',{value:name,configurable:true})").runInContext(context);
|
|
25
|
+
const sources = graphs.get(data.src);
|
|
26
|
+
if(!sources) throw new Error('Module graph is unavailable.');
|
|
27
|
+
const modules = new Map();
|
|
28
|
+
const resolve = (from,name) => {
|
|
29
|
+
const parts=from.split('/').slice(0,-1);
|
|
30
|
+
for(const part of name.split('/')) { if(part==='..') parts.pop(); else if(part!=='.') parts.push(part); }
|
|
31
|
+
return parts.join('/');
|
|
32
|
+
};
|
|
33
|
+
const link = (name,ref) => load(resolve(ref.identifier,name));
|
|
34
|
+
function load(path) {
|
|
35
|
+
if(modules.has(path)) return modules.get(path);
|
|
36
|
+
const source=sources[path];
|
|
37
|
+
if(!source) throw new Error('Module is unavailable: '+path);
|
|
38
|
+
const module=new SourceTextModule(source.code,{context,identifier:path,importModuleDynamically:async name=>{
|
|
39
|
+
const child=load(resolve(path,name));
|
|
40
|
+
if(child.status==='unlinked') await child.link(link);
|
|
41
|
+
if(child.status==='linked') await child.evaluate({timeout:workerData.timeout});
|
|
42
|
+
return child;
|
|
43
|
+
}});
|
|
44
|
+
modules.set(path,module);return module;
|
|
45
|
+
}
|
|
46
|
+
const root=load(data.src);
|
|
47
|
+
await root.link(link);await root.evaluate({timeout:workerData.timeout});
|
|
48
|
+
context.__module=root.namespace;
|
|
49
|
+
context.__inputJson=JSON.stringify(data.input);
|
|
50
|
+
new Script('globalThis.__runtime=('+workerData.runtime+')(__module,JSON.parse(__inputJson),{call:async()=>{throw new Error("Capabilities are unavailable during export.")},invalidate(){}})').runInContext(context,{timeout:workerData.timeout});
|
|
51
|
+
return {context,signature:data.signature,time:-1,draw:!!root.namespace.draw,canvas:null};
|
|
52
|
+
}
|
|
53
|
+
parentPort.on('message',async data=>{
|
|
54
|
+
try {
|
|
55
|
+
if(data.release) {for(const id of data.release) release(id);return;}
|
|
56
|
+
if(data.sources) graphs.set(data.src,data.sources);
|
|
57
|
+
let entry=instances.get(data.input.id);
|
|
58
|
+
if(!entry || entry.signature!==data.signature || data.time<entry.time) {
|
|
59
|
+
release(data.input.id);
|
|
60
|
+
entry=await create(data);instances.set(data.input.id,entry);
|
|
61
|
+
}
|
|
62
|
+
const context=entry.context;
|
|
63
|
+
context.__inputJson=JSON.stringify(data.input);context.__time=data.time;
|
|
64
|
+
update.runInContext(context,{timeout:workerData.timeout});entry.time=data.time;
|
|
65
|
+
let png;
|
|
66
|
+
if(entry.draw) {
|
|
67
|
+
const width=Math.max(1,Math.round(data.input.width*data.scale));
|
|
68
|
+
const height=Math.max(1,Math.round(data.input.height*data.scale));
|
|
69
|
+
const canvas=entry.canvas??=createCanvas(width,height);
|
|
70
|
+
canvas.width=width;canvas.height=height;
|
|
71
|
+
const drawing=canvas.getContext('2d');drawing.scale(data.scale,data.scale);
|
|
72
|
+
context.__drawing=drawing;draw.runInContext(context,{timeout:workerData.timeout});
|
|
73
|
+
png=canvas.toBuffer('image/png');delete context.__drawing;
|
|
74
|
+
}
|
|
75
|
+
parentPort.postMessage({png,output:JSON.parse(output.runInContext(context,{timeout:workerData.timeout}))});
|
|
76
|
+
} catch(error) { instances.delete(data.input?.id);parentPort.postMessage({error:String(error.stack||error)}); }
|
|
77
|
+
});
|
|
78
|
+
`;
|
|
79
|
+
function createNodeBoardScriptHost(renderer, options) {
|
|
80
|
+
const textures = /* @__PURE__ */ new Map();
|
|
81
|
+
const outputs = /* @__PURE__ */ new Map();
|
|
82
|
+
const errors = /* @__PURE__ */ new Map();
|
|
83
|
+
const sources = /* @__PURE__ */ new Map();
|
|
84
|
+
const modules = createBoardScriptModuleReader(options.readModule, options.readTimeoutMs);
|
|
85
|
+
const lanes = Array.from({ length: 4 }, () => ({
|
|
86
|
+
worker: null,
|
|
87
|
+
tail: Promise.resolve(),
|
|
88
|
+
graphs: /* @__PURE__ */ new Set()
|
|
89
|
+
}));
|
|
90
|
+
const assignments = /* @__PURE__ */ new Map();
|
|
91
|
+
let disposed = false;
|
|
92
|
+
let nextLane = 0;
|
|
93
|
+
const timeout = options.timeoutMs ?? 2e3;
|
|
94
|
+
const key = (id, time) => `${id}|${time}`;
|
|
95
|
+
function stop(lane) {
|
|
96
|
+
const worker = lane.worker;
|
|
97
|
+
lane.worker = null;
|
|
98
|
+
lane.graphs.clear();
|
|
99
|
+
worker?.terminate();
|
|
100
|
+
}
|
|
101
|
+
function sample(input, graph, time, scale) {
|
|
102
|
+
let lane = assignments.get(input.id);
|
|
103
|
+
if (!lane) {
|
|
104
|
+
lane = lanes[nextLane++ % lanes.length];
|
|
105
|
+
assignments.set(input.id, lane);
|
|
106
|
+
}
|
|
107
|
+
const selected = lane;
|
|
108
|
+
const task = selected.tail.then(() => new Promise((resolve, reject) => {
|
|
109
|
+
if (disposed) {
|
|
110
|
+
reject(/* @__PURE__ */ new Error("Script host is disposed."));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!Number.isFinite(time) || time < 0 || time > 6e5) {
|
|
114
|
+
reject(/* @__PURE__ */ new Error("Script export time must be between 0 and 600000 ms."));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const freshWorker = !selected.worker;
|
|
118
|
+
selected.worker ??= new Worker(WORKER, {
|
|
119
|
+
eval: true,
|
|
120
|
+
execArgv: ["--experimental-vm-modules", "--disable-warning=ExperimentalWarning"],
|
|
121
|
+
env: {},
|
|
122
|
+
resourceLimits: { maxOldGenerationSizeMb: 128 },
|
|
123
|
+
workerData: {
|
|
124
|
+
runtime: createScriptRuntime.toString(),
|
|
125
|
+
timeout,
|
|
126
|
+
canvasModule: fileURLToPath(import.meta.resolve("@napi-rs/canvas"))
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
const worker = selected.worker;
|
|
130
|
+
if (freshWorker) {
|
|
131
|
+
const stopped = (error) => {
|
|
132
|
+
if (selected.worker !== worker) return;
|
|
133
|
+
if (selected.reject) selected.reject(error);
|
|
134
|
+
else stop(selected);
|
|
135
|
+
};
|
|
136
|
+
worker.on("error", stopped);
|
|
137
|
+
worker.on("exit", () => stopped(/* @__PURE__ */ new Error("Script worker stopped.")));
|
|
138
|
+
}
|
|
139
|
+
const cleanup = () => {
|
|
140
|
+
clearTimeout(timer);
|
|
141
|
+
worker.off("message", message);
|
|
142
|
+
selected.reject = void 0;
|
|
143
|
+
};
|
|
144
|
+
const failure = (error) => {
|
|
145
|
+
cleanup();
|
|
146
|
+
stop(selected);
|
|
147
|
+
reject(error);
|
|
148
|
+
};
|
|
149
|
+
const message = (value) => {
|
|
150
|
+
cleanup();
|
|
151
|
+
if (value.error) reject(new Error(value.error));
|
|
152
|
+
else resolve(value);
|
|
153
|
+
};
|
|
154
|
+
const timer = setTimeout(() => failure(/* @__PURE__ */ new Error("Script export timed out.")), Math.max(timeout, 15e3));
|
|
155
|
+
selected.reject = failure;
|
|
156
|
+
worker.once("message", message);
|
|
157
|
+
const src = input.item.script?.src ?? "";
|
|
158
|
+
worker.postMessage({
|
|
159
|
+
input,
|
|
160
|
+
src,
|
|
161
|
+
signature: JSON.stringify(input.item.script),
|
|
162
|
+
sources: selected.graphs.has(src) ? void 0 : graph,
|
|
163
|
+
time,
|
|
164
|
+
scale
|
|
165
|
+
});
|
|
166
|
+
selected.graphs.add(src);
|
|
167
|
+
}));
|
|
168
|
+
selected.tail = task.catch(() => void 0);
|
|
169
|
+
return task;
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
ready: (id) => [...outputs.values()].some((at) => at.has(id)),
|
|
173
|
+
frame: (item, time) => textures.get(key(item.id, time)) ?? null,
|
|
174
|
+
error: (id) => errors.get(id) ?? null,
|
|
175
|
+
release() {},
|
|
176
|
+
document(document, time) {
|
|
177
|
+
const at = outputs.get(time);
|
|
178
|
+
if (!at?.size) return document;
|
|
179
|
+
const items = { ...document.items };
|
|
180
|
+
for (const [id, item] of composeBoardScriptItems(document, buildBoardScene(document), at)) items[id] = item;
|
|
181
|
+
return {
|
|
182
|
+
...document,
|
|
183
|
+
items
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
clearFrames() {
|
|
187
|
+
for (const texture of textures.values()) texture.destroy(true);
|
|
188
|
+
textures.clear();
|
|
189
|
+
outputs.clear();
|
|
190
|
+
errors.clear();
|
|
191
|
+
},
|
|
192
|
+
async prepare(items, times, zoom) {
|
|
193
|
+
const scripted = items.filter((item) => item.script?.enabled);
|
|
194
|
+
const alive = new Set(scripted.map((item) => item.id));
|
|
195
|
+
for (const [id, lane] of assignments) if (!alive.has(id)) {
|
|
196
|
+
lane.worker?.postMessage({ release: [id] });
|
|
197
|
+
assignments.delete(id);
|
|
198
|
+
}
|
|
199
|
+
if (!scripted.length) return;
|
|
200
|
+
const all = Object.fromEntries(items.map(({ id, frame: _frame, ...item }) => [id, item]));
|
|
201
|
+
await Promise.all(scripted.map(async (item) => {
|
|
202
|
+
const base = all[item.id];
|
|
203
|
+
const src = item.script?.src;
|
|
204
|
+
if (!base || !src) return;
|
|
205
|
+
try {
|
|
206
|
+
let graph = sources.get(src);
|
|
207
|
+
if (!graph) {
|
|
208
|
+
graph = loadBoardScriptSources(src, modules.read, options.readTimeoutMs);
|
|
209
|
+
sources.set(src, graph);
|
|
210
|
+
}
|
|
211
|
+
const resolved = await graph;
|
|
212
|
+
const width = "size" in item ? item.size.width : item.frame.width;
|
|
213
|
+
const height = "size" in item ? item.size.height : item.frame.height;
|
|
214
|
+
const scale = Math.min(4, Math.max(.25, zoom), 2048 / Math.max(1, width, height));
|
|
215
|
+
const scoped = Object.fromEntries([...boardScriptScope({ items: all }, item.id)].flatMap((id) => all[id] ? [[id, all[id]]] : []));
|
|
216
|
+
for (const time of times) {
|
|
217
|
+
const result = await sample({
|
|
218
|
+
id: item.id,
|
|
219
|
+
item: base,
|
|
220
|
+
items: scoped,
|
|
221
|
+
width,
|
|
222
|
+
height
|
|
223
|
+
}, resolved, time, scale);
|
|
224
|
+
if (disposed) return;
|
|
225
|
+
if (result.png) {
|
|
226
|
+
const frameKey = key(item.id, time);
|
|
227
|
+
textures.get(frameKey)?.destroy(true);
|
|
228
|
+
textures.set(frameKey, await renderer.decodeImage(result.png));
|
|
229
|
+
}
|
|
230
|
+
let at = outputs.get(time);
|
|
231
|
+
if (!at) {
|
|
232
|
+
at = /* @__PURE__ */ new Map();
|
|
233
|
+
outputs.set(time, at);
|
|
234
|
+
}
|
|
235
|
+
at.set(item.id, result.output);
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
errors.set(item.id, error instanceof Error ? error.message : String(error));
|
|
239
|
+
}
|
|
240
|
+
}));
|
|
241
|
+
},
|
|
242
|
+
destroy() {
|
|
243
|
+
disposed = true;
|
|
244
|
+
for (const lane of lanes) {
|
|
245
|
+
lane.reject?.(/* @__PURE__ */ new Error("Script host is disposed."));
|
|
246
|
+
stop(lane);
|
|
247
|
+
}
|
|
248
|
+
for (const texture of textures.values()) texture.destroy(true);
|
|
249
|
+
textures.clear();
|
|
250
|
+
outputs.clear();
|
|
251
|
+
sources.clear();
|
|
252
|
+
modules.destroy();
|
|
253
|
+
assignments.clear();
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
export { createNodeBoardScriptHost };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BoardSettings } from "../../protocol/dist/board-model.js";
|
|
2
2
|
import "../../protocol/dist/index.js";
|
|
3
|
-
import { Rect } from "../geometry.js";
|
|
4
|
-
import { BoardScene, BoardSceneItem } from "../
|
|
5
|
-
import { BoardShapeColors } from "../
|
|
6
|
-
import { BoardRenderContext, BoardRenderPalette } from "../render/renderers/board-renderer-registry.js";
|
|
3
|
+
import { Rect } from "../model/geometry.js";
|
|
4
|
+
import { BoardScene, BoardSceneItem } from "../model/scene.js";
|
|
5
|
+
import { BoardShapeColors } from "../model/palette.js";
|
|
6
|
+
import { BoardCardRendererResolver, BoardRenderContext, BoardRenderPalette } from "../render/renderers/board-renderer-registry.js";
|
|
7
7
|
import "../render/index.js";
|
|
8
8
|
import { Container, Texture } from "pixi.js";
|
|
9
9
|
//#region src/board/export/scene.d.ts
|
|
@@ -12,14 +12,17 @@ type BoardExportSceneInput = {
|
|
|
12
12
|
scene: BoardScene;
|
|
13
13
|
items: readonly BoardSceneItem[];
|
|
14
14
|
time?: number;
|
|
15
|
+
frameAt?: BoardRenderContext["frameAt"];
|
|
15
16
|
world: Rect;
|
|
16
17
|
scale: number;
|
|
17
18
|
colorScheme: "dark" | "light";
|
|
18
19
|
palette?: Partial<BoardRenderPalette>;
|
|
19
20
|
colors?: BoardShapeColors;
|
|
20
21
|
textures?: Map<string, Texture>;
|
|
21
|
-
|
|
22
|
+
scripts?: BoardRenderContext["scripts"];
|
|
22
23
|
assetKey?: (item: BoardSceneItem) => string | null;
|
|
24
|
+
/** Renderers for item types beyond the built-ins. */
|
|
25
|
+
renderers?: BoardCardRendererResolver;
|
|
23
26
|
background?: number | null;
|
|
24
27
|
backgroundImage?: {
|
|
25
28
|
texture: Texture;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { clippingAncestor, isClippingFrame, syncClipGroup } from "../render/clip.js";
|
|
1
|
+
import { buildFallbackShapeColors } from "../model/palette.js";
|
|
2
|
+
import { imageAssetKey } from "../model/image-key.js";
|
|
4
3
|
import { defaultBoardPalette } from "../render/palette.js";
|
|
4
|
+
import { clippingAncestor, isClippingFrame, syncClipGroup } from "../render/clip.js";
|
|
5
5
|
import { getBoardCardRenderer } from "../render/renderers/board-renderer-registry.js";
|
|
6
6
|
import { Container, Graphics, Sprite, TilingSprite } from "pixi.js";
|
|
7
7
|
//#region src/board/export/scene.ts
|
|
@@ -13,6 +13,7 @@ function buildContext(input) {
|
|
|
13
13
|
settings: input.settings,
|
|
14
14
|
scene: input.scene,
|
|
15
15
|
time: input.time ?? 0,
|
|
16
|
+
frameAt: input.frameAt,
|
|
16
17
|
selectedIds: /* @__PURE__ */ new Set(),
|
|
17
18
|
hoveredId: null,
|
|
18
19
|
resizingIds: /* @__PURE__ */ new Set(),
|
|
@@ -24,7 +25,7 @@ function buildContext(input) {
|
|
|
24
25
|
colorScheme: input.colorScheme,
|
|
25
26
|
rendererType: "canvas",
|
|
26
27
|
zoom: input.scale,
|
|
27
|
-
|
|
28
|
+
scripts: input.scripts,
|
|
28
29
|
assetKey: input.assetKey ?? imageAssetKey,
|
|
29
30
|
getTexture: (key) => textures.get(key) ?? null,
|
|
30
31
|
hasError: (key) => {
|
|
@@ -75,14 +76,28 @@ function createBoardExportScene(input) {
|
|
|
75
76
|
});
|
|
76
77
|
world.scale.set(input.scale);
|
|
77
78
|
world.position.set(-input.world.x * input.scale, -input.world.y * input.scale);
|
|
79
|
+
const resolve = input.renderers ?? getBoardCardRenderer;
|
|
78
80
|
const groups = /* @__PURE__ */ new Map();
|
|
79
|
-
|
|
81
|
+
function hostFor(item) {
|
|
80
82
|
const clip = clippingAncestor(input.scene, item);
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
const ancestor = clip ? input.scene.get(clip) : void 0;
|
|
84
|
+
if (!ancestor) return world;
|
|
85
|
+
let group = groups.get(ancestor.id);
|
|
86
|
+
if (!group) {
|
|
87
|
+
group = syncClipGroup(void 0, ancestor).group;
|
|
88
|
+
hostFor(ancestor).addChild(group);
|
|
89
|
+
groups.set(ancestor.id, group);
|
|
90
|
+
}
|
|
91
|
+
return group;
|
|
92
|
+
}
|
|
93
|
+
for (const item of input.items) {
|
|
94
|
+
const opacity = input.scene.opacity(item.id);
|
|
95
|
+
if (opacity <= 0) continue;
|
|
96
|
+
const host = hostFor(item);
|
|
97
|
+
const container = resolve(item, context).create(item, context);
|
|
98
|
+
container.alpha = opacity;
|
|
84
99
|
host.addChild(container);
|
|
85
|
-
if (isClippingFrame(item)) {
|
|
100
|
+
if (isClippingFrame(item) && !groups.has(item.id)) {
|
|
86
101
|
const { group } = syncClipGroup(void 0, item);
|
|
87
102
|
host.addChild(group);
|
|
88
103
|
groups.set(item.id, group);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BoardAnimationHeader, BoardColor, BoardDocument, BoardItem, BoardVec2 } from "
|
|
2
|
-
import { BoardValueKind } from "
|
|
3
|
-
import "
|
|
4
|
-
//#region src/board/animation.d.ts
|
|
1
|
+
import { BoardAnimationHeader, BoardColor, BoardDocument, BoardItem, BoardVec2 } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import { BoardValueKind } from "../../protocol/dist/board-patch.js";
|
|
3
|
+
import "../../protocol/dist/index.js";
|
|
4
|
+
//#region src/board/model/animation.d.ts
|
|
5
5
|
type BoardEaseFunction = (progress: number) => number;
|
|
6
6
|
declare function boardEase(ease: string | undefined): BoardEaseFunction;
|
|
7
7
|
declare function boardAnimationTime(header: Pick<BoardAnimationHeader, "duration" | "delay" | "loop" | "end" | "play">, elapsed: number): number | null;
|
|
@@ -35,7 +35,10 @@ type CompiledBoardAnimations = {
|
|
|
35
35
|
readonly document: BoardDocument;
|
|
36
36
|
};
|
|
37
37
|
declare function compileBoardAnimations(document: BoardDocument): CompiledBoardAnimations;
|
|
38
|
-
type BoardColorResolver = (color: BoardColor) => number |
|
|
38
|
+
type BoardColorResolver = (color: BoardColor) => number | {
|
|
39
|
+
color: number;
|
|
40
|
+
alpha: number;
|
|
41
|
+
} | null;
|
|
39
42
|
declare function parseHexColor(color: BoardColor): number | null;
|
|
40
43
|
declare function sampleBoardTrack(track: CompiledTrack, time: number, resolveColor?: BoardColorResolver): unknown;
|
|
41
44
|
type BoardCameraOverride = {
|