@field/cascade 0.11.0 → 0.13.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/AGENTS.md +8 -5
- package/ARCHITECTURE.md +5 -4
- package/CHANGELOG.md +245 -0
- package/README.md +1 -1
- package/dist/assets/AgentPanel-1JugFjE4.css +1 -0
- package/dist/assets/AgentPanel-BDL5MddA.js +5 -0
- package/dist/assets/{CodeEditor-4O7FQ__R.js → CodeEditor-C-xYG-Wn.js} +120 -120
- package/dist/assets/CodePanel-CtXd50m6.js +2 -0
- package/dist/assets/CookInfoPanel-B3NMhKJF.css +1 -0
- package/dist/assets/CookInfoPanel-DG4_TRsX.js +2 -0
- package/dist/assets/CustomNodeDialog-CHfZUs-r.js +1 -0
- package/dist/assets/DefinitionNode-CaRTXQ_b.js +1 -0
- package/dist/assets/DefinitionPanel-C3CxZY9r.js +1 -0
- package/dist/assets/DefinitionPanel-VNLnAiQD.css +1 -0
- package/dist/assets/OpenGraphDialog-BLdr6k_q.js +1 -0
- package/dist/assets/ProjectSettings-ZnvmIAir.js +2 -0
- package/dist/assets/{SettingsDialog-Bz8JxISH.js → SettingsDialog-CBX3Wa87.js} +1 -1
- package/dist/assets/TimelinePanel-CDeR0arY.css +1 -0
- package/dist/assets/TimelinePanel-CWgnFH1e.js +1 -0
- package/dist/assets/{VersionHistoryDialog-D5Z0nJ5-.js → VersionHistoryDialog-BOSoW1R-.js} +1 -1
- package/dist/assets/assert-BO2_erPD.js +1 -0
- package/dist/assets/assert-hvykGCnP.js +1 -0
- package/dist/assets/builder-BmBKcDix.js +1 -0
- package/dist/assets/camera-DFF7YA3F.js +1 -0
- package/dist/assets/checks-DAvyO9Gf.js +1 -0
- package/dist/assets/contactSheet-N1NcaWxw.js +2 -0
- package/dist/assets/{core-Yqi0Ni61.js → core-DB-MkGjj.js} +3 -4
- package/dist/assets/coreTypes-DtnDATZ7.js +1 -0
- package/dist/assets/{cssMode-CxUzc4vp.js → cssMode-DPVckSOc.js} +1 -1
- package/dist/assets/definitions-B227e7f_.js +1 -0
- package/dist/assets/definitions-D0WOUJd7.js +1 -0
- package/dist/assets/{editor.api-BNFb25CX.js → editor.api-Dkutg_Z1.js} +1 -1
- package/dist/assets/expressions-X-Z-GrgW.js +5 -0
- package/dist/assets/file-DAL6IfjV.js +1 -0
- package/dist/assets/filters-D3k1LRMa.js +1 -0
- package/dist/assets/{freemarker2-0ZDnWxeM.js → freemarker2-CLiLKk3B.js} +1 -1
- package/dist/assets/generators-BhDxRAFC.js +1 -0
- package/dist/assets/geo-BsMImJIJ.js +1 -0
- package/dist/assets/geo-C4YngDob.js +2 -0
- package/dist/assets/{handlebars-Cy18MoaD.js → handlebars-CcD3aMeL.js} +1 -1
- package/dist/assets/{html-B-2Dx7nq.js → html-DvZWGfqb.js} +1 -1
- package/dist/assets/{htmlMode-DUAc9B_d.js → htmlMode-DUD3VaoN.js} +1 -1
- package/dist/assets/image-0SfH-snh.js +1 -0
- package/dist/assets/image-Ck-RdGU4.js +2 -0
- package/dist/assets/index-BWnrmIB9.js +137 -0
- package/dist/assets/index-DIaxEONI.css +1 -0
- package/dist/assets/io-BGmt2g0D.js +1 -0
- package/dist/assets/{javascript-DeQsDqP5.js → javascript-Cap2ahgh.js} +1 -1
- package/dist/assets/{jsonMode-BiFwJVSk.js → jsonMode-B0uLjp9C.js} +1 -1
- package/dist/assets/{liquid-BLoHH68a.js → liquid-CnxwhfLn.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-CNFgm1Kv.js → lspLanguageFeatures-Dn9hlKX6.js} +1 -1
- package/dist/assets/math-GeULS-sk.js +1 -0
- package/dist/assets/{mdx-CFXQVNfs.js → mdx-BV3jbrVa.js} +1 -1
- package/dist/assets/pop-KMF_qloi.js +1 -0
- package/dist/assets/preload-helper-Czpn1I53.js +1 -0
- package/dist/assets/{python-Cf7S7p2E.js → python-CGyFk4XK.js} +1 -1
- package/dist/assets/{razor-CMHBcG-g.js → razor-CQfzX3-N.js} +1 -1
- package/dist/assets/remap-5SjXQU-q.js +1 -0
- package/dist/assets/renderMarkdown-ork0Oir7.js +67 -0
- package/dist/assets/studioImages-CAyH-0Pl.js +1 -0
- package/dist/assets/text-ZpX7qNkx.js +2 -0
- package/dist/assets/time-P_OiBhcf.js +1 -0
- package/dist/assets/{tsMode-BEih0GDj.js → tsMode-BOeXzO9H.js} +1 -1
- package/dist/assets/{typescript-COEKYD_a.js → typescript-J1SnE_Tu.js} +1 -1
- package/dist/assets/{workers-BNhAhMNn.js → workers-CYwwTiVF.js} +1 -1
- package/dist/assets/{xml-CPiMpnPl.js → xml-DnPRNzK9.js} +1 -1
- package/dist/assets/{yaml-Bgp1ITLR.js → yaml-BmmYBNa9.js} +1 -1
- package/dist/cli/DefinitionNode-P7AA4TAU.js +15 -0
- package/dist/cli/{Graph-ZJJTRQTM.js → Graph-OB6EWSGL.js} +12 -12
- package/dist/cli/assert-GROGQNCQ.js +25 -0
- package/dist/cli/checks-3WB44XBL.js +189 -0
- package/dist/cli/{chunk-3JTJHF7V.js → chunk-2L34ERS2.js} +4 -4
- package/dist/cli/chunk-53LGFPWX.js +138 -0
- package/dist/cli/chunk-5ORUQ6ES.js +267 -0
- package/dist/cli/{chunk-YAT5Y25U.js → chunk-7QE2ZNSN.js} +3 -3
- package/dist/cli/{chunk-SGJAET2L.js → chunk-BPODRH52.js} +8 -4
- package/dist/cli/{chunk-XWDSKG7N.js → chunk-BZ63XQ3I.js} +2 -2
- package/dist/cli/{chunk-FCDXJ6EK.js → chunk-CTPLRSWF.js} +2 -13
- package/dist/cli/{chunk-WIH4TEIS.js → chunk-EZRWJ4G2.js} +1 -1
- package/dist/cli/{chunk-BIJO5OFS.js → chunk-FWMSGKEH.js} +1 -1
- package/dist/cli/{chunk-POMMNKZZ.js → chunk-G23A2BZZ.js} +38 -5
- package/dist/cli/{chunk-35D343DC.js → chunk-GRIN2DDP.js} +19 -1
- package/dist/cli/{chunk-WKURDVYP.js → chunk-JEW5MPGI.js} +28 -331
- package/dist/cli/chunk-JVOCK5W4.js +83 -0
- package/dist/cli/chunk-KBGUO27Q.js +15 -0
- package/dist/cli/{chunk-GFS6W3C5.js → chunk-L6B6FUQP.js} +54 -32
- package/dist/cli/chunk-LTXWBXOM.js +438 -0
- package/dist/cli/chunk-MI5JLQYA.js +220 -0
- package/dist/cli/{chunk-A4OAMOZH.js → chunk-NJFMDXHR.js} +13 -3
- package/dist/cli/{chunk-DUIUFVU2.js → chunk-OBZAP3GG.js} +49 -23
- package/dist/cli/chunk-QAGATJGE.js +336 -0
- package/dist/cli/{chunk-EUIAC3U3.js → chunk-QKL7CCRS.js} +966 -132
- package/dist/cli/{chunk-RLCAJBVR.js → chunk-TJW67QSI.js} +8 -7
- package/dist/cli/{chunk-RQZ4SX5R.js → chunk-W5PJ5RMP.js} +156 -84
- package/dist/cli/chunk-W7OUAT7J.js +122 -0
- package/dist/cli/chunk-WGKPJZDY.js +364 -0
- package/dist/cli/{chunk-D6BUOHUG.js → chunk-X4WKAOQP.js} +4 -4
- package/dist/cli/{chunk-VVGSLVSF.js → chunk-X566FWBV.js} +6 -1
- package/dist/cli/chunk-YH637PDL.js +317 -0
- package/dist/cli/chunk-ZSCUZE6I.js +112 -0
- package/dist/cli/{cliCommands-UQSFGEHF.js → cliCommands-XVFRD7CF.js} +23 -17
- package/dist/cli/{commands-Q23M26QM.js → commands-M2XLTPTZ.js} +129 -47
- package/dist/cli/contactSheet-2PQVRUFW.js +11 -0
- package/dist/cli/{definitions-HF2FTHYU.js → definitions-BPOPW52L.js} +7 -7
- package/dist/cli/{doctorCommand-B7BPQMN6.js → doctorCommand-RAEI7GVY.js} +36 -6
- package/dist/cli/{edit-JHCPTQFT.js → edit-S5KEQ5RA.js} +3 -3
- package/dist/cli/editorCommands-5BBG4S6V.js +41 -0
- package/dist/cli/{encode-HAUZTYPT.js → encode-ICPEPMH5.js} +2 -2
- package/dist/cli/file-3HTQHPYQ.js +41 -0
- package/dist/cli/filters-6ODFWYK4.js +379 -0
- package/dist/cli/generators-YU7GB4MD.js +210 -0
- package/dist/cli/{geo-4RNK3QVN.js → geo-6ZPGKZRU.js} +7 -7
- package/dist/cli/{graphCommands-6BMAKGQE.js → graphCommands-MULQ7VD2.js} +4 -4
- package/dist/cli/{graphFile-VPSQ6OF7.js → graphFile-CITF36ZM.js} +25 -19
- package/dist/cli/{headlessCanvas-5XLDZT7M.js → headlessCanvas-ENRHC7GS.js} +3 -2
- package/dist/cli/{helpCommand-3VRE3KVO.js → helpCommand-X2QDANM3.js} +9 -7
- package/dist/cli/image-TXELZZK5.js +55 -0
- package/dist/cli/index.js +14 -14
- package/dist/cli/{math-ZRMLKU2D.js → math-RSYRQ3C6.js} +5 -5
- package/dist/cli/{mcp-ZLEEMYGF.js → mcp-YRIGRLYQ.js} +4 -4
- package/dist/cli/{parity-KINARCP2.js → parity-3N3HTKWX.js} +42 -36
- package/dist/cli/{pop-USDFXB7H.js → pop-B7SIIYKN.js} +5 -5
- package/dist/cli/project-SJF5ZF3F.js +12 -0
- package/dist/cli/{projectDefinition-DMTZN2NE.js → projectDefinition-F3D7UIHJ.js} +8 -8
- package/dist/cli/{projectRuntime-Z5PJOH47.js → projectRuntime-NY4XMDFH.js} +19 -12
- package/dist/cli/registerStandardNodes-BXJCB6E4.js +744 -0
- package/dist/cli/{render-YURAPPUI.js → render-Y23W6MY6.js} +29 -22
- package/dist/cli/{runCommand-PI764LEG.js → runCommand-XOG7AVC5.js} +3 -3
- package/dist/cli/runner-DNJO5WO2.js +43 -0
- package/dist/cli/runtime/image.ts +27 -2
- package/dist/cli/runtime/io.ts +78 -0
- package/dist/cli/share-B7HTCOJX.js +166 -0
- package/dist/cli/stageCache-TY2BFZJR.js +15 -0
- package/dist/cli/{stageRunner-KUNIMQKJ.js → stageRunner-KY2EJP7X.js} +2 -2
- package/dist/cli/text-MB3EKR4H.js +126 -0
- package/dist/cli/{verbs-RCE3K4VQ.js → verbs-PI2JH5FI.js} +2 -2
- package/dist/cli/webBuild-2K4COCGY.js +44 -0
- package/dist/contracts/capabilities.d.ts +39 -1
- package/dist/contracts/color.d.ts +8 -0
- package/dist/contracts/color.js +23 -0
- package/dist/contracts/definition.d.ts +10 -0
- package/dist/contracts/schema.d.ts +1 -1
- package/dist/contracts/schema.js +1 -0
- package/dist/contracts/validate.js +11 -1
- package/dist/contracts/values.d.ts +24 -0
- package/dist/image.d.ts +15 -0
- package/dist/image.js +36 -2
- package/dist/index.html +8 -2
- package/dist/io.d.ts +29 -0
- package/dist/io.js +40 -0
- package/dist/player/app.js +11 -7
- package/dist/player/editor.js +3 -2
- package/dist/player/editorEngine.js +3 -2
- package/dist/player/embed.js +2 -0
- package/dist/player/types.d.ts +6 -0
- package/dist/runtime/builtins/assert/checks.d.ts +18 -0
- package/dist/runtime/builtins/assert/checks.js +207 -0
- package/dist/runtime/builtins/assert/definitions.d.ts +130 -0
- package/dist/runtime/builtins/assert/definitions.js +54 -0
- package/dist/runtime/builtins/assert/index.d.ts +152 -0
- package/dist/runtime/builtins/assert/index.js +36 -0
- package/dist/runtime/builtins/image/contactSheet.d.ts +3 -165
- package/dist/runtime/builtins/image/contactSheet.js +0 -49
- package/dist/runtime/builtins/image/definitions.d.ts +950 -0
- package/dist/runtime/builtins/image/definitions.js +343 -0
- package/dist/runtime/builtins/image/file.d.ts +8 -0
- package/dist/runtime/builtins/image/file.js +37 -0
- package/dist/runtime/builtins/image/filters.d.ts +8 -0
- package/dist/runtime/builtins/image/filters.js +394 -0
- package/dist/runtime/builtins/image/generators.d.ts +7 -0
- package/dist/runtime/builtins/image/generators.js +144 -0
- package/dist/runtime/builtins/image/index.d.ts +947 -4
- package/dist/runtime/builtins/image/index.js +41 -6
- package/dist/runtime/builtins/image/io.d.ts +100 -0
- package/dist/runtime/builtins/image/io.js +142 -0
- package/dist/runtime/builtins/image/planar.d.ts +55 -0
- package/dist/runtime/builtins/image/planar.js +274 -0
- package/dist/runtime/builtins/image/simplex.d.ts +22 -0
- package/dist/runtime/builtins/image/simplex.js +92 -0
- package/dist/runtime/builtins/image/text.d.ts +4 -0
- package/dist/runtime/builtins/image/text.js +141 -0
- package/dist/runtime/builtins/index.d.ts +3 -0
- package/dist/runtime/builtins/index.js +7 -0
- package/dist/runtime/definition/architecture.js +89 -0
- package/dist/runtime/gpu.d.ts +25 -0
- package/dist/runtime/gpu.js +40 -0
- package/dist/runtime/runtime.d.ts +2 -0
- package/dist/runtime/runtime.js +268 -44
- package/dist/runtime/types.d.ts +30 -0
- package/doc/CLI_REFERENCE.md +21 -3
- package/doc/EDITOR_EXPORT.md +26 -0
- package/doc/MCP.md +2 -1
- package/doc/NODE_REFERENCE.md +286 -14
- package/doc/PROJECT_AUTHORING.md +158 -4
- package/doc/WEB_PLAYER.md +9 -1
- package/package.json +4 -1
- package/dist/assets/CodePanel-BU-autmq.js +0 -2
- package/dist/assets/CustomNodeDialog-BRpDfOV5.js +0 -1
- package/dist/assets/OpenGraphDialog-BwbRlC0X.js +0 -1
- package/dist/assets/ProjectSettings-DLOXLxcA.js +0 -2
- package/dist/assets/definitions-GreEMXLV.js +0 -1
- package/dist/assets/geo-u0n_jOsD.js +0 -1
- package/dist/assets/image-cAa-Nu9O.js +0 -2062
- package/dist/assets/index-5ZtDAuy2.js +0 -220
- package/dist/assets/index-7vae6YFC.css +0 -1
- package/dist/assets/math-DioIQOPJ.js +0 -1
- package/dist/assets/pop-DC_TQG9t.js +0 -1
- package/dist/cli/chunk-36P5K3SD.js +0 -631
- package/dist/cli/chunk-4UDFYF5G.js +0 -132
- package/dist/cli/chunk-53NMBJAO.js +0 -35
- package/dist/cli/chunk-MIIEFUGG.js +0 -623
- package/dist/cli/chunk-QBBKRNGY.js +0 -90
- package/dist/cli/chunk-WPUDGEFY.js +0 -20
- package/dist/cli/editorCommands-UIF5YLUZ.js +0 -33
- package/dist/cli/project-K3QIPGBB.js +0 -12
- package/dist/cli/registerStandardNodes-S2VLMF6J.js +0 -3081
- package/dist/cli/runner-RA6UKEPD.js +0 -37
- package/dist/cli/webBuild-GT4PZT5D.js +0 -37
- package/dist/runtime/builtins/headless.d.ts +0 -19
- package/dist/runtime/builtins/headless.js +0 -25
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildPlayer,
|
|
3
|
+
canonicalFuturePath,
|
|
4
|
+
exists,
|
|
5
|
+
inside,
|
|
6
|
+
installRoot,
|
|
7
|
+
playerFile,
|
|
8
|
+
staticRuntimePlugin
|
|
9
|
+
} from "./chunk-2L34ERS2.js";
|
|
10
|
+
import "./chunk-QKL7CCRS.js";
|
|
11
|
+
import "./chunk-MI5JLQYA.js";
|
|
12
|
+
import "./chunk-GRIN2DDP.js";
|
|
13
|
+
import "./chunk-X4WKAOQP.js";
|
|
14
|
+
import "./chunk-DEQSEFFH.js";
|
|
15
|
+
import "./chunk-RXDIMXN5.js";
|
|
16
|
+
import "./chunk-QQPA2ZHH.js";
|
|
17
|
+
import "./chunk-KH4MUBKF.js";
|
|
18
|
+
import "./chunk-HSNOBIVT.js";
|
|
19
|
+
import "./chunk-L6B6FUQP.js";
|
|
20
|
+
import "./chunk-HFHWYL55.js";
|
|
21
|
+
import "./chunk-KBGUO27Q.js";
|
|
22
|
+
import "./chunk-ICH7N5PN.js";
|
|
23
|
+
import "./chunk-CO22XHNG.js";
|
|
24
|
+
import "./chunk-LTXWBXOM.js";
|
|
25
|
+
import "./chunk-BZ63XQ3I.js";
|
|
26
|
+
import "./chunk-YH637PDL.js";
|
|
27
|
+
import "./chunk-X566FWBV.js";
|
|
28
|
+
import "./chunk-WD62JIP6.js";
|
|
29
|
+
import "./chunk-5ORUQ6ES.js";
|
|
30
|
+
import "./chunk-W5PJ5RMP.js";
|
|
31
|
+
import "./chunk-NJFMDXHR.js";
|
|
32
|
+
import "./chunk-J7VK7MNF.js";
|
|
33
|
+
import "./chunk-FWMSGKEH.js";
|
|
34
|
+
import "./chunk-JVOCK5W4.js";
|
|
35
|
+
export {
|
|
36
|
+
buildPlayer,
|
|
37
|
+
canonicalFuturePath,
|
|
38
|
+
exists,
|
|
39
|
+
inside,
|
|
40
|
+
installRoot,
|
|
41
|
+
playerFile,
|
|
42
|
+
staticRuntimePlugin
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=webBuild-2K4COCGY.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AssetRef, ImageRef, JsonValue } from "./values.js";
|
|
1
|
+
import type { AssetRef, ImagePixels, ImageRef, JsonValue } from "./values.js";
|
|
2
2
|
export interface CascadeAbortSignal {
|
|
3
3
|
readonly aborted: boolean;
|
|
4
4
|
readonly reason?: unknown;
|
|
@@ -18,10 +18,31 @@ export interface ProgressReporter {
|
|
|
18
18
|
detail?: JsonValue;
|
|
19
19
|
}): void;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* A cache a node finds again by its own key: `put(key, data)` then, on a later
|
|
23
|
+
* cook or run, `get(key)` returns those bytes (or null). Keys are path-like
|
|
24
|
+
* (`stage/3fa9c2…`, letters, digits, `.`, `_`, `-`, `/`-separated) and are never
|
|
25
|
+
* renamed by a content hash. Derive a key from everything the bytes depend on.
|
|
26
|
+
*/
|
|
27
|
+
export interface KeyedCache {
|
|
28
|
+
get(key: string, options: {
|
|
29
|
+
signal: CascadeAbortSignal;
|
|
30
|
+
}): Promise<Uint8Array | null>;
|
|
31
|
+
put(key: string, data: Uint8Array, options: {
|
|
32
|
+
signal: CascadeAbortSignal;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Project files. Reads resolve in the project (and `shared/` and the read-only
|
|
37
|
+
* roots cascade.json `reads` declares). Writes keep the name given, and go to
|
|
38
|
+
* `.cascade-cache/` or a folder cascade.json `writes` declares.
|
|
39
|
+
*/
|
|
21
40
|
export interface FileCapability {
|
|
22
41
|
read(path: string, options: {
|
|
23
42
|
signal: CascadeAbortSignal;
|
|
24
43
|
}): Promise<Uint8Array>;
|
|
44
|
+
/** The keyed cache, under `.cascade-cache/keyed/`. */
|
|
45
|
+
readonly cache: KeyedCache;
|
|
25
46
|
write(path: string, data: Uint8Array, options: {
|
|
26
47
|
signal: CascadeAbortSignal;
|
|
27
48
|
}): Promise<void>;
|
|
@@ -46,6 +67,23 @@ export interface AssetCapability {
|
|
|
46
67
|
signal: CascadeAbortSignal;
|
|
47
68
|
}): Promise<AssetRef>;
|
|
48
69
|
resolveUrl?(ref: AssetRef | ImageRef): Promise<ResourceLease<string>>;
|
|
70
|
+
/**
|
|
71
|
+
* Store an intermediate image from its pixels. Optional; a host without it
|
|
72
|
+
* gets encoded bytes through `write`. The host chooses how: the headless
|
|
73
|
+
* host holds the pixels in memory and writes a fast lossless PNG behind
|
|
74
|
+
* (zlib level 1), or encodes that PNG at once when the run does not keep
|
|
75
|
+
* pixels. The returned path is content-addressed like `write`'s and is a
|
|
76
|
+
* whole file before anything reads it from disk. Finals are not encoded
|
|
77
|
+
* here: a run's saved outputs are encoded at full compression when copied.
|
|
78
|
+
*/
|
|
79
|
+
keepImage?(pixels: ImagePixels, metadata: {
|
|
80
|
+
suggestedName?: string;
|
|
81
|
+
}, options: {
|
|
82
|
+
signal: CascadeAbortSignal;
|
|
83
|
+
}): Promise<AssetRef>;
|
|
84
|
+
/** The pixels behind a stored image while the host still holds them in
|
|
85
|
+
* memory, so a reader skips the read and the decode. */
|
|
86
|
+
imagePixels?(ref: AssetRef | ImageRef): ImagePixels | undefined;
|
|
49
87
|
}
|
|
50
88
|
export interface MediaCapability {
|
|
51
89
|
decodeImage(ref: ImageRef | AssetRef, options: {
|
|
@@ -57,6 +57,14 @@ export declare const Color: Readonly<{
|
|
|
57
57
|
alpha(color: Color): number;
|
|
58
58
|
/** The same colour at full alpha. */
|
|
59
59
|
opaque(color: Color): Color;
|
|
60
|
+
/**
|
|
61
|
+
* A colour saved in an older shape, as the one colour: `{ r, g, b, a? }`
|
|
62
|
+
* (the class-based image nodes stored that until 2026-11-07) or three
|
|
63
|
+
* components, with alpha 1. Components above 1 are read as 0–255, the way
|
|
64
|
+
* those nodes read them. Anything else comes back unchanged, so a reader can
|
|
65
|
+
* apply this to every stored `color` value and validate the result.
|
|
66
|
+
*/
|
|
67
|
+
upgrade(value: unknown): unknown;
|
|
60
68
|
/**
|
|
61
69
|
* Four unit components from anything indexable, clamping and defaulting a
|
|
62
70
|
* missing alpha to 1. The reader for a `Cd` attribute's flat array, and the
|
package/dist/contracts/color.js
CHANGED
|
@@ -70,6 +70,29 @@ export const Color = Object.freeze({
|
|
|
70
70
|
opaque(color) {
|
|
71
71
|
return [clamp(color[0]), clamp(color[1]), clamp(color[2]), 1];
|
|
72
72
|
},
|
|
73
|
+
/**
|
|
74
|
+
* A colour saved in an older shape, as the one colour: `{ r, g, b, a? }`
|
|
75
|
+
* (the class-based image nodes stored that until 2026-11-07) or three
|
|
76
|
+
* components, with alpha 1. Components above 1 are read as 0–255, the way
|
|
77
|
+
* those nodes read them. Anything else comes back unchanged, so a reader can
|
|
78
|
+
* apply this to every stored `color` value and validate the result.
|
|
79
|
+
*/
|
|
80
|
+
upgrade(value) {
|
|
81
|
+
const legacy = value !== null && typeof value === "object" && !Array.isArray(value) && "r" in value && "g" in value && "b" in value
|
|
82
|
+
? value
|
|
83
|
+
: Array.isArray(value) && value.length === 3
|
|
84
|
+
? { r: value[0], g: value[1], b: value[2] }
|
|
85
|
+
: null;
|
|
86
|
+
if (!legacy)
|
|
87
|
+
return value;
|
|
88
|
+
const parts = [legacy.r, legacy.g, legacy.b, legacy.a ?? 1];
|
|
89
|
+
if (!parts.every((part) => typeof part === "number" && Number.isFinite(part)))
|
|
90
|
+
return value;
|
|
91
|
+
const numbers = parts;
|
|
92
|
+
const unit = numbers.slice(0, 3).every((part) => part <= 1);
|
|
93
|
+
const read = (part) => (unit ? part : part / 255);
|
|
94
|
+
return [read(numbers[0]), read(numbers[1]), read(numbers[2]), legacy.a === undefined ? 1 : read(numbers[3])];
|
|
95
|
+
},
|
|
73
96
|
/**
|
|
74
97
|
* Four unit components from anything indexable, clamping and defaulting a
|
|
75
98
|
* missing alpha to 1. The reader for a `Cd` attribute's flat array, and the
|
|
@@ -190,6 +190,16 @@ export interface NodeDefinitionForEnvironment<E extends RuntimeEnvironment> {
|
|
|
190
190
|
*/
|
|
191
191
|
readonly container?: "subnet" | "feedback";
|
|
192
192
|
readonly capabilities?: readonly CapabilityForEnvironment<E>[];
|
|
193
|
+
/**
|
|
194
|
+
* GPU limits this node cannot run without, by WebGPU name, for a node that
|
|
195
|
+
* declares `gpu`: `{ maxStorageBufferBindingSize: 512 * 2 ** 20 }`. The host
|
|
196
|
+
* already asks for everything the adapter allows; this makes a GPU that
|
|
197
|
+
* allows less fail before the cook, naming the limit, instead of with a
|
|
198
|
+
* validation error from inside it. `max*` limits are minimums to reach,
|
|
199
|
+
* `min*Alignment` ones maximums. Read `context.capabilities.gpu.limits` for
|
|
200
|
+
* what the device actually gives.
|
|
201
|
+
*/
|
|
202
|
+
readonly gpuLimits?: Readonly<Record<string, number>>;
|
|
193
203
|
/**
|
|
194
204
|
* `live` marks a node that reads data from outside the graph — an archive,
|
|
195
205
|
* a CLI, a cache, body data, the filesystem or a network. `cascade export`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const nodeDefinitionSchema: {
|
|
2
|
-
readonly allOf: readonly [Readonly<Record<string, unknown>>, Readonly<Record<string, unknown>>, Readonly<Record<string, unknown>>];
|
|
3
2
|
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
4
3
|
readonly $id: "https://cascade.dev/schema/node-definition-v1.json";
|
|
4
|
+
readonly allOf: readonly [Readonly<Record<string, unknown>>, Readonly<Record<string, unknown>>, Readonly<Record<string, unknown>>];
|
|
5
5
|
};
|
|
6
6
|
//# sourceMappingURL=schema.d.ts.map
|
package/dist/contracts/schema.js
CHANGED
|
@@ -19,7 +19,7 @@ export const CAPABILITIES_BY_ENVIRONMENT = {
|
|
|
19
19
|
};
|
|
20
20
|
const ALLOWED = CAPABILITIES_BY_ENVIRONMENT;
|
|
21
21
|
const fields = (names) => new Set(names.split(" "));
|
|
22
|
-
const TOP_FIELDS = fields("apiVersion runsOn container capabilities source label description icon inputs outputs props");
|
|
22
|
+
const TOP_FIELDS = fields("apiVersion runsOn container capabilities gpuLimits source label description icon inputs outputs props");
|
|
23
23
|
const DATA_FIELDS = fields("kind type default description variadic min max step accept control options schema fields");
|
|
24
24
|
const OUTPUT_FIELDS = fields("kind type description schema fields");
|
|
25
25
|
const PROP_FIELDS = fields("type default label description min max step accept control options expression action");
|
|
@@ -111,6 +111,16 @@ export function validateNodeDefinition(value) {
|
|
|
111
111
|
add("duplicate-capability", `${String(capability)} is duplicated`, path);
|
|
112
112
|
seen.add(capability);
|
|
113
113
|
}
|
|
114
|
+
if (value.gpuLimits !== undefined) {
|
|
115
|
+
if (!seen.has("gpu"))
|
|
116
|
+
add("gpu-limits-without-gpu", "gpuLimits needs the gpu capability", "gpuLimits");
|
|
117
|
+
if (!isRecord(value.gpuLimits))
|
|
118
|
+
add("invalid-gpu-limits", "gpuLimits must be an object of WebGPU limit names to numbers", "gpuLimits");
|
|
119
|
+
else
|
|
120
|
+
for (const [name, limit] of Object.entries(value.gpuLimits))
|
|
121
|
+
if (typeof limit !== "number" || !Number.isFinite(limit) || limit < 0)
|
|
122
|
+
add("invalid-gpu-limits", `gpuLimits.${name} must be a non-negative number`, `gpuLimits.${name}`);
|
|
123
|
+
}
|
|
114
124
|
// Two namespaces, not one. An output is addressed in the other direction from
|
|
115
125
|
// an input, so `geometry` in and `geometry` out is not ambiguous anywhere: the
|
|
116
126
|
// document format names the two endpoints of a connection separately, the
|
|
@@ -51,6 +51,18 @@ export type Mat4 = readonly [
|
|
|
51
51
|
number,
|
|
52
52
|
number
|
|
53
53
|
];
|
|
54
|
+
/**
|
|
55
|
+
* The value on an `image` port: a path naming stored pixels, plus what they
|
|
56
|
+
* are. The port carries the reference, never the pixels, so a value stays
|
|
57
|
+
* small to snapshot, hash, trace and send to a Python stage.
|
|
58
|
+
*
|
|
59
|
+
* The path is always readable as a file by whoever needs a file. A host may
|
|
60
|
+
* still hold the pixels in memory and write the file behind (see
|
|
61
|
+
* {@link ImagePixels} and `AssetCapability.keepImage`): a reader in the same
|
|
62
|
+
* process gets the pixels without a decode, and the host makes the file whole
|
|
63
|
+
* before anything reads it from disk (a final copy, a Python stage, the end of
|
|
64
|
+
* a run).
|
|
65
|
+
*/
|
|
54
66
|
export interface ImageRef {
|
|
55
67
|
readonly path: string;
|
|
56
68
|
readonly size: Vec2i;
|
|
@@ -58,6 +70,18 @@ export interface ImageRef {
|
|
|
58
70
|
readonly depth: "u8" | "u16" | "f16" | "f32";
|
|
59
71
|
readonly space: "srgb" | "linear";
|
|
60
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* An image's pixels in memory: 8-bit RGBA, sRGB, unpremultiplied, row-major
|
|
75
|
+
* with the top row first. This is the layout of `ImageData` and of a PNG's
|
|
76
|
+
* decoded rows, so handing pixels on in memory and handing them on through a
|
|
77
|
+
* PNG give the next node the same numbers.
|
|
78
|
+
*/
|
|
79
|
+
export interface ImagePixels {
|
|
80
|
+
readonly width: number;
|
|
81
|
+
readonly height: number;
|
|
82
|
+
/** `width * height * 4` bytes. Owned by the host once kept: never mutate. */
|
|
83
|
+
readonly data: Uint8ClampedArray;
|
|
84
|
+
}
|
|
61
85
|
declare const textureHandleBrand: unique symbol;
|
|
62
86
|
export interface TextureHandle {
|
|
63
87
|
readonly [textureHandleBrand]: true;
|
package/dist/image.d.ts
CHANGED
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
* `cascade/io`'s bridge, because the node's copy of this module and the CLI's
|
|
44
44
|
* copy are not always the same module instance.
|
|
45
45
|
*/
|
|
46
|
+
import { type ImagePixels } from './io.js';
|
|
47
|
+
export type { ImagePixels } from './io.js';
|
|
46
48
|
/** An image port value. Mirrors Cascade's core `ImageRef`. */
|
|
47
49
|
export interface ImageRef {
|
|
48
50
|
path: string;
|
|
@@ -71,6 +73,19 @@ export interface ImageAssets {
|
|
|
71
73
|
path: string;
|
|
72
74
|
mediaType?: string;
|
|
73
75
|
}>;
|
|
76
|
+
/** Optional: store an intermediate from its pixels (see core `AssetCapability.keepImage`). */
|
|
77
|
+
keepImage?(pixels: ImagePixels, metadata: {
|
|
78
|
+
suggestedName?: string;
|
|
79
|
+
}, options: {
|
|
80
|
+
signal: unknown;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
path: string;
|
|
83
|
+
mediaType?: string;
|
|
84
|
+
}>;
|
|
85
|
+
/** Optional: the pixels behind a stored image while the host holds them in memory. */
|
|
86
|
+
imagePixels?(ref: {
|
|
87
|
+
path: string;
|
|
88
|
+
}): ImagePixels | undefined;
|
|
74
89
|
}
|
|
75
90
|
/**
|
|
76
91
|
* The slice of a definition-v1 `NodeExecutionContext` these helpers need, so
|
package/dist/image.js
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
// server/src/runtime/io.ts
|
|
2
|
+
function pixelsBitmap(pixels) {
|
|
3
|
+
const Canvas = globalThis.OffscreenCanvas;
|
|
4
|
+
if (!Canvas) throw new Error("cascade/io: this host has no OffscreenCanvas to hold the image");
|
|
5
|
+
const canvas = new Canvas(pixels.width, pixels.height);
|
|
6
|
+
const context = canvas.getContext("2d");
|
|
7
|
+
if (!context) throw new Error("cascade/io: the canvas has no 2D context");
|
|
8
|
+
const data = new ImageData(pixels.data, pixels.width, pixels.height);
|
|
9
|
+
context.putImageData(data, 0, 0);
|
|
10
|
+
const drawable = canvas;
|
|
11
|
+
drawable.close = () => {
|
|
12
|
+
};
|
|
13
|
+
drawable.naturalWidth = pixels.width;
|
|
14
|
+
drawable.naturalHeight = pixels.height;
|
|
15
|
+
return canvas;
|
|
16
|
+
}
|
|
17
|
+
function canvasPixels(source) {
|
|
18
|
+
const canvas = source;
|
|
19
|
+
if (typeof canvas?.getContext !== "function" || typeof canvas.width !== "number" || typeof canvas.height !== "number") return null;
|
|
20
|
+
if (!canvas.width || !canvas.height) return null;
|
|
21
|
+
const context = canvas.getContext("2d");
|
|
22
|
+
if (!context || typeof context.getImageData !== "function") return null;
|
|
23
|
+
const image = context.getImageData(0, 0, canvas.width, canvas.height);
|
|
24
|
+
return { width: image.width, height: image.height, data: image.data };
|
|
25
|
+
}
|
|
26
|
+
|
|
1
27
|
// server/src/runtime/image.ts
|
|
2
28
|
var HOST_KEY = "__cascadeImageHost";
|
|
3
29
|
var NO_CANVAS = 'cascade/image: this host has no canvas. In a browser this needs OffscreenCanvas; headless, Cascade installs @napi-rs/canvas before a run (install it with "npm install @napi-rs/canvas" if it is missing).';
|
|
@@ -97,12 +123,20 @@ async function readBytes(context, ref) {
|
|
|
97
123
|
return assetsOf(context).read(refOf(ref), { signal: context.signal ?? NEVER });
|
|
98
124
|
}
|
|
99
125
|
async function readImage(context, ref) {
|
|
126
|
+
const pixels = assetsOf(context).imagePixels?.(refOf(ref));
|
|
127
|
+
if (pixels) return pixelsBitmap(pixels);
|
|
100
128
|
return decodeImage(await readBytes(context, ref));
|
|
101
129
|
}
|
|
102
130
|
async function writeImage(context, canvas, name, options = {}) {
|
|
103
131
|
const type = options.type ?? "image/png";
|
|
104
|
-
const
|
|
105
|
-
const
|
|
132
|
+
const assets = assetsOf(context);
|
|
133
|
+
const signal = context.signal ?? NEVER;
|
|
134
|
+
const pixels = type === "image/png" && assets.keepImage ? canvasPixels(canvas) : null;
|
|
135
|
+
const stored = pixels && assets.keepImage ? await assets.keepImage(pixels, { suggestedName: name }, { signal }) : await assets.write(
|
|
136
|
+
await encodeImage(canvas, { type, ...options.quality === void 0 ? {} : { quality: options.quality } }),
|
|
137
|
+
{ mediaType: type, suggestedName: name },
|
|
138
|
+
{ signal }
|
|
139
|
+
);
|
|
106
140
|
return {
|
|
107
141
|
path: stored.path,
|
|
108
142
|
size: [canvas.width, canvas.height],
|
package/dist/index.html
CHANGED
|
@@ -6,11 +6,17 @@
|
|
|
6
6
|
<!-- Pinterest browser extension: no Save buttons over canvases and previews -->
|
|
7
7
|
<meta name="pinterest" content="nopin">
|
|
8
8
|
<title>Cascade</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-BWnrmIB9.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/legacy-CTEeXeqF.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/index-client-DqYmKstU.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/nodeTypeUtils-BDJsc2Ks.js">
|
|
13
|
-
<link rel="
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/coreTypes-DtnDATZ7.js">
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/expressions-X-Z-GrgW.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/DefinitionNode-CaRTXQ_b.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/assets/builder-BmBKcDix.js">
|
|
17
|
+
<link rel="modulepreload" crossorigin href="/assets/preload-helper-Czpn1I53.js">
|
|
18
|
+
<link rel="modulepreload" crossorigin href="/assets/studioImages-CAyH-0Pl.js">
|
|
19
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DIaxEONI.css">
|
|
14
20
|
</head>
|
|
15
21
|
<body>
|
|
16
22
|
<div id="app"></div>
|
package/dist/io.d.ts
CHANGED
|
@@ -33,6 +33,24 @@ export interface IoBridge {
|
|
|
33
33
|
write(path: string, data: Uint8Array): Promise<string>;
|
|
34
34
|
/** Host-owned display URL, valid until the host releases its stored asset. */
|
|
35
35
|
url?(path: string, options?: MediaOptions): string;
|
|
36
|
+
/**
|
|
37
|
+
* Store an intermediate image from its pixels and return the stored path,
|
|
38
|
+
* as `write` would. Optional. The headless host has it: it writes a fast
|
|
39
|
+
* lossless PNG, and in a run that keeps pixels it holds them in memory and
|
|
40
|
+
* writes behind (`pixels` below). Without it `saveImage` encodes and writes.
|
|
41
|
+
*/
|
|
42
|
+
keep?(path: string, pixels: ImagePixels): Promise<string>;
|
|
43
|
+
/** The pixels behind a path `keep` returned, while the host holds them. */
|
|
44
|
+
pixels?(path: string): ImagePixels | undefined;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* An image's pixels in memory. Mirrors Cascade's core `ImagePixels`: 8-bit
|
|
48
|
+
* RGBA, sRGB, unpremultiplied, top row first — `ImageData`'s layout.
|
|
49
|
+
*/
|
|
50
|
+
export interface ImagePixels {
|
|
51
|
+
readonly width: number;
|
|
52
|
+
readonly height: number;
|
|
53
|
+
readonly data: Uint8ClampedArray;
|
|
36
54
|
}
|
|
37
55
|
/** Install the local transport. Returns a disposer, so a test can take it down. */
|
|
38
56
|
export declare function installIoBridge(bridge: IoBridge | null): () => void;
|
|
@@ -47,6 +65,11 @@ export declare function loadBytes(path: string, options?: MediaOptions): Promise
|
|
|
47
65
|
* to hand it. Pass a width explicitly to work at a smaller size on purpose.
|
|
48
66
|
*/
|
|
49
67
|
export declare function loadImage(path: string, options?: MediaOptions): Promise<HTMLImageElement>;
|
|
68
|
+
/**
|
|
69
|
+
* `ImagePixels` as a drawable: a canvas holding them, with an `ImageBitmap`'s
|
|
70
|
+
* `width`, `height` and `close()` (and an image's `naturalWidth`/`naturalHeight`).
|
|
71
|
+
*/
|
|
72
|
+
export declare function pixelsBitmap(pixels: ImagePixels): ImageBitmap;
|
|
50
73
|
/** Same, as an ImageBitmap — the right input for `texImage2D`. */
|
|
51
74
|
export declare function loadBitmap(path: string, options?: MediaOptions): Promise<ImageBitmap>;
|
|
52
75
|
/**
|
|
@@ -83,6 +106,12 @@ export interface ImageSource {
|
|
|
83
106
|
* node.out('path').setValue(out);
|
|
84
107
|
*/
|
|
85
108
|
export declare function saveImage(source: HTMLCanvasElement | OffscreenCanvas | Blob | ImageSource, path: string, options?: SaveOptions): Promise<string>;
|
|
109
|
+
/**
|
|
110
|
+
* A canvas's pixels as `ImagePixels`, or null for anything that is not a 2D
|
|
111
|
+
* canvas (a Blob, an encoder-only source, a WebGL canvas, whose `getContext('2d')`
|
|
112
|
+
* is null).
|
|
113
|
+
*/
|
|
114
|
+
export declare function canvasPixels(source: unknown): ImagePixels | null;
|
|
86
115
|
/** Write any bytes into the project cache and return the path. */
|
|
87
116
|
export declare function saveBytes(data: Blob | ArrayBuffer | Uint8Array, path: string): Promise<string>;
|
|
88
117
|
/**
|
package/dist/io.js
CHANGED
|
@@ -40,6 +40,8 @@ async function loadBytes(path, options = { raw: true }) {
|
|
|
40
40
|
return await response.arrayBuffer();
|
|
41
41
|
}
|
|
42
42
|
async function loadImage(path, options = { raw: true }) {
|
|
43
|
+
const held = heldBitmap(path);
|
|
44
|
+
if (held) return held;
|
|
43
45
|
const image = new Image();
|
|
44
46
|
const bridge = localIo();
|
|
45
47
|
let temporaryUrl;
|
|
@@ -65,7 +67,29 @@ async function loadImage(path, options = { raw: true }) {
|
|
|
65
67
|
if (temporaryUrl) URL.revokeObjectURL(temporaryUrl);
|
|
66
68
|
}
|
|
67
69
|
}
|
|
70
|
+
function heldBitmap(path) {
|
|
71
|
+
if (/^(https?:|data:|blob:)/.test(path)) return null;
|
|
72
|
+
const pixels = localIo()?.pixels?.(path.replace(/^\.?\//, ""));
|
|
73
|
+
return pixels ? pixelsBitmap(pixels) : null;
|
|
74
|
+
}
|
|
75
|
+
function pixelsBitmap(pixels) {
|
|
76
|
+
const Canvas = globalThis.OffscreenCanvas;
|
|
77
|
+
if (!Canvas) throw new Error("cascade/io: this host has no OffscreenCanvas to hold the image");
|
|
78
|
+
const canvas = new Canvas(pixels.width, pixels.height);
|
|
79
|
+
const context = canvas.getContext("2d");
|
|
80
|
+
if (!context) throw new Error("cascade/io: the canvas has no 2D context");
|
|
81
|
+
const data = new ImageData(pixels.data, pixels.width, pixels.height);
|
|
82
|
+
context.putImageData(data, 0, 0);
|
|
83
|
+
const drawable = canvas;
|
|
84
|
+
drawable.close = () => {
|
|
85
|
+
};
|
|
86
|
+
drawable.naturalWidth = pixels.width;
|
|
87
|
+
drawable.naturalHeight = pixels.height;
|
|
88
|
+
return canvas;
|
|
89
|
+
}
|
|
68
90
|
async function loadBitmap(path, options = { raw: true }) {
|
|
91
|
+
const held = heldBitmap(path);
|
|
92
|
+
if (held) return held;
|
|
69
93
|
const bridge = localIo();
|
|
70
94
|
if (bridge?.url) return createImageBitmap(await loadImage(path, options));
|
|
71
95
|
if (bridge) return createImageBitmap(new Blob([await loadBytes(path, options)]));
|
|
@@ -80,6 +104,11 @@ async function saveImage(source, path, options = {}) {
|
|
|
80
104
|
const format = options.format ?? "png";
|
|
81
105
|
const type = `image/${format}`;
|
|
82
106
|
let blob;
|
|
107
|
+
const bridge = localIo();
|
|
108
|
+
if (format === "png" && bridge?.keep) {
|
|
109
|
+
const pixels = canvasPixels(source);
|
|
110
|
+
if (pixels) return bridge.keep(path.replace(/^\.?\//, ""), pixels);
|
|
111
|
+
}
|
|
83
112
|
if (source instanceof Blob) {
|
|
84
113
|
blob = source;
|
|
85
114
|
} else if (typeof source.convertToBlob === "function") {
|
|
@@ -99,6 +128,15 @@ async function saveImage(source, path, options = {}) {
|
|
|
99
128
|
}
|
|
100
129
|
return saveBytes(blob, path);
|
|
101
130
|
}
|
|
131
|
+
function canvasPixels(source) {
|
|
132
|
+
const canvas = source;
|
|
133
|
+
if (typeof canvas?.getContext !== "function" || typeof canvas.width !== "number" || typeof canvas.height !== "number") return null;
|
|
134
|
+
if (!canvas.width || !canvas.height) return null;
|
|
135
|
+
const context = canvas.getContext("2d");
|
|
136
|
+
if (!context || typeof context.getImageData !== "function") return null;
|
|
137
|
+
const image = context.getImageData(0, 0, canvas.width, canvas.height);
|
|
138
|
+
return { width: image.width, height: image.height, data: image.data };
|
|
139
|
+
}
|
|
102
140
|
async function saveBytes(data, path) {
|
|
103
141
|
const clean = path.replace(/^\.?\//, "");
|
|
104
142
|
const bridge = localIo();
|
|
@@ -302,6 +340,7 @@ async function textureToImage(ref, path, options = {}) {
|
|
|
302
340
|
}
|
|
303
341
|
export {
|
|
304
342
|
cachePath,
|
|
343
|
+
canvasPixels,
|
|
305
344
|
createTexture,
|
|
306
345
|
installIoBridge,
|
|
307
346
|
loadBitmap,
|
|
@@ -310,6 +349,7 @@ export {
|
|
|
310
349
|
loadFloats,
|
|
311
350
|
loadImage,
|
|
312
351
|
mediaUrl,
|
|
352
|
+
pixelsBitmap,
|
|
313
353
|
saveBytes,
|
|
314
354
|
saveFloats,
|
|
315
355
|
saveImage,
|
package/dist/player/app.js
CHANGED
|
@@ -12,7 +12,8 @@ import { installIoBridge } from "@field/cascade/io";
|
|
|
12
12
|
|
|
13
13
|
// src/browser/gpu.ts
|
|
14
14
|
import {
|
|
15
|
-
createGpuHost
|
|
15
|
+
createGpuHost,
|
|
16
|
+
requestDeviceWithAdapterLimits
|
|
16
17
|
} from "@field/cascade/runtime";
|
|
17
18
|
function createBrowserGpuHost() {
|
|
18
19
|
const gpu = globalThis.navigator?.gpu;
|
|
@@ -25,7 +26,7 @@ function createBrowserGpuHost() {
|
|
|
25
26
|
"No WebGPU adapter is available \u2014 the browser reports WebGPU but the system offers no GPU to render on."
|
|
26
27
|
);
|
|
27
28
|
}
|
|
28
|
-
const device = await adapter
|
|
29
|
+
const device = await requestDeviceWithAdapterLimits(adapter);
|
|
29
30
|
const info = adapter.info;
|
|
30
31
|
return {
|
|
31
32
|
device,
|
|
@@ -307,7 +308,7 @@ async function startPlayer(options) {
|
|
|
307
308
|
if (!root) throw new Error("Cascade player needs a document body or explicit root");
|
|
308
309
|
const view = hostDocument.defaultView;
|
|
309
310
|
const initial = readInitialState(view?.location.href);
|
|
310
|
-
const ui = createUi(hostDocument, root);
|
|
311
|
+
const ui = createUi(hostDocument, root, options.chrome ?? initial.chrome);
|
|
311
312
|
let assets;
|
|
312
313
|
let disposeIo;
|
|
313
314
|
let gpu;
|
|
@@ -544,7 +545,7 @@ var BrowserPlayer = class {
|
|
|
544
545
|
this.assertActive();
|
|
545
546
|
let result;
|
|
546
547
|
try {
|
|
547
|
-
result = await this.context.graph.run({ frame, fps: this.context.graph.getFps() });
|
|
548
|
+
result = await this.context.graph.run({ frame, fps: this.context.graph.getFps(), reuse: "strict" });
|
|
548
549
|
this.settledRoots = outputValues(result);
|
|
549
550
|
if (result.status !== "completed") throw resultError(result);
|
|
550
551
|
if (!this.selected) this.selected = preferredOutput(result);
|
|
@@ -665,10 +666,11 @@ var BrowserPlayer = class {
|
|
|
665
666
|
if (this.disposed) throw new Error("Cascade player is disposed");
|
|
666
667
|
}
|
|
667
668
|
};
|
|
668
|
-
function createUi(hostDocument, root) {
|
|
669
|
+
function createUi(hostDocument, root, chrome) {
|
|
669
670
|
root.replaceChildren();
|
|
670
671
|
root.dataset.cascadePlayer = "";
|
|
671
|
-
Object.assign(root.style, { display: "flex", flexDirection: "column", height: "100%", margin: "0",
|
|
672
|
+
Object.assign(root.style, { display: "flex", flexDirection: "column", height: "100%", margin: "0", overflow: "hidden" });
|
|
673
|
+
if (chrome) Object.assign(root.style, { background: "#141414", color: "#eee" });
|
|
672
674
|
const toolbar = hostDocument.createElement("div");
|
|
673
675
|
toolbar.dataset.cascadeControls = "";
|
|
674
676
|
Object.assign(toolbar.style, { display: "flex", gap: "8px", padding: "8px", flex: "none", alignItems: "center" });
|
|
@@ -689,7 +691,8 @@ function createUi(hostDocument, root) {
|
|
|
689
691
|
output.dataset.cascadeOutput = "";
|
|
690
692
|
Object.assign(output.style, { display: "grid", placeItems: "center", flex: "1", minHeight: "0", minWidth: "0", overflow: "auto" });
|
|
691
693
|
toolbar.append(play, frame);
|
|
692
|
-
root.append(toolbar
|
|
694
|
+
if (chrome) root.append(toolbar);
|
|
695
|
+
root.append(error, output);
|
|
693
696
|
return { play, frame, error, output };
|
|
694
697
|
}
|
|
695
698
|
function renderSceneCanvas(hostDocument, scene, width, height, stroke = [1, 1, 1, 1]) {
|
|
@@ -739,6 +742,7 @@ function readInitialState(href) {
|
|
|
739
742
|
frame,
|
|
740
743
|
fps,
|
|
741
744
|
autoplay: query.get("autoplay") === "1",
|
|
745
|
+
chrome: query.get("chrome") !== "0",
|
|
742
746
|
...nodeId && port ? { output: { nodeId, port } } : {}
|
|
743
747
|
};
|
|
744
748
|
}
|
package/dist/player/editor.js
CHANGED
|
@@ -28,7 +28,8 @@ import { installIoBridge } from "@field/cascade/io";
|
|
|
28
28
|
|
|
29
29
|
// src/browser/gpu.ts
|
|
30
30
|
import {
|
|
31
|
-
createGpuHost
|
|
31
|
+
createGpuHost,
|
|
32
|
+
requestDeviceWithAdapterLimits
|
|
32
33
|
} from "@field/cascade/runtime";
|
|
33
34
|
function createBrowserGpuHost() {
|
|
34
35
|
const gpu = globalThis.navigator?.gpu;
|
|
@@ -41,7 +42,7 @@ function createBrowserGpuHost() {
|
|
|
41
42
|
"No WebGPU adapter is available \u2014 the browser reports WebGPU but the system offers no GPU to render on."
|
|
42
43
|
);
|
|
43
44
|
}
|
|
44
|
-
const device = await adapter
|
|
45
|
+
const device = await requestDeviceWithAdapterLimits(adapter);
|
|
45
46
|
const info = adapter.info;
|
|
46
47
|
return {
|
|
47
48
|
device,
|
|
@@ -5,7 +5,8 @@ import { installIoBridge as installIoBridge2 } from "@field/cascade/io";
|
|
|
5
5
|
|
|
6
6
|
// src/browser/gpu.ts
|
|
7
7
|
import {
|
|
8
|
-
createGpuHost
|
|
8
|
+
createGpuHost,
|
|
9
|
+
requestDeviceWithAdapterLimits
|
|
9
10
|
} from "@field/cascade/runtime";
|
|
10
11
|
function createBrowserGpuHost() {
|
|
11
12
|
const gpu = globalThis.navigator?.gpu;
|
|
@@ -18,7 +19,7 @@ function createBrowserGpuHost() {
|
|
|
18
19
|
"No WebGPU adapter is available \u2014 the browser reports WebGPU but the system offers no GPU to render on."
|
|
19
20
|
);
|
|
20
21
|
}
|
|
21
|
-
const device = await adapter
|
|
22
|
+
const device = await requestDeviceWithAdapterLimits(adapter);
|
|
22
23
|
const info = adapter.info;
|
|
23
24
|
return {
|
|
24
25
|
device,
|
package/dist/player/embed.js
CHANGED
|
@@ -12,6 +12,8 @@ async function mountPlayer(container, options) {
|
|
|
12
12
|
setQueryOption(url, "frame", options.frame ?? 1);
|
|
13
13
|
setQueryOption(url, "fps", options.fps ?? 30);
|
|
14
14
|
url.searchParams.set("autoplay", options.autoplay ? "1" : "0");
|
|
15
|
+
if (options.chrome === false) url.searchParams.set("chrome", "0");
|
|
16
|
+
else url.searchParams.delete("chrome");
|
|
15
17
|
if (options.output) {
|
|
16
18
|
url.searchParams.set("outputNode", options.output.nodeId);
|
|
17
19
|
url.searchParams.set("outputPort", options.output.port);
|
package/dist/player/types.d.ts
CHANGED
|
@@ -32,4 +32,10 @@ export interface MountPlayerOptions {
|
|
|
32
32
|
readonly fps?: number;
|
|
33
33
|
readonly autoplay?: boolean;
|
|
34
34
|
readonly output?: PlayerOutputSelection;
|
|
35
|
+
/**
|
|
36
|
+
* `false` shows the output alone on a transparent page: no dark frame, Play
|
|
37
|
+
* button or frame field. Errors still appear. Default `true`; the URL form
|
|
38
|
+
* is `?chrome=0`.
|
|
39
|
+
*/
|
|
40
|
+
readonly chrome?: boolean;
|
|
35
41
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { NodeExecutionContext } from "@field/cascade/contracts";
|
|
2
|
+
import type { equalsDefinition, notBlankDefinition, rangeDefinition, trueDefinition } from "./definitions.js";
|
|
3
|
+
export declare function executeRange({ nodeId, inputs, props, outputs }: NodeExecutionContext<typeof rangeDefinition>): void;
|
|
4
|
+
export declare function executeEquals({ nodeId, inputs, props, outputs }: NodeExecutionContext<typeof equalsDefinition>): void;
|
|
5
|
+
export declare function executeTrue({ nodeId, inputs, props, outputs }: NodeExecutionContext<typeof trueDefinition>): void;
|
|
6
|
+
export declare function executeNotBlank({ nodeId, inputs, props, outputs, capabilities, signal }: NodeExecutionContext<typeof notBlankDefinition>): Promise<void>;
|
|
7
|
+
export interface Pixels {
|
|
8
|
+
readonly width: number;
|
|
9
|
+
readonly height: number;
|
|
10
|
+
/** Channels per pixel: 1 grey, 2 grey+alpha, 3 RGB, 4 RGBA. */
|
|
11
|
+
readonly channels: number;
|
|
12
|
+
readonly data: ArrayLike<number>;
|
|
13
|
+
}
|
|
14
|
+
/** 'one flat colour', 'fully transparent', or null when the image has content. */
|
|
15
|
+
export declare function blankness(pixels: Pixels, tolerance?: number): string | null;
|
|
16
|
+
/** 8-bit non-interlaced PNG (grey, grey+alpha, RGB, RGBA) or binary PPM/PGM. */
|
|
17
|
+
export declare function decodeImage(bytes: Uint8Array): Promise<Pixels | null>;
|
|
18
|
+
//# sourceMappingURL=checks.d.ts.map
|