@field/cascade 0.10.0 → 0.11.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 +20 -3
- package/CHANGELOG.md +187 -0
- package/README.md +1 -2
- package/dist/assets/{CodeEditor-DSZBpzdy.js → CodeEditor-4O7FQ__R.js} +4 -4
- package/dist/assets/{CodePanel-sY6sZa7B.js → CodePanel-BU-autmq.js} +2 -2
- package/dist/assets/{CustomNodeDialog-BRKnqZhp.js → CustomNodeDialog-BRpDfOV5.js} +1 -1
- package/dist/assets/{OpenGraphDialog-ZsgL-iwr.js → OpenGraphDialog-BwbRlC0X.js} +1 -1
- package/dist/assets/{ProjectSettings-Cw17nNe3.js → ProjectSettings-DLOXLxcA.js} +1 -1
- package/dist/assets/{SettingsDialog-p25h3tj0.js → SettingsDialog-Bz8JxISH.js} +1 -1
- package/dist/assets/{VersionHistoryDialog-DzFLUotB.js → VersionHistoryDialog-D5Z0nJ5-.js} +1 -1
- package/dist/assets/{core-BICrEt0y.js → core-Yqi0Ni61.js} +1 -1
- package/dist/assets/{cssMode-D7TXw57I.js → cssMode-CxUzc4vp.js} +1 -1
- package/dist/assets/{definitions-DUww2Rt-.js → definitions-GreEMXLV.js} +1 -1
- package/dist/assets/{editor.api-DvkCO3ko.js → editor.api-BNFb25CX.js} +1 -1
- package/dist/assets/{freemarker2-BA2lxsF1.js → freemarker2-0ZDnWxeM.js} +1 -1
- package/dist/assets/geo-u0n_jOsD.js +1 -0
- package/dist/assets/{handlebars-BcDiyPd8.js → handlebars-Cy18MoaD.js} +1 -1
- package/dist/assets/{html-C7O4TyhX.js → html-B-2Dx7nq.js} +1 -1
- package/dist/assets/{htmlMode-WaDGF3Mj.js → htmlMode-DUAc9B_d.js} +1 -1
- package/dist/assets/{image-DR4oeyJB.js → image-cAa-Nu9O.js} +1 -1
- package/dist/assets/{index-DyvDC6pS.js → index-5ZtDAuy2.js} +42 -41
- package/dist/assets/{javascript-CpIEK7tz.js → javascript-DeQsDqP5.js} +1 -1
- package/dist/assets/{jsonMode-B2FltW0f.js → jsonMode-BiFwJVSk.js} +1 -1
- package/dist/assets/{liquid-CN6FFHZE.js → liquid-BLoHH68a.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-QhV9XtLp.js → lspLanguageFeatures-CNFgm1Kv.js} +1 -1
- package/dist/assets/math-DioIQOPJ.js +1 -0
- package/dist/assets/{mdx-DE89pafV.js → mdx-CFXQVNfs.js} +1 -1
- package/dist/assets/pop-DC_TQG9t.js +1 -0
- package/dist/assets/{python-ByTllTB9.js → python-Cf7S7p2E.js} +1 -1
- package/dist/assets/{razor-USYlRRCE.js → razor-CMHBcG-g.js} +1 -1
- package/dist/assets/{tsMode-BXpN8iUz.js → tsMode-BEih0GDj.js} +1 -1
- package/dist/assets/{typescript-DInBjGQQ.js → typescript-COEKYD_a.js} +1 -1
- package/dist/assets/{workers-C7Ye5B7D.js → workers-BNhAhMNn.js} +1 -1
- package/dist/assets/{xml-U0Uocqyo.js → xml-CPiMpnPl.js} +1 -1
- package/dist/assets/{yaml-CBw_PVYf.js → yaml-Bgp1ITLR.js} +1 -1
- package/dist/cli/Graph-ZJJTRQTM.js +2975 -0
- package/dist/cli/chunk-2KXB47FP.js +115 -0
- package/dist/cli/chunk-35D343DC.js +1447 -0
- package/dist/cli/chunk-36P5K3SD.js +631 -0
- package/dist/cli/chunk-3JTJHF7V.js +267 -0
- package/dist/cli/chunk-4UDFYF5G.js +132 -0
- package/dist/cli/chunk-53NMBJAO.js +35 -0
- package/dist/cli/chunk-A4OAMOZH.js +310 -0
- package/dist/cli/chunk-BIJO5OFS.js +71 -0
- package/dist/cli/chunk-BP7UKF36.js +376 -0
- package/dist/cli/chunk-CKS2FQWR.js +89 -0
- package/dist/cli/chunk-CO22XHNG.js +593 -0
- package/dist/cli/chunk-D6BUOHUG.js +634 -0
- package/dist/cli/chunk-DEQSEFFH.js +153 -0
- package/dist/cli/chunk-DUIUFVU2.js +241 -0
- package/dist/cli/chunk-EUIAC3U3.js +3006 -0
- package/dist/cli/chunk-FCDXJ6EK.js +2208 -0
- package/dist/cli/chunk-GFS6W3C5.js +308 -0
- package/dist/cli/chunk-HFHWYL55.js +139 -0
- package/dist/cli/chunk-HSNOBIVT.js +263 -0
- package/dist/cli/chunk-ICH7N5PN.js +26 -0
- package/dist/cli/chunk-J7VK7MNF.js +418 -0
- package/dist/cli/chunk-KH4MUBKF.js +1551 -0
- package/dist/cli/chunk-MIIEFUGG.js +623 -0
- package/dist/cli/chunk-OWWBYLHC.js +136 -0
- package/dist/cli/chunk-POMMNKZZ.js +672 -0
- package/dist/cli/chunk-QBBKRNGY.js +90 -0
- package/dist/cli/chunk-QQPA2ZHH.js +273 -0
- package/dist/cli/chunk-RLCAJBVR.js +224 -0
- package/dist/cli/chunk-RQZ4SX5R.js +1125 -0
- package/dist/cli/chunk-RUU3YWXU.js +99 -0
- package/dist/cli/chunk-RXDIMXN5.js +98 -0
- package/dist/cli/chunk-SGJAET2L.js +197 -0
- package/dist/cli/chunk-VVGSLVSF.js +151 -0
- package/dist/cli/chunk-WD62JIP6.js +118 -0
- package/dist/cli/chunk-WIH4TEIS.js +104 -0
- package/dist/cli/chunk-WKURDVYP.js +1119 -0
- package/dist/cli/chunk-WPUDGEFY.js +20 -0
- package/dist/cli/chunk-XWDSKG7N.js +1301 -0
- package/dist/cli/chunk-YAT5Y25U.js +121 -0
- package/dist/cli/chunk-ZL4JTG5Y.js +37 -0
- package/dist/cli/cliCommands-UQSFGEHF.js +3464 -0
- package/dist/cli/commands-Q23M26QM.js +1292 -0
- package/dist/cli/definitions-HF2FTHYU.js +32 -0
- package/dist/cli/doctorCommand-B7BPQMN6.js +76 -0
- package/dist/cli/edit-JHCPTQFT.js +28 -0
- package/dist/cli/editorCommands-UIF5YLUZ.js +33 -0
- package/dist/cli/encode-HAUZTYPT.js +17 -0
- package/dist/cli/frames-LSAUBZ7P.js +16 -0
- package/dist/cli/geo-4RNK3QVN.js +43 -0
- package/dist/cli/graphCommands-6BMAKGQE.js +184 -0
- package/dist/cli/graphFile-VPSQ6OF7.js +286 -0
- package/dist/cli/headlessCanvas-5XLDZT7M.js +15 -0
- package/dist/cli/helpCommand-3VRE3KVO.js +155 -0
- package/dist/cli/index.js +100 -30756
- package/dist/cli/math-ZRMLKU2D.js +16 -0
- package/dist/cli/mcp-ZLEEMYGF.js +164 -0
- package/dist/cli/parity-KINARCP2.js +328 -0
- package/dist/cli/pop-USDFXB7H.js +39 -0
- package/dist/cli/project-K3QIPGBB.js +12 -0
- package/dist/cli/projectDefinition-DMTZN2NE.js +27 -0
- package/dist/cli/projectRuntime-Z5PJOH47.js +48 -0
- package/dist/cli/registerStandardNodes-S2VLMF6J.js +3081 -0
- package/dist/cli/render-YURAPPUI.js +436 -0
- package/dist/cli/runCommand-PI764LEG.js +198 -0
- package/dist/cli/runner-RA6UKEPD.js +37 -0
- package/dist/cli/runtime/image.ts +277 -0
- package/dist/cli/runtime/stage.ts +4 -1
- package/dist/cli/stageRunner-KUNIMQKJ.js +10 -0
- package/dist/cli/verbs-RCE3K4VQ.js +19 -0
- package/dist/cli/webBuild-GT4PZT5D.js +37 -0
- package/dist/contracts/documentFormat.d.ts +18 -0
- package/dist/contracts/documentFormat.js +195 -0
- package/dist/contracts/editor.d.ts +17 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +1 -0
- package/dist/image.d.ts +141 -0
- package/dist/image.js +127 -0
- package/dist/index.html +1 -1
- package/dist/player/editor.js +32 -7
- package/dist/runtime/builtins/headless.d.ts +19 -0
- package/dist/runtime/builtins/headless.js +25 -0
- package/dist/runtime/builtins/image/contactSheet.d.ts +226 -0
- package/dist/runtime/builtins/image/contactSheet.js +199 -0
- package/dist/runtime/builtins/image/index.d.ts +9 -0
- package/dist/runtime/builtins/image/index.js +9 -0
- package/dist/stage.js +4 -1
- package/doc/CLI_REFERENCE.md +73 -2
- package/doc/EDITOR_EXPORT.md +11 -2
- package/doc/MCP.md +17 -1
- package/doc/NODE_REFERENCE.md +142 -0
- package/doc/PROJECT_AUTHORING.md +127 -7
- package/package.json +16 -4
- package/dist/assets/ExportDialog-C7dVGua4.js +0 -358
- package/dist/assets/ExportDialog-DOq0flMV.css +0 -1
- package/dist/assets/geo-C2RHOVHC.js +0 -1
- package/dist/assets/math-DaDEgWKt.js +0 -1
- package/dist/assets/pop-pLH7L0PW.js +0 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// packages/contracts/src/bundle.ts
|
|
2
|
+
function bundleFieldType(definition) {
|
|
3
|
+
if (!definition) return "any";
|
|
4
|
+
return typeof definition === "string" ? definition : definition.type;
|
|
5
|
+
}
|
|
6
|
+
function bundleSchemasCompatible(output, input) {
|
|
7
|
+
return !output || !input || output === input;
|
|
8
|
+
}
|
|
9
|
+
function isBundleValue(value) {
|
|
10
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
11
|
+
const prototype = Object.getPrototypeOf(value);
|
|
12
|
+
return prototype === Object.prototype || prototype === null;
|
|
13
|
+
}
|
|
14
|
+
function selectBundleFields(value, fields) {
|
|
15
|
+
if (!isBundleValue(value)) return value;
|
|
16
|
+
const selected = {};
|
|
17
|
+
for (const field of fields)
|
|
18
|
+
if (Object.prototype.hasOwnProperty.call(value, field)) selected[field] = value[field];
|
|
19
|
+
return Object.freeze(selected);
|
|
20
|
+
}
|
|
21
|
+
function suggestName(name, candidates) {
|
|
22
|
+
let best;
|
|
23
|
+
let bestDistance = Infinity;
|
|
24
|
+
const lower = name.toLowerCase();
|
|
25
|
+
for (const candidate of candidates) {
|
|
26
|
+
const distance = editDistance(lower, candidate.toLowerCase());
|
|
27
|
+
if (distance < bestDistance) {
|
|
28
|
+
best = candidate;
|
|
29
|
+
bestDistance = distance;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (best === void 0) return void 0;
|
|
33
|
+
const limit = Math.max(1, Math.floor(Math.max(name.length, best.length) / 3));
|
|
34
|
+
return bestDistance <= limit ? best : void 0;
|
|
35
|
+
}
|
|
36
|
+
function unknownFieldMessage(field, known, where) {
|
|
37
|
+
const suggestion = suggestName(field, known);
|
|
38
|
+
return `${where} reads unknown bundle field "${field}"` + (suggestion ? ` \u2014 did you mean "${suggestion}"?` : "") + (known.length ? ` (fields: ${known.join(", ")})` : " (the bundle declares no fields)");
|
|
39
|
+
}
|
|
40
|
+
function bundleValueProblem(value, fields) {
|
|
41
|
+
if (value === void 0 || value === null) return null;
|
|
42
|
+
if (!isBundleValue(value)) return "a bundle must be a plain object of fields";
|
|
43
|
+
if (!fields) return null;
|
|
44
|
+
const known = Object.keys(fields);
|
|
45
|
+
for (const key of Object.keys(value))
|
|
46
|
+
if (!Object.prototype.hasOwnProperty.call(fields, key)) {
|
|
47
|
+
const suggestion = suggestName(key, known);
|
|
48
|
+
return `sets undeclared bundle field "${key}"` + (suggestion ? ` \u2014 did you mean "${suggestion}"?` : "") + ` (declared: ${known.join(", ") || "none"})`;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function editDistance(a, b) {
|
|
53
|
+
const previous = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
54
|
+
for (let i = 1; i <= a.length; i++) {
|
|
55
|
+
let diagonal = previous[0];
|
|
56
|
+
previous[0] = i;
|
|
57
|
+
for (let j = 1; j <= b.length; j++) {
|
|
58
|
+
const above = previous[j];
|
|
59
|
+
previous[j] = Math.min(
|
|
60
|
+
previous[j] + 1,
|
|
61
|
+
previous[j - 1] + 1,
|
|
62
|
+
diagonal + (a[i - 1] === b[j - 1] ? 0 : 1)
|
|
63
|
+
);
|
|
64
|
+
diagonal = above;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return previous[b.length];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// packages/runtime/src/seed.ts
|
|
71
|
+
var DEFAULT_GRAPH_SEED = 0;
|
|
72
|
+
function graphSeed(document) {
|
|
73
|
+
const value = document?.seed;
|
|
74
|
+
return typeof value === "number" && Number.isInteger(value) ? value >>> 0 : DEFAULT_GRAPH_SEED;
|
|
75
|
+
}
|
|
76
|
+
function nodeSeed(seedOfGraph, nodeId) {
|
|
77
|
+
const text = `${seedOfGraph >>> 0}:${nodeId}`;
|
|
78
|
+
let hash = 2166136261;
|
|
79
|
+
for (let index = 0; index < text.length; index++) {
|
|
80
|
+
hash ^= text.charCodeAt(index);
|
|
81
|
+
hash = Math.imul(hash, 16777619);
|
|
82
|
+
}
|
|
83
|
+
hash ^= hash >>> 16;
|
|
84
|
+
hash = Math.imul(hash, 2246822507);
|
|
85
|
+
hash ^= hash >>> 13;
|
|
86
|
+
hash = Math.imul(hash, 3266489909);
|
|
87
|
+
hash ^= hash >>> 16;
|
|
88
|
+
return hash >>> 0;
|
|
89
|
+
}
|
|
90
|
+
function seededRandom(seed) {
|
|
91
|
+
let state = seed >>> 0;
|
|
92
|
+
return () => {
|
|
93
|
+
state = state + 1831565813 >>> 0;
|
|
94
|
+
let value = state;
|
|
95
|
+
value = Math.imul(value ^ value >>> 15, value | 1);
|
|
96
|
+
value ^= value + Math.imul(value ^ value >>> 7, value | 61);
|
|
97
|
+
return ((value ^ value >>> 14) >>> 0) / 4294967296;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// packages/runtime/src/gpu.ts
|
|
102
|
+
var HOST_SCOPE = "\0host";
|
|
103
|
+
var MISSING_DEVICE = "The gpu capability was used before its device was ready \u2014 the host must await ensure() before a cook.";
|
|
104
|
+
var DISPOSED = "The gpu capability has been disposed.";
|
|
105
|
+
function isGpuHost(value) {
|
|
106
|
+
return !!value && typeof value.ensure === "function" && typeof value.forNode === "function" && typeof value.dispose === "function";
|
|
107
|
+
}
|
|
108
|
+
function createGpuHost(options) {
|
|
109
|
+
let active = null;
|
|
110
|
+
let starting = null;
|
|
111
|
+
let disposal = null;
|
|
112
|
+
let disposed = false;
|
|
113
|
+
const caches = /* @__PURE__ */ new Map();
|
|
114
|
+
const retiring = /* @__PURE__ */ new Set();
|
|
115
|
+
const retirementErrors = [];
|
|
116
|
+
function dropCaches() {
|
|
117
|
+
const errors = [];
|
|
118
|
+
const scopes = [...caches.values()];
|
|
119
|
+
caches.clear();
|
|
120
|
+
for (const entries of scopes) {
|
|
121
|
+
for (const entry of entries.values()) {
|
|
122
|
+
try {
|
|
123
|
+
entry.destroy?.(entry.value);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
errors.push(error);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return errors;
|
|
130
|
+
}
|
|
131
|
+
async function release(acquired, destroyDevice) {
|
|
132
|
+
if (acquired.released) return [];
|
|
133
|
+
acquired.released = true;
|
|
134
|
+
const errors = [];
|
|
135
|
+
if (destroyDevice) {
|
|
136
|
+
try {
|
|
137
|
+
acquired.device.destroy();
|
|
138
|
+
} catch (error) {
|
|
139
|
+
errors.push(error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
await acquired.release?.();
|
|
144
|
+
} catch (error) {
|
|
145
|
+
errors.push(error);
|
|
146
|
+
}
|
|
147
|
+
return errors;
|
|
148
|
+
}
|
|
149
|
+
function throwCleanupErrors(errors) {
|
|
150
|
+
if (errors.length === 1) throw errors[0];
|
|
151
|
+
if (errors.length > 1) {
|
|
152
|
+
const combined = new Error("GPU host cleanup failed");
|
|
153
|
+
Object.assign(combined, { errors });
|
|
154
|
+
throw combined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function watchLoss(acquired) {
|
|
158
|
+
void acquired.device.lost.then(() => {
|
|
159
|
+
if (disposed || active !== acquired) return;
|
|
160
|
+
active = null;
|
|
161
|
+
retirementErrors.push(...dropCaches());
|
|
162
|
+
const cleanup = release(acquired, false).then((errors) => {
|
|
163
|
+
retirementErrors.push(...errors);
|
|
164
|
+
});
|
|
165
|
+
retiring.add(cleanup);
|
|
166
|
+
void cleanup.finally(() => retiring.delete(cleanup));
|
|
167
|
+
}).catch(() => {
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function start() {
|
|
171
|
+
const result = await options.acquire();
|
|
172
|
+
const acquired = {
|
|
173
|
+
device: result.device,
|
|
174
|
+
info: {
|
|
175
|
+
vendor: result.info?.vendor ?? "",
|
|
176
|
+
architecture: result.info?.architecture ?? "",
|
|
177
|
+
device: result.info?.device ?? "",
|
|
178
|
+
description: result.info?.description ?? ""
|
|
179
|
+
},
|
|
180
|
+
limits: readGpuLimits(result.limits),
|
|
181
|
+
release: result.release,
|
|
182
|
+
released: false
|
|
183
|
+
};
|
|
184
|
+
if (disposed) {
|
|
185
|
+
const errors = await release(acquired, true);
|
|
186
|
+
throwCleanupErrors(errors);
|
|
187
|
+
throw new Error(DISPOSED);
|
|
188
|
+
}
|
|
189
|
+
active = acquired;
|
|
190
|
+
watchLoss(acquired);
|
|
191
|
+
}
|
|
192
|
+
const host = {
|
|
193
|
+
get device() {
|
|
194
|
+
if (!active) throw new Error(MISSING_DEVICE);
|
|
195
|
+
return active.device;
|
|
196
|
+
},
|
|
197
|
+
get adapterInfo() {
|
|
198
|
+
if (!active) throw new Error(MISSING_DEVICE);
|
|
199
|
+
return active.info;
|
|
200
|
+
},
|
|
201
|
+
get limits() {
|
|
202
|
+
return active?.limits ?? {};
|
|
203
|
+
},
|
|
204
|
+
cache(key, create, destroy) {
|
|
205
|
+
return host.forNode(HOST_SCOPE).cache(key, create, destroy);
|
|
206
|
+
},
|
|
207
|
+
async ensure() {
|
|
208
|
+
if (disposed) throw new Error(DISPOSED);
|
|
209
|
+
if (active) return;
|
|
210
|
+
if (!starting) {
|
|
211
|
+
const attempt = start();
|
|
212
|
+
const tracked = attempt.finally(() => {
|
|
213
|
+
if (starting === tracked) starting = null;
|
|
214
|
+
});
|
|
215
|
+
starting = tracked;
|
|
216
|
+
}
|
|
217
|
+
await starting;
|
|
218
|
+
},
|
|
219
|
+
forNode(nodeId) {
|
|
220
|
+
return {
|
|
221
|
+
get device() {
|
|
222
|
+
if (!active) throw new Error(MISSING_DEVICE);
|
|
223
|
+
return active.device;
|
|
224
|
+
},
|
|
225
|
+
get adapterInfo() {
|
|
226
|
+
if (!active) throw new Error(MISSING_DEVICE);
|
|
227
|
+
return active.info;
|
|
228
|
+
},
|
|
229
|
+
get limits() {
|
|
230
|
+
return active?.limits ?? {};
|
|
231
|
+
},
|
|
232
|
+
cache(key, create, destroy) {
|
|
233
|
+
if (!active) throw new Error(MISSING_DEVICE);
|
|
234
|
+
let entries = caches.get(nodeId);
|
|
235
|
+
if (!entries) {
|
|
236
|
+
entries = /* @__PURE__ */ new Map();
|
|
237
|
+
caches.set(nodeId, entries);
|
|
238
|
+
}
|
|
239
|
+
const existing = entries.get(key);
|
|
240
|
+
if (existing) return existing.value;
|
|
241
|
+
const value = create(active.device);
|
|
242
|
+
entries.set(key, {
|
|
243
|
+
value,
|
|
244
|
+
destroy
|
|
245
|
+
});
|
|
246
|
+
return value;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
},
|
|
250
|
+
dispose() {
|
|
251
|
+
disposal ??= performDispose();
|
|
252
|
+
return disposal;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
async function performDispose() {
|
|
256
|
+
disposed = true;
|
|
257
|
+
const errors = dropCaches();
|
|
258
|
+
const pending = starting;
|
|
259
|
+
if (pending) {
|
|
260
|
+
try {
|
|
261
|
+
await pending;
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (!(error instanceof Error && error.message === DISPOSED))
|
|
264
|
+
errors.push(error);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const acquired = active;
|
|
268
|
+
active = null;
|
|
269
|
+
if (acquired) errors.push(...await release(acquired, true));
|
|
270
|
+
await Promise.all([...retiring]);
|
|
271
|
+
errors.push(...retirementErrors);
|
|
272
|
+
retirementErrors.length = 0;
|
|
273
|
+
throwCleanupErrors(errors);
|
|
274
|
+
}
|
|
275
|
+
return host;
|
|
276
|
+
}
|
|
277
|
+
function readGpuLimits(source) {
|
|
278
|
+
if (!source || typeof source !== "object") return {};
|
|
279
|
+
const names = new Set(Object.keys(source));
|
|
280
|
+
for (let cursor = Object.getPrototypeOf(source); cursor && cursor !== Object.prototype; cursor = Object.getPrototypeOf(cursor)) {
|
|
281
|
+
for (const key of Object.getOwnPropertyNames(cursor)) {
|
|
282
|
+
if (key !== "constructor") names.add(key);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const limits = {};
|
|
286
|
+
for (const key of names) {
|
|
287
|
+
const value = source[key];
|
|
288
|
+
if (typeof value === "number") limits[key] = value;
|
|
289
|
+
}
|
|
290
|
+
return limits;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export {
|
|
294
|
+
bundleFieldType,
|
|
295
|
+
bundleSchemasCompatible,
|
|
296
|
+
isBundleValue,
|
|
297
|
+
selectBundleFields,
|
|
298
|
+
suggestName,
|
|
299
|
+
unknownFieldMessage,
|
|
300
|
+
bundleValueProblem,
|
|
301
|
+
isGpuHost,
|
|
302
|
+
createGpuHost,
|
|
303
|
+
DEFAULT_GRAPH_SEED,
|
|
304
|
+
graphSeed,
|
|
305
|
+
nodeSeed,
|
|
306
|
+
seededRandom
|
|
307
|
+
};
|
|
308
|
+
//# sourceMappingURL=chunk-GFS6W3C5.js.map
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExpressionEvaluator,
|
|
3
|
+
isEmptyChannel,
|
|
4
|
+
parseBundleFieldPath,
|
|
5
|
+
sampleChannel
|
|
6
|
+
} from "./chunk-CO22XHNG.js";
|
|
7
|
+
|
|
8
|
+
// packages/runtime/src/params/resolve.ts
|
|
9
|
+
function isBoundProp(binding) {
|
|
10
|
+
if (!binding) return false;
|
|
11
|
+
return !!binding.expression || !isEmptyChannel(binding.channel);
|
|
12
|
+
}
|
|
13
|
+
function resolvePropBinding(binding, context) {
|
|
14
|
+
if (!isEmptyChannel(binding.channel)) {
|
|
15
|
+
const sampled = sampleChannel(binding.channel, context.frame);
|
|
16
|
+
if (sampled !== void 0) return { value: sampled, source: "channel" };
|
|
17
|
+
}
|
|
18
|
+
if (binding.expression && context.evaluateExpression) {
|
|
19
|
+
const result = context.evaluateExpression(binding.expression);
|
|
20
|
+
if (result?.error) {
|
|
21
|
+
return { value: binding.value, source: "value", error: result.error };
|
|
22
|
+
}
|
|
23
|
+
if (result) return { value: result.value, source: "expression" };
|
|
24
|
+
}
|
|
25
|
+
return { value: binding.value, source: "value" };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// packages/runtime/src/params/animator.ts
|
|
29
|
+
var PropAnimator = class {
|
|
30
|
+
constructor(topology) {
|
|
31
|
+
this.topology = topology;
|
|
32
|
+
this.resolving = /* @__PURE__ */ new Set();
|
|
33
|
+
this.evaluator = new ExpressionEvaluator(this.scope());
|
|
34
|
+
}
|
|
35
|
+
/** True when any parameter in the graph is bound at all — so a host can skip
|
|
36
|
+
* the whole pass, and a graph with no animation costs nothing. */
|
|
37
|
+
get animated() {
|
|
38
|
+
return this.topology.nodes.some(
|
|
39
|
+
(node) => Object.values(node.bindings).some((binding) => isBoundProp(binding))
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
setFrame(frame) {
|
|
43
|
+
this.evaluator.setFrame(frame);
|
|
44
|
+
}
|
|
45
|
+
setFps(fps) {
|
|
46
|
+
this.evaluator.setFps(fps);
|
|
47
|
+
}
|
|
48
|
+
/** Write every bound parameter's value at the current frame into `props`. */
|
|
49
|
+
resolveAll() {
|
|
50
|
+
for (const node of this.topology.nodes)
|
|
51
|
+
for (const name of Object.keys(node.bindings)) this.resolve(node, name);
|
|
52
|
+
}
|
|
53
|
+
/** Re-resolve one node's bound parameters, e.g. once its inputs exist. */
|
|
54
|
+
resolveNode(node) {
|
|
55
|
+
for (const name of Object.keys(node.bindings)) this.resolve(node, name);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* One parameter, at the current frame.
|
|
59
|
+
*
|
|
60
|
+
* Re-entry returns the stored value rather than throwing: a parameter whose
|
|
61
|
+
* expression refers back to itself is an author's mistake, and the render
|
|
62
|
+
* that names it is more use than the one that dies.
|
|
63
|
+
*/
|
|
64
|
+
resolve(node, name) {
|
|
65
|
+
const binding = node.bindings[name];
|
|
66
|
+
if (!binding) return node.props[name];
|
|
67
|
+
const key = `${node.id}.${name}`;
|
|
68
|
+
if (this.resolving.has(key)) return binding.value;
|
|
69
|
+
this.resolving.add(key);
|
|
70
|
+
try {
|
|
71
|
+
const resolved = resolvePropBinding(binding, {
|
|
72
|
+
frame: this.evaluator.fframe,
|
|
73
|
+
evaluateExpression: (expression) => this.evaluator.evaluate(expression, node)
|
|
74
|
+
});
|
|
75
|
+
if (resolved.error) this.topology.report?.(node.id, name, resolved.error);
|
|
76
|
+
node.props[name] = resolved.value;
|
|
77
|
+
return resolved.value;
|
|
78
|
+
} finally {
|
|
79
|
+
this.resolving.delete(key);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The host binding the expression engine reads through.
|
|
84
|
+
*
|
|
85
|
+
* A path names a parameter — `./radius`, `../blur1/amount`,
|
|
86
|
+
* `/root/blur1/amount` — and the last segment is always the parameter, the
|
|
87
|
+
* one before it the node. Anything a graph does not have resolves to null,
|
|
88
|
+
* which the engine turns into 0 / '' / [] per accessor rather than an
|
|
89
|
+
* exception: one broken reference must not take a render down.
|
|
90
|
+
*/
|
|
91
|
+
scope() {
|
|
92
|
+
return {
|
|
93
|
+
resolveParam: (from, path) => {
|
|
94
|
+
const segments = split(path);
|
|
95
|
+
if (!segments.length) return null;
|
|
96
|
+
const name = segments[segments.length - 1];
|
|
97
|
+
const owner = this.owner(from, segments.slice(0, -1));
|
|
98
|
+
if (!owner) return null;
|
|
99
|
+
if (owner.bindings[name]) return { value: this.resolve(owner, name) };
|
|
100
|
+
const field = parseBundleFieldPath(name);
|
|
101
|
+
if (field && this.topology.inputValue) {
|
|
102
|
+
const bundle = this.topology.inputValue(owner, field.port);
|
|
103
|
+
if (bundle === null || typeof bundle !== "object") return null;
|
|
104
|
+
if (!Object.prototype.hasOwnProperty.call(bundle, field.field)) return null;
|
|
105
|
+
return { value: bundle[field.field] };
|
|
106
|
+
}
|
|
107
|
+
if (name in owner.props) return { value: owner.props[name] };
|
|
108
|
+
if (name in owner.inputs) return { value: owner.inputs[name] };
|
|
109
|
+
return null;
|
|
110
|
+
},
|
|
111
|
+
nodeExists: (from, path) => {
|
|
112
|
+
const segments = split(path);
|
|
113
|
+
if (!segments.length) return false;
|
|
114
|
+
const last = segments[segments.length - 1];
|
|
115
|
+
if (last === "..") return true;
|
|
116
|
+
return last === from.id || !!this.topology.node(last);
|
|
117
|
+
},
|
|
118
|
+
inputNode: (from, index) => this.topology.inputNode(from, index)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/** The node a path's leading segments name, or `from` when they name none. */
|
|
122
|
+
owner(from, segments) {
|
|
123
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
124
|
+
if (segments[i] === "..") continue;
|
|
125
|
+
return this.topology.node(segments[i]);
|
|
126
|
+
}
|
|
127
|
+
return from;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
function split(path) {
|
|
131
|
+
return String(path ?? "").split("/").filter((segment) => segment.length > 0 && segment !== ".");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export {
|
|
135
|
+
isBoundProp,
|
|
136
|
+
resolvePropBinding,
|
|
137
|
+
PropAnimator
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=chunk-HFHWYL55.js.map
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import {
|
|
2
|
+
POSITION_ATTRIBUTE,
|
|
3
|
+
PRIMITIVE_KINDS,
|
|
4
|
+
attributeArray,
|
|
5
|
+
attributeArrayFrom,
|
|
6
|
+
createGeometry,
|
|
7
|
+
isStringAttribute
|
|
8
|
+
} from "./chunk-J7VK7MNF.js";
|
|
9
|
+
|
|
10
|
+
// packages/runtime/src/geometry/attributes.ts
|
|
11
|
+
function geometryError(code, message) {
|
|
12
|
+
throw new TypeError(`geometry/${code}: ${message}`);
|
|
13
|
+
}
|
|
14
|
+
function attributeSet(geometry, level) {
|
|
15
|
+
return geometry[level];
|
|
16
|
+
}
|
|
17
|
+
function numericAttribute(attribute, path, sizes) {
|
|
18
|
+
if (attribute === void 0) return void 0;
|
|
19
|
+
if (isStringAttribute(attribute))
|
|
20
|
+
geometryError("attribute-storage", `${path} must be numeric`);
|
|
21
|
+
if (sizes !== void 0 && !sizes.includes(attribute.size))
|
|
22
|
+
geometryError(
|
|
23
|
+
"attribute-size",
|
|
24
|
+
`${path} has size ${attribute.size}; expected ${sizes.join(" or ")}`
|
|
25
|
+
);
|
|
26
|
+
return attribute;
|
|
27
|
+
}
|
|
28
|
+
function readComponent(attribute, index, component = 0) {
|
|
29
|
+
return attribute.data[index * attribute.size + component];
|
|
30
|
+
}
|
|
31
|
+
function readElement(attribute, index) {
|
|
32
|
+
const values = new Array(attribute.size);
|
|
33
|
+
for (let component = 0; component < attribute.size; component += 1)
|
|
34
|
+
values[component] = attribute.data[index * attribute.size + component];
|
|
35
|
+
return values;
|
|
36
|
+
}
|
|
37
|
+
function readString(attribute, index) {
|
|
38
|
+
const slot = attribute.data[index];
|
|
39
|
+
return slot < 0 ? "" : attribute.table[slot] ?? "";
|
|
40
|
+
}
|
|
41
|
+
function positionSize(geometry) {
|
|
42
|
+
return geometry.point[POSITION_ATTRIBUTE].size;
|
|
43
|
+
}
|
|
44
|
+
function positionAttribute(geometry) {
|
|
45
|
+
return geometry.point[POSITION_ATTRIBUTE];
|
|
46
|
+
}
|
|
47
|
+
function getPosition(geometry, index) {
|
|
48
|
+
return readElement(positionAttribute(geometry), index);
|
|
49
|
+
}
|
|
50
|
+
function createAttribute(count, size, storage = "f64", fill) {
|
|
51
|
+
const data = attributeArray(storage, size * count);
|
|
52
|
+
if (fill !== void 0) {
|
|
53
|
+
const values = typeof fill === "number" ? [fill] : fill;
|
|
54
|
+
for (let index = 0; index < count; index += 1)
|
|
55
|
+
for (let component = 0; component < size; component += 1)
|
|
56
|
+
data[index * size + component] = values[component % Math.max(values.length, 1)] ?? 0;
|
|
57
|
+
}
|
|
58
|
+
return { storage, size, data };
|
|
59
|
+
}
|
|
60
|
+
function createStringAttribute(values) {
|
|
61
|
+
const table = [];
|
|
62
|
+
const slots = /* @__PURE__ */ new Map();
|
|
63
|
+
const data = new Int32Array(values.length);
|
|
64
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
65
|
+
const value = values[index];
|
|
66
|
+
let slot = slots.get(value);
|
|
67
|
+
if (slot === void 0) {
|
|
68
|
+
slot = table.length;
|
|
69
|
+
table.push(value);
|
|
70
|
+
slots.set(value, slot);
|
|
71
|
+
}
|
|
72
|
+
data[index] = slot;
|
|
73
|
+
}
|
|
74
|
+
return { storage: "string", size: 1, table, data };
|
|
75
|
+
}
|
|
76
|
+
function withAttributeSet(geometry, level, set) {
|
|
77
|
+
return createGeometry({
|
|
78
|
+
pointCount: geometry.pointCount,
|
|
79
|
+
point: level === "point" ? set : geometry.point,
|
|
80
|
+
vertex: level === "vertex" ? set : geometry.vertex,
|
|
81
|
+
primitive: level === "primitive" ? set : geometry.primitive,
|
|
82
|
+
detail: geometry.detail,
|
|
83
|
+
topology: geometry.topology,
|
|
84
|
+
pointGroups: geometry.pointGroups,
|
|
85
|
+
primitiveGroups: geometry.primitiveGroups
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function setAttribute(geometry, level, name, attribute) {
|
|
89
|
+
return withAttributeSet(geometry, level, {
|
|
90
|
+
...geometry[level],
|
|
91
|
+
[name]: attribute
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function copyAttributeArray(attribute) {
|
|
95
|
+
return attributeArrayFrom(attribute.storage, attribute.data);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// packages/runtime/src/geometry/builder.ts
|
|
99
|
+
var GeometryBuilder = class {
|
|
100
|
+
constructor(options = {}) {
|
|
101
|
+
this.positions = [];
|
|
102
|
+
this.vertexPoints = [];
|
|
103
|
+
this.offsets = [0];
|
|
104
|
+
this.kinds = [];
|
|
105
|
+
this.closed = [];
|
|
106
|
+
this.attributes = { point: {}, vertex: {}, primitive: {} };
|
|
107
|
+
this.detail = {};
|
|
108
|
+
this.pointGroups = /* @__PURE__ */ new Map();
|
|
109
|
+
this.primitiveGroups = /* @__PURE__ */ new Map();
|
|
110
|
+
this.size = options.positionSize ?? 2;
|
|
111
|
+
this.storage = options.positionStorage ?? "f64";
|
|
112
|
+
}
|
|
113
|
+
get pointCount() {
|
|
114
|
+
return this.positions.length / this.size;
|
|
115
|
+
}
|
|
116
|
+
get vertexCount() {
|
|
117
|
+
return this.vertexPoints.length;
|
|
118
|
+
}
|
|
119
|
+
get primitiveCount() {
|
|
120
|
+
return this.offsets.length - 1;
|
|
121
|
+
}
|
|
122
|
+
/** Append one point and return its index. */
|
|
123
|
+
addPoint(x, y, z = 0) {
|
|
124
|
+
const index = this.pointCount;
|
|
125
|
+
this.positions.push(x, y);
|
|
126
|
+
if (this.size === 3) this.positions.push(z);
|
|
127
|
+
return index;
|
|
128
|
+
}
|
|
129
|
+
/** Append points from a flat array of `positionSize`-wide entries. */
|
|
130
|
+
addPoints(flat) {
|
|
131
|
+
if (flat.length % this.size !== 0)
|
|
132
|
+
geometryError(
|
|
133
|
+
"point-stride",
|
|
134
|
+
`${flat.length} values is not a multiple of the position size ${this.size}`
|
|
135
|
+
);
|
|
136
|
+
const first = this.pointCount;
|
|
137
|
+
for (let index = 0; index < flat.length; index += 1)
|
|
138
|
+
this.positions.push(flat[index]);
|
|
139
|
+
return first;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Append one primitive over existing point indices and return its index. A
|
|
143
|
+
* closed primitive does not repeat its first point: `closed` is topology, not
|
|
144
|
+
* a duplicated vertex.
|
|
145
|
+
*/
|
|
146
|
+
addPrimitive(points, options = {}) {
|
|
147
|
+
const index = this.primitiveCount;
|
|
148
|
+
for (const point of points) {
|
|
149
|
+
if (!Number.isInteger(point) || point < 0 || point >= this.pointCount)
|
|
150
|
+
geometryError(
|
|
151
|
+
"vertex-point",
|
|
152
|
+
`primitive ${index} references point ${point} of ${this.pointCount}`
|
|
153
|
+
);
|
|
154
|
+
this.vertexPoints.push(point);
|
|
155
|
+
}
|
|
156
|
+
this.offsets.push(this.vertexPoints.length);
|
|
157
|
+
this.kinds.push(PRIMITIVE_KINDS.indexOf(options.kind ?? "poly"));
|
|
158
|
+
this.closed.push(options.closed ? 1 : 0);
|
|
159
|
+
return index;
|
|
160
|
+
}
|
|
161
|
+
/** Append points and one primitive over them, the common generator case. */
|
|
162
|
+
addPolygon(flat, options = {}) {
|
|
163
|
+
const first = this.addPoints(flat);
|
|
164
|
+
const points = [];
|
|
165
|
+
for (let index = first; index < this.pointCount; index += 1)
|
|
166
|
+
points.push(index);
|
|
167
|
+
return this.addPrimitive(points, options);
|
|
168
|
+
}
|
|
169
|
+
setAttribute(level, name, attribute) {
|
|
170
|
+
if (level === "point" && name === POSITION_ATTRIBUTE)
|
|
171
|
+
geometryError(
|
|
172
|
+
"set-position",
|
|
173
|
+
"point.P is owned by the builder; use addPoint"
|
|
174
|
+
);
|
|
175
|
+
this.attributes[level][name] = attribute;
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
setNumericAttribute(level, name, values, size = 1, storage = "f64") {
|
|
179
|
+
return this.setAttribute(level, name, {
|
|
180
|
+
storage,
|
|
181
|
+
size,
|
|
182
|
+
data: attributeArrayFrom(storage, values)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
setStringAttribute(level, name, values) {
|
|
186
|
+
return this.setAttribute(level, name, createStringAttribute(values));
|
|
187
|
+
}
|
|
188
|
+
setDetail(name, value) {
|
|
189
|
+
this.detail[name] = value;
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
addToPointGroup(name, index) {
|
|
193
|
+
const members = this.pointGroups.get(name) ?? /* @__PURE__ */ new Set();
|
|
194
|
+
members.add(index);
|
|
195
|
+
this.pointGroups.set(name, members);
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
addToPrimitiveGroup(name, index) {
|
|
199
|
+
const members = this.primitiveGroups.get(name) ?? /* @__PURE__ */ new Set();
|
|
200
|
+
members.add(index);
|
|
201
|
+
this.primitiveGroups.set(name, members);
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
build() {
|
|
205
|
+
const pointCount = this.pointCount;
|
|
206
|
+
const pointGroups = {};
|
|
207
|
+
for (const [name, members] of this.pointGroups)
|
|
208
|
+
pointGroups[name] = mask(members, pointCount);
|
|
209
|
+
const primitiveGroups = {};
|
|
210
|
+
for (const [name, members] of this.primitiveGroups)
|
|
211
|
+
primitiveGroups[name] = mask(members, this.primitiveCount);
|
|
212
|
+
return createGeometry({
|
|
213
|
+
pointCount,
|
|
214
|
+
point: {
|
|
215
|
+
...this.attributes.point,
|
|
216
|
+
[POSITION_ATTRIBUTE]: {
|
|
217
|
+
storage: this.storage,
|
|
218
|
+
size: this.size,
|
|
219
|
+
data: attributeArrayFrom(this.storage, this.positions)
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
vertex: this.attributes.vertex,
|
|
223
|
+
primitive: this.attributes.primitive,
|
|
224
|
+
detail: this.detail,
|
|
225
|
+
topology: {
|
|
226
|
+
vertexPoints: Int32Array.from(this.vertexPoints),
|
|
227
|
+
offsets: Int32Array.from(this.offsets),
|
|
228
|
+
kinds: Uint8Array.from(this.kinds),
|
|
229
|
+
closed: Uint8Array.from(this.closed)
|
|
230
|
+
},
|
|
231
|
+
pointGroups,
|
|
232
|
+
primitiveGroups
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
function mask(members, count) {
|
|
237
|
+
const result = new Uint8Array(count);
|
|
238
|
+
for (const member of members) {
|
|
239
|
+
if (!Number.isInteger(member) || member < 0 || member >= count)
|
|
240
|
+
geometryError("group-indices", `group references element ${member}`);
|
|
241
|
+
result[member] = 1;
|
|
242
|
+
}
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export {
|
|
247
|
+
geometryError,
|
|
248
|
+
attributeSet,
|
|
249
|
+
numericAttribute,
|
|
250
|
+
readComponent,
|
|
251
|
+
readElement,
|
|
252
|
+
readString,
|
|
253
|
+
positionSize,
|
|
254
|
+
positionAttribute,
|
|
255
|
+
getPosition,
|
|
256
|
+
createAttribute,
|
|
257
|
+
createStringAttribute,
|
|
258
|
+
withAttributeSet,
|
|
259
|
+
setAttribute,
|
|
260
|
+
copyAttributeArray,
|
|
261
|
+
GeometryBuilder
|
|
262
|
+
};
|
|
263
|
+
//# sourceMappingURL=chunk-HSNOBIVT.js.map
|