@field/cascade 0.5.2 → 0.6.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/CHANGELOG.md +42 -0
- package/dist/assets/{CodeEditor-BHej8kM9.js → CodeEditor-BLpahZw6.js} +7 -7
- package/dist/assets/{CodePanel-CT3eirK8.js → CodePanel-BqYKqBMH.js} +2 -2
- package/dist/assets/{CustomNodeDialog-BG0m7_Rv.js → CustomNodeDialog-CYr9y7dG.js} +1 -1
- package/dist/assets/{ProjectSettings-BxoLWJG6.js → ProjectSettings-CnYfrkKh.js} +2 -2
- package/dist/assets/{SettingsDialog-r9PzZ22z.js → SettingsDialog-mSS6KUyS.js} +1 -1
- package/dist/assets/{VersionHistoryDialog-B6zUV6Dy.js → VersionHistoryDialog-DZuwNG6s.js} +1 -1
- package/dist/assets/{core-wwx5881P.js → core-BOGrwBxU.js} +2 -2
- package/dist/assets/{cssMode-DY5T2Or0.js → cssMode-0Z3pyDOW.js} +1 -1
- package/dist/assets/definitions-Cckh442l.js +1 -0
- package/dist/assets/{editor.api-mkORHEMm.js → editor.api-D-_7pnnj.js} +1 -1
- package/dist/assets/{freemarker2-CIWlk0sw.js → freemarker2-DE0JRkF7.js} +1 -1
- package/dist/assets/geo-DcAVygkw.js +1 -0
- package/dist/assets/{handlebars-t4jbj3Br.js → handlebars-B_Shirzj.js} +1 -1
- package/dist/assets/{html-Ctx7UOlY.js → html-DI5Qj4gd.js} +1 -1
- package/dist/assets/{htmlMode-BKNZxVw7.js → htmlMode-CkHZy0mE.js} +1 -1
- package/dist/assets/{image-BCBFz0gD.js → image-B6RU2frM.js} +3 -3
- package/dist/assets/{index-CeqTfMbr.js → index-DTyzl6YV.js} +36 -36
- package/dist/assets/{javascript-Da_TJBzH.js → javascript-zxQfbzS_.js} +1 -1
- package/dist/assets/{jsonMode-Ftt5d1nV.js → jsonMode-DSQ0uLqA.js} +1 -1
- package/dist/assets/{liquid-D5kWYG57.js → liquid-0zs2oOuA.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-B-93LC_L.js → lspLanguageFeatures-7VWaq5lc.js} +1 -1
- package/dist/assets/math-BA6juJD7.js +1 -0
- package/dist/assets/{mdx-DGT3C_qs.js → mdx-BFKlF5Xh.js} +1 -1
- package/dist/assets/pop-Bkzzmp57.js +1 -0
- package/dist/assets/{python-Bz3Eew5S.js → python-BgexpWZh.js} +1 -1
- package/dist/assets/{razor-CFDdKpKI.js → razor-E1kWyvkT.js} +1 -1
- package/dist/assets/{tsMode-BaCINWBI.js → tsMode-CTmJLLW5.js} +1 -1
- package/dist/assets/{typescript-BoOWspVs.js → typescript-BheZLRDM.js} +1 -1
- package/dist/assets/{workers-dSWyDxsQ.js → workers-KIoho05H.js} +1 -1
- package/dist/assets/{xml-eFi1_vYt.js → xml-DaVLg9zI.js} +1 -1
- package/dist/assets/{yaml-a7xrJHxm.js → yaml-D6XGTfOj.js} +1 -1
- package/dist/cli/index.js +574 -289
- package/dist/index.html +1 -1
- package/dist/runtime/builtins/index.js +2 -0
- package/dist/runtime/builtins/math/definitions.d.ts +845 -0
- package/dist/runtime/builtins/math/definitions.js +285 -0
- package/dist/runtime/builtins/math/index.d.ts +2 -0
- package/dist/runtime/builtins/math/index.js +2 -0
- package/doc/NODE_REFERENCE.md +115 -0
- package/package.json +1 -1
- package/dist/assets/definitions-BgCvRHyR.js +0 -1
- package/dist/assets/geo-CIxgs0oE.js +0 -1
- package/dist/assets/pop-BJGN5Ac4.js +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -1653,8 +1653,8 @@ function frameRange(start, end, step2 = 1) {
|
|
|
1653
1653
|
for (let i = 0; i < count; i++) frames[i] = start + i * step2;
|
|
1654
1654
|
return frames;
|
|
1655
1655
|
}
|
|
1656
|
-
async function runFrameRange(clock2,
|
|
1657
|
-
const { start, end, step: step2 = 1, onFrame, signal, restoreFrame = true } =
|
|
1656
|
+
async function runFrameRange(clock2, options2) {
|
|
1657
|
+
const { start, end, step: step2 = 1, onFrame, signal, restoreFrame = true } = options2;
|
|
1658
1658
|
const frames = frameRange(start, end, step2);
|
|
1659
1659
|
const previousFrame = clock2.getFrameFraction();
|
|
1660
1660
|
const visited = [];
|
|
@@ -1842,7 +1842,7 @@ var init_params = __esm({
|
|
|
1842
1842
|
function isGpuHost(value) {
|
|
1843
1843
|
return !!value && typeof value.ensure === "function" && typeof value.forNode === "function" && typeof value.dispose === "function";
|
|
1844
1844
|
}
|
|
1845
|
-
function createGpuHost(
|
|
1845
|
+
function createGpuHost(options2) {
|
|
1846
1846
|
let active = null;
|
|
1847
1847
|
let starting = null;
|
|
1848
1848
|
let disposal = null;
|
|
@@ -1905,7 +1905,7 @@ function createGpuHost(options) {
|
|
|
1905
1905
|
});
|
|
1906
1906
|
}
|
|
1907
1907
|
async function start() {
|
|
1908
|
-
const result = await
|
|
1908
|
+
const result = await options2.acquire();
|
|
1909
1909
|
const acquired = {
|
|
1910
1910
|
device: result.device,
|
|
1911
1911
|
info: {
|
|
@@ -2323,7 +2323,7 @@ var init_builder = __esm({
|
|
|
2323
2323
|
init_src();
|
|
2324
2324
|
init_attributes();
|
|
2325
2325
|
GeometryBuilder = class {
|
|
2326
|
-
constructor(
|
|
2326
|
+
constructor(options2 = {}) {
|
|
2327
2327
|
this.positions = [];
|
|
2328
2328
|
this.vertexPoints = [];
|
|
2329
2329
|
this.offsets = [0];
|
|
@@ -2333,8 +2333,8 @@ var init_builder = __esm({
|
|
|
2333
2333
|
this.detail = {};
|
|
2334
2334
|
this.pointGroups = /* @__PURE__ */ new Map();
|
|
2335
2335
|
this.primitiveGroups = /* @__PURE__ */ new Map();
|
|
2336
|
-
this.size =
|
|
2337
|
-
this.storage =
|
|
2336
|
+
this.size = options2.positionSize ?? 2;
|
|
2337
|
+
this.storage = options2.positionStorage ?? "f64";
|
|
2338
2338
|
}
|
|
2339
2339
|
get pointCount() {
|
|
2340
2340
|
return this.positions.length / this.size;
|
|
@@ -2369,7 +2369,7 @@ var init_builder = __esm({
|
|
|
2369
2369
|
* closed primitive does not repeat its first point: `closed` is topology, not
|
|
2370
2370
|
* a duplicated vertex.
|
|
2371
2371
|
*/
|
|
2372
|
-
addPrimitive(points,
|
|
2372
|
+
addPrimitive(points, options2 = {}) {
|
|
2373
2373
|
const index = this.primitiveCount;
|
|
2374
2374
|
for (const point of points) {
|
|
2375
2375
|
if (!Number.isInteger(point) || point < 0 || point >= this.pointCount)
|
|
@@ -2380,17 +2380,17 @@ var init_builder = __esm({
|
|
|
2380
2380
|
this.vertexPoints.push(point);
|
|
2381
2381
|
}
|
|
2382
2382
|
this.offsets.push(this.vertexPoints.length);
|
|
2383
|
-
this.kinds.push(PRIMITIVE_KINDS.indexOf(
|
|
2384
|
-
this.closed.push(
|
|
2383
|
+
this.kinds.push(PRIMITIVE_KINDS.indexOf(options2.kind ?? "poly"));
|
|
2384
|
+
this.closed.push(options2.closed ? 1 : 0);
|
|
2385
2385
|
return index;
|
|
2386
2386
|
}
|
|
2387
2387
|
/** Append points and one primitive over them, the common generator case. */
|
|
2388
|
-
addPolygon(flat,
|
|
2388
|
+
addPolygon(flat, options2 = {}) {
|
|
2389
2389
|
const first = this.addPoints(flat);
|
|
2390
2390
|
const points = [];
|
|
2391
2391
|
for (let index = first; index < this.pointCount; index += 1)
|
|
2392
2392
|
points.push(index);
|
|
2393
|
-
return this.addPrimitive(points,
|
|
2393
|
+
return this.addPrimitive(points, options2);
|
|
2394
2394
|
}
|
|
2395
2395
|
setAttribute(level, name, attribute) {
|
|
2396
2396
|
if (level === "point" && name === POSITION_ATTRIBUTE)
|
|
@@ -2711,20 +2711,20 @@ var init_transform = __esm({
|
|
|
2711
2711
|
});
|
|
2712
2712
|
|
|
2713
2713
|
// packages/runtime/src/geometry/copy.ts
|
|
2714
|
-
function copyToPoints(source, target,
|
|
2714
|
+
function copyToPoints(source, target, options2 = {}) {
|
|
2715
2715
|
const width = positionSize(source) === 3 ? 3 : 2;
|
|
2716
|
-
const selection =
|
|
2716
|
+
const selection = options2.targetGroup === void 0 || options2.targetGroup === "" ? void 0 : groupMask(target, "point", options2.targetGroup) ?? geometryError(
|
|
2717
2717
|
"missing-group",
|
|
2718
|
-
`point group ${
|
|
2718
|
+
`point group ${options2.targetGroup} is not present on the target`
|
|
2719
2719
|
);
|
|
2720
2720
|
const indices = selection === void 0 ? range(target.pointCount) : groupIndices(selection);
|
|
2721
2721
|
if (indices.length === 0 || source.pointCount === 0)
|
|
2722
2722
|
return emptyGeometry(width);
|
|
2723
|
-
const orient =
|
|
2723
|
+
const orient = options2.useTargetOrientations ?? true;
|
|
2724
2724
|
const pscale = orient ? numericAttribute(target.point.pscale, "point.pscale", [1]) : void 0;
|
|
2725
2725
|
const normal = orient ? numericAttribute(target.point.N, "point.N", [2, 3]) : void 0;
|
|
2726
|
-
const copyNumber =
|
|
2727
|
-
const transfer =
|
|
2726
|
+
const copyNumber = options2.copyNumberAttribute ?? "copynum";
|
|
2727
|
+
const transfer = options2.transferTargetAttributes ?? true ? Object.keys(target.point).filter(
|
|
2728
2728
|
(name) => name !== POSITION_ATTRIBUTE && !Object.prototype.hasOwnProperty.call(source.point, name)
|
|
2729
2729
|
) : [];
|
|
2730
2730
|
const copies = [];
|
|
@@ -2794,9 +2794,9 @@ function finitePair(value, code) {
|
|
|
2794
2794
|
if (!Number.isFinite(value[0]) || !Number.isFinite(value[1]))
|
|
2795
2795
|
geometryError(code, "both components must be finite");
|
|
2796
2796
|
}
|
|
2797
|
-
function rectangleGeometry(
|
|
2798
|
-
const [width, height] =
|
|
2799
|
-
const [cx, cy] =
|
|
2797
|
+
function rectangleGeometry(options2 = {}) {
|
|
2798
|
+
const [width, height] = options2.size ?? [1, 1];
|
|
2799
|
+
const [cx, cy] = options2.center ?? [0, 0];
|
|
2800
2800
|
finitePair([width, height], "rectangle-size");
|
|
2801
2801
|
finitePair([cx, cy], "rectangle-center");
|
|
2802
2802
|
if (width < 0 || height < 0)
|
|
@@ -2809,16 +2809,16 @@ function rectangleGeometry(options = {}) {
|
|
|
2809
2809
|
builder.addPolygon([x0, y0, x1, y0, x1, y1, x0, y1], { closed: true });
|
|
2810
2810
|
return builder.build();
|
|
2811
2811
|
}
|
|
2812
|
-
function circleGeometry(
|
|
2813
|
-
const [cx, cy] =
|
|
2814
|
-
const [rx, ry] =
|
|
2812
|
+
function circleGeometry(options2 = {}) {
|
|
2813
|
+
const [cx, cy] = options2.center ?? [0, 0];
|
|
2814
|
+
const [rx, ry] = options2.radius ?? [1, 1];
|
|
2815
2815
|
finitePair([cx, cy], "circle-center");
|
|
2816
2816
|
finitePair([rx, ry], "circle-radius");
|
|
2817
2817
|
if (rx < 0 || ry < 0)
|
|
2818
2818
|
geometryError("circle-radius", "circle radius must not be negative");
|
|
2819
2819
|
const builder = new GeometryBuilder();
|
|
2820
|
-
if ((
|
|
2821
|
-
const divisions =
|
|
2820
|
+
if ((options2.type ?? "bezier") === "poly") {
|
|
2821
|
+
const divisions = options2.divisions ?? 32;
|
|
2822
2822
|
if (!Number.isSafeInteger(divisions) || divisions < 3)
|
|
2823
2823
|
geometryError(
|
|
2824
2824
|
"circle-divisions",
|
|
@@ -2956,10 +2956,10 @@ var init_resample = __esm({
|
|
|
2956
2956
|
});
|
|
2957
2957
|
|
|
2958
2958
|
// packages/runtime/src/geometry/svg.ts
|
|
2959
|
-
function geometryToSvg(geometry,
|
|
2960
|
-
validateOptions(
|
|
2961
|
-
const margin =
|
|
2962
|
-
const explicit =
|
|
2959
|
+
function geometryToSvg(geometry, options2 = {}) {
|
|
2960
|
+
validateOptions(options2);
|
|
2961
|
+
const margin = options2.margin ?? 0;
|
|
2962
|
+
const explicit = options2.bounds;
|
|
2963
2963
|
const bounds = explicit ? void 0 : geometryBounds(geometry);
|
|
2964
2964
|
const minX = explicit ? explicit[0] - margin : bounds === void 0 ? 0 : bounds.min[0] - margin;
|
|
2965
2965
|
const minY = explicit ? explicit[1] - margin : bounds === void 0 ? 0 : bounds.min[1] - margin;
|
|
@@ -2967,14 +2967,14 @@ function geometryToSvg(geometry, options = {}) {
|
|
|
2967
2967
|
const maxY = explicit ? explicit[3] + margin : bounds === void 0 ? 1 : bounds.max[1] + margin;
|
|
2968
2968
|
const spanX = Math.max(maxX - minX, Number.EPSILON);
|
|
2969
2969
|
const spanY = Math.max(maxY - minY, Number.EPSILON);
|
|
2970
|
-
const width =
|
|
2971
|
-
const height =
|
|
2972
|
-
const precision =
|
|
2970
|
+
const width = options2.width && options2.width > 0 ? options2.width : spanX;
|
|
2971
|
+
const height = options2.height && options2.height > 0 ? options2.height : spanY;
|
|
2972
|
+
const precision = options2.precision ?? 3;
|
|
2973
2973
|
const number = (value) => format(value, precision);
|
|
2974
|
-
const stroke =
|
|
2975
|
-
const strokeWidth =
|
|
2976
|
-
const fill =
|
|
2977
|
-
const filled = (
|
|
2974
|
+
const stroke = options2.stroke ?? BLACK;
|
|
2975
|
+
const strokeWidth = options2.strokeWidth ?? 1;
|
|
2976
|
+
const fill = options2.fill ?? BLACK;
|
|
2977
|
+
const filled = (options2.fillMode ?? "none") === "solid";
|
|
2978
2978
|
const colour = geometry.primitive.Cd;
|
|
2979
2979
|
const strokeWidths = numericAttribute(geometry.primitive.width, "primitive.width", [1]);
|
|
2980
2980
|
const opacities = numericAttribute(geometry.primitive.opacity, "primitive.opacity", [1]);
|
|
@@ -3037,7 +3037,7 @@ function geometryToSvg(geometry, options = {}) {
|
|
|
3037
3037
|
const position = positionAttribute(geometry);
|
|
3038
3038
|
for (let point = 0; point < geometry.pointCount; point += 1) {
|
|
3039
3039
|
if (loose[point] !== 1) continue;
|
|
3040
|
-
const radius = pointScale === void 0 ?
|
|
3040
|
+
const radius = pointScale === void 0 ? options2.pointRadius ?? 0.5 : readComponent(pointScale, point);
|
|
3041
3041
|
const paint = paintOf(pointColour, point, "point") ?? stroke;
|
|
3042
3042
|
const transparent = Color.alpha(paint) < 1;
|
|
3043
3043
|
body.push(
|
|
@@ -3051,13 +3051,13 @@ function geometryToSvg(geometry, options = {}) {
|
|
|
3051
3051
|
}
|
|
3052
3052
|
const root = [
|
|
3053
3053
|
`<svg xmlns="http://www.w3.org/2000/svg" width="${number(width)}" height="${number(height)}" viewBox="${number(minX)} ${number(-maxY)} ${number(spanX)} ${number(spanY)}">`,
|
|
3054
|
-
...
|
|
3055
|
-
`<rect x="${number(minX)}" y="${number(-maxY)}" width="${number(spanX)}" height="${number(spanY)}" fill="${Color.toHex(
|
|
3054
|
+
...options2.background ? [indent(
|
|
3055
|
+
`<rect x="${number(minX)}" y="${number(-maxY)}" width="${number(spanX)}" height="${number(spanY)}" fill="${Color.toHex(options2.background)}" />`,
|
|
3056
3056
|
1
|
|
3057
3057
|
)] : [],
|
|
3058
3058
|
indent("<!-- Geometry is +Y up; SVG is +Y down. This is the one flip. -->", 1),
|
|
3059
3059
|
indent(
|
|
3060
|
-
`<g transform="scale(1,-1)" fill="${filled ? Color.toHex(fill) : "none"}"${filled && Color.alpha(fill) < 1 ? ` fill-opacity="${number(Color.alpha(fill))}"` : ""} stroke="${Color.toHex(stroke)}"${Color.alpha(stroke) < 1 ? ` stroke-opacity="${number(Color.alpha(stroke))}"` : ""} stroke-width="${number(strokeWidth)}"${
|
|
3060
|
+
`<g transform="scale(1,-1)" fill="${filled ? Color.toHex(fill) : "none"}"${filled && Color.alpha(fill) < 1 ? ` fill-opacity="${number(Color.alpha(fill))}"` : ""} stroke="${Color.toHex(stroke)}"${Color.alpha(stroke) < 1 ? ` stroke-opacity="${number(Color.alpha(stroke))}"` : ""} stroke-width="${number(strokeWidth)}"${options2.opacity !== void 0 && options2.opacity !== 1 ? ` opacity="${number(options2.opacity)}"` : ""}>`,
|
|
3061
3061
|
1
|
|
3062
3062
|
),
|
|
3063
3063
|
...body,
|
|
@@ -3110,25 +3110,25 @@ function format(value, precision) {
|
|
|
3110
3110
|
const rounded = Number.parseFloat(value.toFixed(precision));
|
|
3111
3111
|
return Object.is(rounded, -0) ? "0" : String(rounded);
|
|
3112
3112
|
}
|
|
3113
|
-
function validateOptions(
|
|
3113
|
+
function validateOptions(options2) {
|
|
3114
3114
|
for (const [name, value] of [
|
|
3115
|
-
["width",
|
|
3116
|
-
["height",
|
|
3117
|
-
["margin",
|
|
3118
|
-
["strokeWidth",
|
|
3119
|
-
["opacity",
|
|
3120
|
-
["pointRadius",
|
|
3115
|
+
["width", options2.width],
|
|
3116
|
+
["height", options2.height],
|
|
3117
|
+
["margin", options2.margin],
|
|
3118
|
+
["strokeWidth", options2.strokeWidth],
|
|
3119
|
+
["opacity", options2.opacity],
|
|
3120
|
+
["pointRadius", options2.pointRadius]
|
|
3121
3121
|
]) {
|
|
3122
3122
|
if (value !== void 0 && !Number.isFinite(value))
|
|
3123
3123
|
geometryError("svg-option", `${name} must be finite`);
|
|
3124
3124
|
}
|
|
3125
|
-
if ((
|
|
3125
|
+
if ((options2.width ?? 0) < 0 || (options2.height ?? 0) < 0)
|
|
3126
3126
|
geometryError("svg-option", "width and height must not be negative");
|
|
3127
|
-
if ((
|
|
3127
|
+
if ((options2.strokeWidth ?? 0) < 0 || (options2.pointRadius ?? 0) < 0)
|
|
3128
3128
|
geometryError("svg-option", "strokeWidth and pointRadius must not be negative");
|
|
3129
|
-
if (
|
|
3129
|
+
if (options2.opacity !== void 0 && (options2.opacity < 0 || options2.opacity > 1))
|
|
3130
3130
|
geometryError("svg-option", "opacity must be between 0 and 1");
|
|
3131
|
-
const precision =
|
|
3131
|
+
const precision = options2.precision ?? 3;
|
|
3132
3132
|
if (!Number.isSafeInteger(precision) || precision < 0 || precision > 15)
|
|
3133
3133
|
geometryError("svg-precision", "precision must be an integer from 0 to 15");
|
|
3134
3134
|
}
|
|
@@ -3842,7 +3842,7 @@ var init_core = __esm({
|
|
|
3842
3842
|
previousRegistration
|
|
3843
3843
|
]);
|
|
3844
3844
|
registrationsById = new Map(
|
|
3845
|
-
coreNodeRegistrations.map((
|
|
3845
|
+
coreNodeRegistrations.map((registration2) => [registration2.moduleId, registration2])
|
|
3846
3846
|
);
|
|
3847
3847
|
}
|
|
3848
3848
|
});
|
|
@@ -4223,24 +4223,24 @@ function multiply(matrix, x, y, z) {
|
|
|
4223
4223
|
(row) => matrix[row] * x + matrix[4 + row] * y + matrix[8 + row] * z + matrix[12 + row]
|
|
4224
4224
|
);
|
|
4225
4225
|
}
|
|
4226
|
-
function renderScene(geometry,
|
|
4227
|
-
const [width, height] =
|
|
4228
|
-
const canvas =
|
|
4226
|
+
function renderScene(geometry, options2) {
|
|
4227
|
+
const [width, height] = options2.size;
|
|
4228
|
+
const canvas = options2.surface(
|
|
4229
4229
|
Math.max(1, Math.round(width)),
|
|
4230
4230
|
Math.max(1, Math.round(height))
|
|
4231
4231
|
);
|
|
4232
4232
|
const context = canvas.getContext("2d");
|
|
4233
4233
|
if (!context) throw new Error("no 2D context on this surface");
|
|
4234
|
-
if (
|
|
4235
|
-
context.fillStyle = css(
|
|
4234
|
+
if (options2.background && options2.background[3] > 0) {
|
|
4235
|
+
context.fillStyle = css(options2.background);
|
|
4236
4236
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
4237
4237
|
}
|
|
4238
|
-
for (const one of geometry) drawGeometry(context, canvas, one,
|
|
4238
|
+
for (const one of geometry) drawGeometry(context, canvas, one, options2);
|
|
4239
4239
|
return canvas;
|
|
4240
4240
|
}
|
|
4241
|
-
function drawGeometry(context, canvas, geometry,
|
|
4242
|
-
const view = viewMatrix(
|
|
4243
|
-
const projection = projectionMatrix(
|
|
4241
|
+
function drawGeometry(context, canvas, geometry, options2) {
|
|
4242
|
+
const view = viewMatrix(options2.camera);
|
|
4243
|
+
const projection = projectionMatrix(options2.camera);
|
|
4244
4244
|
const position = geometry.point[POSITION_ATTRIBUTE];
|
|
4245
4245
|
if (!position || position.storage === "string") return;
|
|
4246
4246
|
const size = position.size;
|
|
@@ -4265,15 +4265,15 @@ function drawGeometry(context, canvas, geometry, options) {
|
|
|
4265
4265
|
const widths = numericAttribute(geometry.primitive.width, "primitive.width", [1]);
|
|
4266
4266
|
context.lineCap = "round";
|
|
4267
4267
|
context.lineJoin = "round";
|
|
4268
|
-
context.globalAlpha =
|
|
4268
|
+
context.globalAlpha = options2.opacity;
|
|
4269
4269
|
const { vertexPoints, offsets, closed } = geometry.topology;
|
|
4270
4270
|
const drawn = /* @__PURE__ */ new Set();
|
|
4271
4271
|
for (let primitive = 0; primitive < geometry.primitiveCount; primitive += 1) {
|
|
4272
4272
|
const from = offsets[primitive];
|
|
4273
4273
|
const to = offsets[primitive + 1];
|
|
4274
4274
|
if (to - from < 2) continue;
|
|
4275
|
-
context.strokeStyle = colours ? css(readElement(colours, primitive)) : css(
|
|
4276
|
-
context.lineWidth = widths ? readElement(widths, primitive)[0] :
|
|
4275
|
+
context.strokeStyle = colours ? css(readElement(colours, primitive)) : css(options2.stroke);
|
|
4276
|
+
context.lineWidth = widths ? readElement(widths, primitive)[0] : options2.strokeWidth;
|
|
4277
4277
|
context.beginPath();
|
|
4278
4278
|
let open = false;
|
|
4279
4279
|
for (let vertex = from; vertex < to; vertex += 1) {
|
|
@@ -4296,14 +4296,14 @@ function drawGeometry(context, canvas, geometry, options) {
|
|
|
4296
4296
|
}
|
|
4297
4297
|
context.stroke();
|
|
4298
4298
|
}
|
|
4299
|
-
if (
|
|
4300
|
-
context.fillStyle = css(
|
|
4299
|
+
if (options2.drawPoints && options2.pointRadius > 0) {
|
|
4300
|
+
context.fillStyle = css(options2.stroke);
|
|
4301
4301
|
for (let index = 0; index < projected.length; index += 1) {
|
|
4302
4302
|
if (drawn.has(index)) continue;
|
|
4303
4303
|
const at = projected[index];
|
|
4304
4304
|
if (at.w <= 0) continue;
|
|
4305
4305
|
context.beginPath();
|
|
4306
|
-
context.arc(at.x, at.y,
|
|
4306
|
+
context.arc(at.x, at.y, options2.pointRadius, 0, Math.PI * 2);
|
|
4307
4307
|
context.fill();
|
|
4308
4308
|
}
|
|
4309
4309
|
}
|
|
@@ -4485,17 +4485,300 @@ var init_geo = __esm({
|
|
|
4485
4485
|
svgExportRegistration
|
|
4486
4486
|
]);
|
|
4487
4487
|
registrationsById2 = new Map(
|
|
4488
|
-
geoNodeRegistrations.map((
|
|
4489
|
-
|
|
4490
|
-
|
|
4488
|
+
geoNodeRegistrations.map((registration2) => [
|
|
4489
|
+
registration2.moduleId,
|
|
4490
|
+
registration2
|
|
4491
4491
|
])
|
|
4492
4492
|
);
|
|
4493
4493
|
}
|
|
4494
4494
|
});
|
|
4495
4495
|
|
|
4496
|
+
// packages/runtime/src/builtins/math/definitions.ts
|
|
4497
|
+
function asComponents(value, label2) {
|
|
4498
|
+
if (typeof value === "number") return [value];
|
|
4499
|
+
if (Array.isArray(value) && value.every((part) => typeof part === "number"))
|
|
4500
|
+
return value;
|
|
4501
|
+
if (value === void 0 || value === null) return [0];
|
|
4502
|
+
throw new Error(
|
|
4503
|
+
`${label2} needs a number or a vector of numbers, and got ${describe(value)}`
|
|
4504
|
+
);
|
|
4505
|
+
}
|
|
4506
|
+
function describe(value) {
|
|
4507
|
+
if (Array.isArray(value)) return `an array of ${value.length}`;
|
|
4508
|
+
return `a ${typeof value}`;
|
|
4509
|
+
}
|
|
4510
|
+
function combine(left, right, operate) {
|
|
4511
|
+
const a = asComponents(left, "the first input");
|
|
4512
|
+
const b = asComponents(right, "the second input");
|
|
4513
|
+
if (a.length !== b.length && a.length !== 1 && b.length !== 1)
|
|
4514
|
+
throw new Error(
|
|
4515
|
+
`cannot combine a vector of ${a.length} with a vector of ${b.length}`
|
|
4516
|
+
);
|
|
4517
|
+
const width = Math.max(a.length, b.length);
|
|
4518
|
+
const out = [];
|
|
4519
|
+
for (let index = 0; index < width; index += 1)
|
|
4520
|
+
out.push(operate(a[a.length === 1 ? 0 : index], b[b.length === 1 ? 0 : index]));
|
|
4521
|
+
return width === 1 ? out[0] : out;
|
|
4522
|
+
}
|
|
4523
|
+
function map(value, operate) {
|
|
4524
|
+
const components = asComponents(value, "the input");
|
|
4525
|
+
const out = components.map(operate);
|
|
4526
|
+
return out.length === 1 ? out[0] : out;
|
|
4527
|
+
}
|
|
4528
|
+
function divide(a, b) {
|
|
4529
|
+
return b === 0 ? 0 : a / b;
|
|
4530
|
+
}
|
|
4531
|
+
function options(table) {
|
|
4532
|
+
return Object.keys(table).map((value) => ({ value, label: label(value) }));
|
|
4533
|
+
}
|
|
4534
|
+
function label(value) {
|
|
4535
|
+
return value.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
4536
|
+
}
|
|
4537
|
+
function executeBinary(context) {
|
|
4538
|
+
const operate = BINARY[context.props.operation];
|
|
4539
|
+
if (!operate)
|
|
4540
|
+
throw new Error(
|
|
4541
|
+
`cascade.math.Binary has no operation "${context.props.operation}"`
|
|
4542
|
+
);
|
|
4543
|
+
context.outputs.value.set(combine(context.inputs.a, context.inputs.b, operate));
|
|
4544
|
+
}
|
|
4545
|
+
function executeUnary(context) {
|
|
4546
|
+
const operate = UNARY[context.props.operation];
|
|
4547
|
+
if (!operate)
|
|
4548
|
+
throw new Error(
|
|
4549
|
+
`cascade.math.Unary has no operation "${context.props.operation}"`
|
|
4550
|
+
);
|
|
4551
|
+
context.outputs.value.set(map(context.inputs.value, operate));
|
|
4552
|
+
}
|
|
4553
|
+
function executeClamp(context) {
|
|
4554
|
+
const lower = combine(context.inputs.value, context.inputs.min, Math.max);
|
|
4555
|
+
context.outputs.value.set(combine(lower, context.inputs.max, Math.min));
|
|
4556
|
+
}
|
|
4557
|
+
function executeMix(context) {
|
|
4558
|
+
const bias = context.inputs.bias ?? 0.5;
|
|
4559
|
+
const delta = combine(context.inputs.b, context.inputs.a, (b, a) => b - a);
|
|
4560
|
+
context.outputs.value.set(
|
|
4561
|
+
combine(context.inputs.a, delta, (a, d) => a + d * bias)
|
|
4562
|
+
);
|
|
4563
|
+
}
|
|
4564
|
+
function executeCompare(context) {
|
|
4565
|
+
const operation = context.props.operation;
|
|
4566
|
+
const test = COMPARE[operation];
|
|
4567
|
+
if (!test)
|
|
4568
|
+
throw new Error(`cascade.math.Compare has no test "${context.props.operation}"`);
|
|
4569
|
+
const a = context.inputs.a ?? 0;
|
|
4570
|
+
const b = context.inputs.b ?? 0;
|
|
4571
|
+
const tolerance = context.props.tolerance;
|
|
4572
|
+
if (tolerance > 0 && (operation === "equal" || operation === "not-equal")) {
|
|
4573
|
+
const near = Math.abs(a - b) <= tolerance;
|
|
4574
|
+
context.outputs.result.set(operation === "equal" ? near : !near);
|
|
4575
|
+
return;
|
|
4576
|
+
}
|
|
4577
|
+
context.outputs.result.set(test(a, b));
|
|
4578
|
+
}
|
|
4579
|
+
function registration(name, definition, execute2) {
|
|
4580
|
+
return {
|
|
4581
|
+
kind: "definition-v1",
|
|
4582
|
+
moduleId: `cascade.math.${name}`,
|
|
4583
|
+
definition,
|
|
4584
|
+
loadExecute: async () => execute2
|
|
4585
|
+
};
|
|
4586
|
+
}
|
|
4587
|
+
var BINARY, DEG2, UNARY, COMPARE, binaryDefinition, unaryDefinition, clampDefinition, mixDefinition, compareDefinition, binaryRegistration, unaryRegistration, clampRegistration, mixRegistration, compareRegistration, mathNodeRegistrations, mathNodeDefinitions;
|
|
4588
|
+
var init_definitions2 = __esm({
|
|
4589
|
+
"packages/runtime/src/builtins/math/definitions.ts"() {
|
|
4590
|
+
"use strict";
|
|
4591
|
+
BINARY = {
|
|
4592
|
+
add: (a, b) => a + b,
|
|
4593
|
+
subtract: (a, b) => a - b,
|
|
4594
|
+
multiply: (a, b) => a * b,
|
|
4595
|
+
divide,
|
|
4596
|
+
power: (a, b) => a ** b,
|
|
4597
|
+
modulo: (a, b) => b === 0 ? 0 : a % b,
|
|
4598
|
+
min: (a, b) => Math.min(a, b),
|
|
4599
|
+
max: (a, b) => Math.max(a, b),
|
|
4600
|
+
atan2: (a, b) => Math.atan2(a, b)
|
|
4601
|
+
};
|
|
4602
|
+
DEG2 = Math.PI / 180;
|
|
4603
|
+
UNARY = {
|
|
4604
|
+
abs: Math.abs,
|
|
4605
|
+
negate: (a) => -a,
|
|
4606
|
+
floor: Math.floor,
|
|
4607
|
+
ceil: Math.ceil,
|
|
4608
|
+
round: Math.round,
|
|
4609
|
+
sqrt: (a) => a < 0 ? 0 : Math.sqrt(a),
|
|
4610
|
+
sign: Math.sign,
|
|
4611
|
+
// Trigonometry in RADIANS, matching the expression engine, where bare `sin`
|
|
4612
|
+
// is radians too. `radians` and `degrees` are here for the conversion, and
|
|
4613
|
+
// the divergence from `Transform`'s degrees is recorded in AGENTS.md.
|
|
4614
|
+
sin: Math.sin,
|
|
4615
|
+
cos: Math.cos,
|
|
4616
|
+
tan: Math.tan,
|
|
4617
|
+
asin: (a) => Math.asin(Math.max(-1, Math.min(1, a))),
|
|
4618
|
+
acos: (a) => Math.acos(Math.max(-1, Math.min(1, a))),
|
|
4619
|
+
exp: Math.exp,
|
|
4620
|
+
log: (a) => a <= 0 ? 0 : Math.log(a),
|
|
4621
|
+
radians: (a) => a * DEG2,
|
|
4622
|
+
degrees: (a) => a / DEG2,
|
|
4623
|
+
/** The fractional part, always positive — `fract(-0.25)` is `0.75`, which is
|
|
4624
|
+
* what a repeating pattern wants and what GLSL's `fract` does. */
|
|
4625
|
+
fract: (a) => a - Math.floor(a)
|
|
4626
|
+
};
|
|
4627
|
+
COMPARE = {
|
|
4628
|
+
greater: (a, b) => a > b,
|
|
4629
|
+
"greater-or-equal": (a, b) => a >= b,
|
|
4630
|
+
less: (a, b) => a < b,
|
|
4631
|
+
"less-or-equal": (a, b) => a <= b,
|
|
4632
|
+
equal: (a, b) => a === b,
|
|
4633
|
+
"not-equal": (a, b) => a !== b
|
|
4634
|
+
};
|
|
4635
|
+
binaryDefinition = {
|
|
4636
|
+
apiVersion: 1,
|
|
4637
|
+
label: "Binary Math",
|
|
4638
|
+
description: "Two values, one operation. Component-wise, and a scalar broadcasts against a vector.",
|
|
4639
|
+
icon: "Plus",
|
|
4640
|
+
runsOn: "portable",
|
|
4641
|
+
inputs: {
|
|
4642
|
+
a: { kind: "data", type: "any", default: 0, description: "First value." },
|
|
4643
|
+
b: { kind: "data", type: "any", default: 0, description: "Second value." }
|
|
4644
|
+
},
|
|
4645
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
4646
|
+
props: {
|
|
4647
|
+
operation: {
|
|
4648
|
+
type: "string",
|
|
4649
|
+
default: "add",
|
|
4650
|
+
control: "select",
|
|
4651
|
+
options: options(BINARY),
|
|
4652
|
+
label: "Operation"
|
|
4653
|
+
}
|
|
4654
|
+
}
|
|
4655
|
+
};
|
|
4656
|
+
unaryDefinition = {
|
|
4657
|
+
apiVersion: 1,
|
|
4658
|
+
label: "Unary Math",
|
|
4659
|
+
description: "One value, one operation. Trigonometry is in radians.",
|
|
4660
|
+
icon: "FunctionSquare",
|
|
4661
|
+
runsOn: "portable",
|
|
4662
|
+
inputs: {
|
|
4663
|
+
value: { kind: "data", type: "any", default: 0 }
|
|
4664
|
+
},
|
|
4665
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
4666
|
+
props: {
|
|
4667
|
+
operation: {
|
|
4668
|
+
type: "string",
|
|
4669
|
+
default: "abs",
|
|
4670
|
+
control: "select",
|
|
4671
|
+
options: options(UNARY),
|
|
4672
|
+
label: "Operation"
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4675
|
+
};
|
|
4676
|
+
clampDefinition = {
|
|
4677
|
+
apiVersion: 1,
|
|
4678
|
+
label: "Clamp",
|
|
4679
|
+
description: "Hold a value between two bounds.",
|
|
4680
|
+
icon: "Brackets",
|
|
4681
|
+
runsOn: "portable",
|
|
4682
|
+
inputs: {
|
|
4683
|
+
value: { kind: "data", type: "any", default: 0 },
|
|
4684
|
+
min: { kind: "data", type: "any", default: 0 },
|
|
4685
|
+
max: { kind: "data", type: "any", default: 1 }
|
|
4686
|
+
},
|
|
4687
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
4688
|
+
props: {}
|
|
4689
|
+
};
|
|
4690
|
+
mixDefinition = {
|
|
4691
|
+
apiVersion: 1,
|
|
4692
|
+
label: "Mix",
|
|
4693
|
+
description: "Blend between two values. Houdini's lerp.",
|
|
4694
|
+
icon: "Blend",
|
|
4695
|
+
runsOn: "portable",
|
|
4696
|
+
inputs: {
|
|
4697
|
+
a: { kind: "data", type: "any", default: 0, description: "The value at 0." },
|
|
4698
|
+
b: { kind: "data", type: "any", default: 1, description: "The value at 1." },
|
|
4699
|
+
bias: {
|
|
4700
|
+
kind: "data",
|
|
4701
|
+
type: "float",
|
|
4702
|
+
default: 0.5,
|
|
4703
|
+
min: 0,
|
|
4704
|
+
max: 1,
|
|
4705
|
+
step: 0.01,
|
|
4706
|
+
description: "Not clamped: past 0..1 this extrapolates, which is useful."
|
|
4707
|
+
}
|
|
4708
|
+
},
|
|
4709
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
4710
|
+
props: {}
|
|
4711
|
+
};
|
|
4712
|
+
compareDefinition = {
|
|
4713
|
+
apiVersion: 1,
|
|
4714
|
+
label: "Compare",
|
|
4715
|
+
description: "Test two values. Outputs a bool, for a Switch.",
|
|
4716
|
+
icon: "Equal",
|
|
4717
|
+
runsOn: "portable",
|
|
4718
|
+
inputs: {
|
|
4719
|
+
a: { kind: "data", type: "float", default: 0 },
|
|
4720
|
+
b: { kind: "data", type: "float", default: 0 }
|
|
4721
|
+
},
|
|
4722
|
+
outputs: { result: { kind: "data", type: "bool" } },
|
|
4723
|
+
props: {
|
|
4724
|
+
operation: {
|
|
4725
|
+
type: "string",
|
|
4726
|
+
default: "greater",
|
|
4727
|
+
control: "select",
|
|
4728
|
+
options: options(COMPARE),
|
|
4729
|
+
label: "Test"
|
|
4730
|
+
},
|
|
4731
|
+
/**
|
|
4732
|
+
* Scalars only, unlike the rest of this namespace.
|
|
4733
|
+
*
|
|
4734
|
+
* "Is this vector greater than that one" has no single right answer — all
|
|
4735
|
+
* components, any component, or the length — and a node that picked one
|
|
4736
|
+
* silently would be wrong for the other two readings. A comparison feeding
|
|
4737
|
+
* a `Switch` wants one boolean, so the input is a `float` and the question
|
|
4738
|
+
* does not arise.
|
|
4739
|
+
*/
|
|
4740
|
+
tolerance: {
|
|
4741
|
+
type: "float",
|
|
4742
|
+
default: 0,
|
|
4743
|
+
min: 0,
|
|
4744
|
+
label: "Tolerance",
|
|
4745
|
+
description: "Slack for Equal and Not Equal. Floating point rarely lands on exactly equal."
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
};
|
|
4749
|
+
binaryRegistration = registration("Binary", binaryDefinition, executeBinary);
|
|
4750
|
+
unaryRegistration = registration("Unary", unaryDefinition, executeUnary);
|
|
4751
|
+
clampRegistration = registration("Clamp", clampDefinition, executeClamp);
|
|
4752
|
+
mixRegistration = registration("Mix", mixDefinition, executeMix);
|
|
4753
|
+
compareRegistration = registration("Compare", compareDefinition, executeCompare);
|
|
4754
|
+
mathNodeRegistrations = Object.freeze([
|
|
4755
|
+
binaryRegistration,
|
|
4756
|
+
unaryRegistration,
|
|
4757
|
+
clampRegistration,
|
|
4758
|
+
mixRegistration,
|
|
4759
|
+
compareRegistration
|
|
4760
|
+
]);
|
|
4761
|
+
mathNodeDefinitions = Object.freeze([
|
|
4762
|
+
["cascade.math.Binary", binaryDefinition],
|
|
4763
|
+
["cascade.math.Unary", unaryDefinition],
|
|
4764
|
+
["cascade.math.Clamp", clampDefinition],
|
|
4765
|
+
["cascade.math.Mix", mixDefinition],
|
|
4766
|
+
["cascade.math.Compare", compareDefinition]
|
|
4767
|
+
]);
|
|
4768
|
+
}
|
|
4769
|
+
});
|
|
4770
|
+
|
|
4771
|
+
// packages/runtime/src/builtins/math/index.ts
|
|
4772
|
+
var init_math2 = __esm({
|
|
4773
|
+
"packages/runtime/src/builtins/math/index.ts"() {
|
|
4774
|
+
"use strict";
|
|
4775
|
+
init_definitions2();
|
|
4776
|
+
}
|
|
4777
|
+
});
|
|
4778
|
+
|
|
4496
4779
|
// packages/runtime/src/pop/state.ts
|
|
4497
|
-
function step(state, forces,
|
|
4498
|
-
const { timestep, maxSpeed = 0, wrap } =
|
|
4780
|
+
function step(state, forces, options2) {
|
|
4781
|
+
const { timestep, maxSpeed = 0, wrap } = options2;
|
|
4499
4782
|
const { count, size } = state;
|
|
4500
4783
|
if (count === 0) return state;
|
|
4501
4784
|
const acceleration = new Float32Array(count * size);
|
|
@@ -4856,8 +5139,8 @@ function drag(airresist) {
|
|
|
4856
5139
|
}
|
|
4857
5140
|
};
|
|
4858
5141
|
}
|
|
4859
|
-
function noiseField(
|
|
4860
|
-
const { seed, frequency, amplitude, evolve = 0 } =
|
|
5142
|
+
function noiseField(options2) {
|
|
5143
|
+
const { seed, frequency, amplitude, evolve = 0 } = options2;
|
|
4861
5144
|
return {
|
|
4862
5145
|
label: "noiseField",
|
|
4863
5146
|
accelerate(state, size) {
|
|
@@ -4873,8 +5156,8 @@ function noiseField(options) {
|
|
|
4873
5156
|
}
|
|
4874
5157
|
};
|
|
4875
5158
|
}
|
|
4876
|
-
function separation(
|
|
4877
|
-
const { radius, strength } =
|
|
5159
|
+
function separation(options2) {
|
|
5160
|
+
const { radius, strength } = options2;
|
|
4878
5161
|
return {
|
|
4879
5162
|
label: "separation",
|
|
4880
5163
|
accelerate(state, size) {
|
|
@@ -4945,8 +5228,8 @@ function hash(seed, x, y, z) {
|
|
|
4945
5228
|
const n = Math.sin(seed * 12.9898 + x * 78.233 + y * 37.719 + z * 19.371) * 43758.5453;
|
|
4946
5229
|
return n - Math.floor(n);
|
|
4947
5230
|
}
|
|
4948
|
-
function attract(
|
|
4949
|
-
const { targets, targetSize, targetCount, amplitude, radius } =
|
|
5231
|
+
function attract(options2) {
|
|
5232
|
+
const { targets, targetSize, targetCount, amplitude, radius } = options2;
|
|
4950
5233
|
const cell = radius > 0 ? radius : 0;
|
|
4951
5234
|
const buckets = /* @__PURE__ */ new Map();
|
|
4952
5235
|
if (cell > 0) {
|
|
@@ -5008,7 +5291,7 @@ function attract(options) {
|
|
|
5008
5291
|
function bucketKey(x, y, cell) {
|
|
5009
5292
|
return `${Math.floor(x / cell)}:${Math.floor(y / cell)}`;
|
|
5010
5293
|
}
|
|
5011
|
-
function flowField(
|
|
5294
|
+
function flowField(options2) {
|
|
5012
5295
|
const {
|
|
5013
5296
|
positions,
|
|
5014
5297
|
positionSize: positionSize2,
|
|
@@ -5020,7 +5303,7 @@ function flowField(options) {
|
|
|
5020
5303
|
radius,
|
|
5021
5304
|
level = 0,
|
|
5022
5305
|
hold = 0
|
|
5023
|
-
} =
|
|
5306
|
+
} = options2;
|
|
5024
5307
|
const cell = radius > 0 ? radius : 1;
|
|
5025
5308
|
const buckets = /* @__PURE__ */ new Map();
|
|
5026
5309
|
for (let sample = 0; sample < count; sample += 1) {
|
|
@@ -5135,8 +5418,8 @@ function trailFrame(geometry) {
|
|
|
5135
5418
|
size: position.size
|
|
5136
5419
|
};
|
|
5137
5420
|
}
|
|
5138
|
-
function buildTrails(history, current,
|
|
5139
|
-
const { result = "polylines", length = 12, increment = 1, velocityscale = 1 } =
|
|
5421
|
+
function buildTrails(history, current, options2 = {}) {
|
|
5422
|
+
const { result = "polylines", length = 12, increment = 1, velocityscale = 1 } = options2;
|
|
5140
5423
|
if (result === "preserve") return current;
|
|
5141
5424
|
const frames = sampled(history, length, increment);
|
|
5142
5425
|
const size = frames[0]?.size ?? 2;
|
|
@@ -5552,7 +5835,7 @@ function executeSimulate(context) {
|
|
|
5552
5835
|
);
|
|
5553
5836
|
}
|
|
5554
5837
|
var sourceDefinition, solverDefinition, noiseForceDefinition, separateDefinition, fieldForceDefinition, trailDefinition, simulateDefinition, simulateRegistration, sourceRegistration, solverRegistration, noiseForceRegistration, separateRegistration, fieldForceRegistration, trailRegistration, popNodeRegistrations, popNodeDefinitions;
|
|
5555
|
-
var
|
|
5838
|
+
var init_definitions3 = __esm({
|
|
5556
5839
|
"packages/runtime/src/builtins/pop/definitions.ts"() {
|
|
5557
5840
|
"use strict";
|
|
5558
5841
|
init_src();
|
|
@@ -5945,7 +6228,7 @@ var init_definitions2 = __esm({
|
|
|
5945
6228
|
var init_pop2 = __esm({
|
|
5946
6229
|
"packages/runtime/src/builtins/pop/index.ts"() {
|
|
5947
6230
|
"use strict";
|
|
5948
|
-
|
|
6231
|
+
init_definitions3();
|
|
5949
6232
|
}
|
|
5950
6233
|
});
|
|
5951
6234
|
|
|
@@ -5991,12 +6274,12 @@ function executeScene(context) {
|
|
|
5991
6274
|
return;
|
|
5992
6275
|
}
|
|
5993
6276
|
throw new Error(
|
|
5994
|
-
`cascade.scene.Scene input ${index} is not geometry, a camera, a light or a scene (received ${
|
|
6277
|
+
`cascade.scene.Scene input ${index} is not geometry, a camera, a light or a scene (received ${describe2(value)}). A scene can only hold those.`
|
|
5995
6278
|
);
|
|
5996
6279
|
});
|
|
5997
6280
|
context.outputs.scene.set({ geometry, camera, lights });
|
|
5998
6281
|
}
|
|
5999
|
-
function
|
|
6282
|
+
function describe2(value) {
|
|
6000
6283
|
if (Array.isArray(value)) return `an array of ${value.length}`;
|
|
6001
6284
|
if (typeof value === "object" && value !== null) {
|
|
6002
6285
|
const kind = value.kind;
|
|
@@ -6016,7 +6299,7 @@ function executeLight(context) {
|
|
|
6016
6299
|
});
|
|
6017
6300
|
}
|
|
6018
6301
|
var SCENE_NAMESPACE, sceneDefinition, lightDefinition, sceneRegistration, lightRegistration, sceneNodeRegistrations, sceneNodeDefinitions;
|
|
6019
|
-
var
|
|
6302
|
+
var init_definitions4 = __esm({
|
|
6020
6303
|
"packages/runtime/src/builtins/scene/definitions.ts"() {
|
|
6021
6304
|
"use strict";
|
|
6022
6305
|
init_src();
|
|
@@ -6124,7 +6407,7 @@ var init_definitions3 = __esm({
|
|
|
6124
6407
|
var init_scene3 = __esm({
|
|
6125
6408
|
"packages/runtime/src/builtins/scene/index.ts"() {
|
|
6126
6409
|
"use strict";
|
|
6127
|
-
|
|
6410
|
+
init_definitions4();
|
|
6128
6411
|
}
|
|
6129
6412
|
});
|
|
6130
6413
|
|
|
@@ -6138,36 +6421,38 @@ var init_builtins = __esm({
|
|
|
6138
6421
|
"use strict";
|
|
6139
6422
|
init_core();
|
|
6140
6423
|
init_geo();
|
|
6424
|
+
init_math2();
|
|
6141
6425
|
init_pop2();
|
|
6142
6426
|
init_scene3();
|
|
6143
6427
|
builtinNodeRegistrations = Object.freeze([
|
|
6144
6428
|
...coreNodeRegistrations,
|
|
6145
6429
|
...geoNodeRegistrations,
|
|
6430
|
+
...mathNodeRegistrations,
|
|
6146
6431
|
...popNodeRegistrations,
|
|
6147
6432
|
...sceneNodeRegistrations
|
|
6148
6433
|
]);
|
|
6149
6434
|
registrationsById3 = new Map(
|
|
6150
|
-
builtinNodeRegistrations.map((
|
|
6151
|
-
|
|
6152
|
-
|
|
6435
|
+
builtinNodeRegistrations.map((registration2) => [
|
|
6436
|
+
registration2.moduleId,
|
|
6437
|
+
registration2
|
|
6153
6438
|
])
|
|
6154
6439
|
);
|
|
6155
6440
|
}
|
|
6156
6441
|
});
|
|
6157
6442
|
|
|
6158
6443
|
// packages/runtime/src/runtime.ts
|
|
6159
|
-
function createRuntime(
|
|
6160
|
-
return new Runtime(
|
|
6444
|
+
function createRuntime(options2) {
|
|
6445
|
+
return new Runtime(options2.host, [...builtinNodeRegistrations, ...options2.nodes ?? []]);
|
|
6161
6446
|
}
|
|
6162
6447
|
function bindShellToRun(shell, runSignal) {
|
|
6163
6448
|
if (!shell) return void 0;
|
|
6164
|
-
const
|
|
6449
|
+
const options2 = (value) => ({
|
|
6165
6450
|
...value,
|
|
6166
6451
|
signal: combineAbortSignals(runSignal, value?.signal)
|
|
6167
6452
|
});
|
|
6168
6453
|
return Object.freeze({
|
|
6169
|
-
run: (command, args, value) => shell.run(command, args,
|
|
6170
|
-
runJson: (command, args, value) => shell.runJson(command, args,
|
|
6454
|
+
run: (command, args, value) => shell.run(command, args, options2(value)),
|
|
6455
|
+
runJson: (command, args, value) => shell.runJson(command, args, options2(value))
|
|
6171
6456
|
});
|
|
6172
6457
|
}
|
|
6173
6458
|
function combineAbortSignals(first, second) {
|
|
@@ -6180,7 +6465,7 @@ function combineAbortSignals(first, second) {
|
|
|
6180
6465
|
get reason() {
|
|
6181
6466
|
return first.aborted ? first.reason : second.reason;
|
|
6182
6467
|
},
|
|
6183
|
-
addEventListener(_type, listener,
|
|
6468
|
+
addEventListener(_type, listener, options2) {
|
|
6184
6469
|
if (first.aborted || second.aborted) {
|
|
6185
6470
|
listener();
|
|
6186
6471
|
return;
|
|
@@ -6192,8 +6477,8 @@ function combineAbortSignals(first, second) {
|
|
|
6192
6477
|
listener();
|
|
6193
6478
|
};
|
|
6194
6479
|
wrappers.set(listener, wrapped);
|
|
6195
|
-
first.addEventListener("abort", wrapped,
|
|
6196
|
-
second.addEventListener("abort", wrapped,
|
|
6480
|
+
first.addEventListener("abort", wrapped, options2);
|
|
6481
|
+
second.addEventListener("abort", wrapped, options2);
|
|
6197
6482
|
},
|
|
6198
6483
|
removeEventListener(_type, listener) {
|
|
6199
6484
|
const wrapped = wrappers.get(listener);
|
|
@@ -6204,11 +6489,11 @@ function combineAbortSignals(first, second) {
|
|
|
6204
6489
|
}
|
|
6205
6490
|
};
|
|
6206
6491
|
}
|
|
6207
|
-
function materialize(authored,
|
|
6492
|
+
function materialize(authored, registration2) {
|
|
6208
6493
|
const inputs = {};
|
|
6209
6494
|
const props = {};
|
|
6210
6495
|
for (const [name, definition] of Object.entries(
|
|
6211
|
-
|
|
6496
|
+
registration2.definition.inputs ?? {}
|
|
6212
6497
|
))
|
|
6213
6498
|
if (definition.kind === "data" && "default" in definition)
|
|
6214
6499
|
inputs[name] = runtimeValue(
|
|
@@ -6219,7 +6504,7 @@ function materialize(authored, registration) {
|
|
|
6219
6504
|
);
|
|
6220
6505
|
if (Array.isArray(authored.inputs))
|
|
6221
6506
|
for (const saved of authored.inputs) {
|
|
6222
|
-
const definition =
|
|
6507
|
+
const definition = registration2.definition.inputs?.[saved.name];
|
|
6223
6508
|
if (definition?.kind === "data") {
|
|
6224
6509
|
inputs[saved.name] = runtimeValue(
|
|
6225
6510
|
"defaultValue" in saved ? saved.defaultValue : saved.value,
|
|
@@ -6231,7 +6516,7 @@ function materialize(authored, registration) {
|
|
|
6231
6516
|
}
|
|
6232
6517
|
else if (authored.inputs)
|
|
6233
6518
|
for (const [name, saved] of Object.entries(authored.inputs)) {
|
|
6234
|
-
const definition =
|
|
6519
|
+
const definition = registration2.definition.inputs?.[name];
|
|
6235
6520
|
if (definition?.kind === "data")
|
|
6236
6521
|
inputs[name] = runtimeValue(
|
|
6237
6522
|
saved,
|
|
@@ -6241,7 +6526,7 @@ function materialize(authored, registration) {
|
|
|
6241
6526
|
);
|
|
6242
6527
|
}
|
|
6243
6528
|
for (const [name, definition] of Object.entries(
|
|
6244
|
-
|
|
6529
|
+
registration2.definition.props ?? {}
|
|
6245
6530
|
))
|
|
6246
6531
|
props[name] = runtimeValue(
|
|
6247
6532
|
definition.default,
|
|
@@ -6257,7 +6542,7 @@ function materialize(authored, registration) {
|
|
|
6257
6542
|
const bindings = {};
|
|
6258
6543
|
const storedProps = authored.props ?? {};
|
|
6259
6544
|
for (const [name, definition] of Object.entries(
|
|
6260
|
-
|
|
6545
|
+
registration2.definition.props ?? {}
|
|
6261
6546
|
)) {
|
|
6262
6547
|
if (!definition.expression || name in storedProps) continue;
|
|
6263
6548
|
bindings[name] = {
|
|
@@ -6266,7 +6551,7 @@ function materialize(authored, registration) {
|
|
|
6266
6551
|
};
|
|
6267
6552
|
}
|
|
6268
6553
|
for (const [name, saved] of Object.entries(storedProps)) {
|
|
6269
|
-
const definition =
|
|
6554
|
+
const definition = registration2.definition.props?.[name];
|
|
6270
6555
|
if (!definition) continue;
|
|
6271
6556
|
const object = saved && typeof saved === "object" && "value" in saved ? saved : null;
|
|
6272
6557
|
const value = runtimeValue(
|
|
@@ -6291,26 +6576,26 @@ function materialize(authored, registration) {
|
|
|
6291
6576
|
}
|
|
6292
6577
|
return {
|
|
6293
6578
|
id: authored.id,
|
|
6294
|
-
moduleId:
|
|
6579
|
+
moduleId: registration2.moduleId,
|
|
6295
6580
|
...authored.parent ? { parent: authored.parent } : {},
|
|
6296
|
-
registration,
|
|
6297
|
-
definition:
|
|
6581
|
+
registration: registration2,
|
|
6582
|
+
definition: registration2.definition,
|
|
6298
6583
|
inputs,
|
|
6299
6584
|
props,
|
|
6300
6585
|
bindings,
|
|
6301
|
-
strayParams: strayParams(authored,
|
|
6302
|
-
unknownProps: unknownProps(authored,
|
|
6586
|
+
strayParams: strayParams(authored, registration2),
|
|
6587
|
+
unknownProps: unknownProps(authored, registration2),
|
|
6303
6588
|
outputs: /* @__PURE__ */ new Map()
|
|
6304
6589
|
};
|
|
6305
6590
|
}
|
|
6306
|
-
function unknownProps(authored,
|
|
6591
|
+
function unknownProps(authored, registration2) {
|
|
6307
6592
|
const props = authored.props;
|
|
6308
6593
|
if (!props || Array.isArray(props)) return [];
|
|
6309
|
-
const declared =
|
|
6594
|
+
const declared = registration2.definition.props ?? {};
|
|
6310
6595
|
return Object.keys(props).filter((name) => !(name in declared));
|
|
6311
6596
|
}
|
|
6312
|
-
function strayParams(authored,
|
|
6313
|
-
const definition =
|
|
6597
|
+
function strayParams(authored, registration2) {
|
|
6598
|
+
const definition = registration2.definition;
|
|
6314
6599
|
const declared = /* @__PURE__ */ new Set([
|
|
6315
6600
|
...Object.keys(definition.props ?? {}),
|
|
6316
6601
|
...Object.keys(definition.inputs ?? {})
|
|
@@ -6320,14 +6605,14 @@ function strayParams(authored, registration) {
|
|
|
6320
6605
|
(name) => typeof name === "string" && declared.has(name)
|
|
6321
6606
|
);
|
|
6322
6607
|
}
|
|
6323
|
-
function specializeCoreRegistration(
|
|
6324
|
-
if (
|
|
6608
|
+
function specializeCoreRegistration(registration2, authored, nodes) {
|
|
6609
|
+
if (registration2.moduleId === "cascade.core.Input" || registration2.moduleId === "cascade.core.Output") {
|
|
6325
6610
|
const type = savedDataType(authored.props?.dataType);
|
|
6326
|
-
const inputName2 =
|
|
6611
|
+
const inputName2 = registration2.moduleId === "cascade.core.Input" ? "value" : "input";
|
|
6327
6612
|
return Object.freeze({
|
|
6328
|
-
...
|
|
6613
|
+
...registration2,
|
|
6329
6614
|
definition: Object.freeze({
|
|
6330
|
-
...
|
|
6615
|
+
...registration2.definition,
|
|
6331
6616
|
inputs: Object.freeze({
|
|
6332
6617
|
[inputName2]: dataInputDefinition(type)
|
|
6333
6618
|
}),
|
|
@@ -6337,14 +6622,14 @@ function specializeCoreRegistration(registration, authored, nodes) {
|
|
|
6337
6622
|
})
|
|
6338
6623
|
});
|
|
6339
6624
|
}
|
|
6340
|
-
if (
|
|
6625
|
+
if (registration2.moduleId !== "cascade.core.Subnet") return registration2;
|
|
6341
6626
|
const children = nodes.filter((candidate) => candidate.parent === authored.id);
|
|
6342
6627
|
const inputs = indexedBoundaryPorts(children, "cascade.core.Input", "inputIndex", "input");
|
|
6343
6628
|
const outputs = indexedBoundaryPorts(children, "cascade.core.Output", "outputIndex", "output");
|
|
6344
6629
|
return Object.freeze({
|
|
6345
|
-
...
|
|
6630
|
+
...registration2,
|
|
6346
6631
|
definition: Object.freeze({
|
|
6347
|
-
...
|
|
6632
|
+
...registration2.definition,
|
|
6348
6633
|
...Object.keys(inputs).length ? { inputs: Object.freeze(inputs) } : {},
|
|
6349
6634
|
...Object.keys(outputs).length ? { outputs: Object.freeze(outputs) } : {}
|
|
6350
6635
|
})
|
|
@@ -6516,11 +6801,11 @@ function validateHierarchy(nodes, byId) {
|
|
|
6516
6801
|
}
|
|
6517
6802
|
}
|
|
6518
6803
|
}
|
|
6519
|
-
function snapshotRegistration(
|
|
6520
|
-
if (
|
|
6521
|
-
return Object.freeze({ ...
|
|
6522
|
-
const definition = snapshot(
|
|
6523
|
-
return Object.freeze({ ...
|
|
6804
|
+
function snapshotRegistration(registration2) {
|
|
6805
|
+
if (registration2.kind === "legacy-dynamic")
|
|
6806
|
+
return Object.freeze({ ...registration2 });
|
|
6807
|
+
const definition = snapshot(registration2.definition);
|
|
6808
|
+
return Object.freeze({ ...registration2, definition });
|
|
6524
6809
|
}
|
|
6525
6810
|
function isGated(node) {
|
|
6526
6811
|
return Object.values(node.definition.inputs ?? {}).some(
|
|
@@ -6764,9 +7049,9 @@ var init_runtime = __esm({
|
|
|
6764
7049
|
this.aborted = false;
|
|
6765
7050
|
this.listeners = /* @__PURE__ */ new Set();
|
|
6766
7051
|
}
|
|
6767
|
-
addEventListener(_type, listener,
|
|
7052
|
+
addEventListener(_type, listener, options2) {
|
|
6768
7053
|
if (this.aborted) this.call(listener);
|
|
6769
|
-
else if (
|
|
7054
|
+
else if (options2?.once) {
|
|
6770
7055
|
const once = () => {
|
|
6771
7056
|
this.listeners.delete(once);
|
|
6772
7057
|
listener();
|
|
@@ -6803,22 +7088,22 @@ var init_runtime = __esm({
|
|
|
6803
7088
|
this.graphs = /* @__PURE__ */ new Set();
|
|
6804
7089
|
this.sealed = false;
|
|
6805
7090
|
this.disposed = false;
|
|
6806
|
-
for (const
|
|
7091
|
+
for (const registration2 of registrations) this.registerNode(registration2);
|
|
6807
7092
|
}
|
|
6808
|
-
registerNode(
|
|
7093
|
+
registerNode(registration2) {
|
|
6809
7094
|
if (this.sealed || this.disposed)
|
|
6810
7095
|
misuse(
|
|
6811
7096
|
"runtime/registry-sealed",
|
|
6812
7097
|
"Node registrations are sealed after the first load"
|
|
6813
7098
|
);
|
|
6814
|
-
if (this.registrations.has(
|
|
7099
|
+
if (this.registrations.has(registration2.moduleId))
|
|
6815
7100
|
misuse(
|
|
6816
7101
|
"runtime/duplicate-registration",
|
|
6817
|
-
`Duplicate registration ${
|
|
7102
|
+
`Duplicate registration ${registration2.moduleId}`
|
|
6818
7103
|
);
|
|
6819
7104
|
this.registrations.set(
|
|
6820
|
-
|
|
6821
|
-
snapshotRegistration(
|
|
7105
|
+
registration2.moduleId,
|
|
7106
|
+
snapshotRegistration(registration2)
|
|
6822
7107
|
);
|
|
6823
7108
|
}
|
|
6824
7109
|
async load(document2) {
|
|
@@ -6853,18 +7138,18 @@ var init_runtime = __esm({
|
|
|
6853
7138
|
"runtime/legacy-adapter-required",
|
|
6854
7139
|
`Legacy module ${moduleId2} requires the explicit legacy adapter`
|
|
6855
7140
|
);
|
|
6856
|
-
const
|
|
7141
|
+
const registration2 = specializeCoreRegistration(
|
|
6857
7142
|
snapshot2,
|
|
6858
7143
|
authored,
|
|
6859
7144
|
document2.nodes
|
|
6860
7145
|
);
|
|
6861
|
-
const diagnostics = validateNodeDefinition(
|
|
7146
|
+
const diagnostics = validateNodeDefinition(registration2.definition);
|
|
6862
7147
|
if (diagnostics.length)
|
|
6863
7148
|
throw new CascadeRuntimeError(
|
|
6864
7149
|
"runtime/definition-invalid",
|
|
6865
7150
|
diagnostics
|
|
6866
7151
|
);
|
|
6867
|
-
nodes.push(materialize(authored,
|
|
7152
|
+
nodes.push(materialize(authored, registration2));
|
|
6868
7153
|
}
|
|
6869
7154
|
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
6870
7155
|
validateHierarchy(nodes, byId);
|
|
@@ -7184,17 +7469,17 @@ var init_runtime = __esm({
|
|
|
7184
7469
|
getFps() {
|
|
7185
7470
|
return this.fps;
|
|
7186
7471
|
}
|
|
7187
|
-
run(
|
|
7188
|
-
if (
|
|
7189
|
-
if (
|
|
7472
|
+
run(options2 = {}) {
|
|
7473
|
+
if (options2.fps !== void 0) this.setFps(options2.fps);
|
|
7474
|
+
if (options2.frame !== void 0) this.setFrame(options2.frame);
|
|
7190
7475
|
else this.animator.resolveAll();
|
|
7191
7476
|
return this.trackRun(
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7477
|
+
options2.target ?? { kind: "all" },
|
|
7478
|
+
options2.signal,
|
|
7479
|
+
options2.runId
|
|
7195
7480
|
);
|
|
7196
7481
|
}
|
|
7197
|
-
trigger(nodeId, inputName2, payload,
|
|
7482
|
+
trigger(nodeId, inputName2, payload, options2 = {}) {
|
|
7198
7483
|
const node = this.requireNode(nodeId);
|
|
7199
7484
|
if (node.definition.inputs?.[inputName2]?.kind !== "trigger")
|
|
7200
7485
|
return Promise.reject(
|
|
@@ -7205,8 +7490,8 @@ var init_runtime = __esm({
|
|
|
7205
7490
|
);
|
|
7206
7491
|
return this.trackRun(
|
|
7207
7492
|
{ kind: "node", nodeId },
|
|
7208
|
-
|
|
7209
|
-
|
|
7493
|
+
options2.signal,
|
|
7494
|
+
options2.runId,
|
|
7210
7495
|
{ nodeId, inputName: inputName2, payload }
|
|
7211
7496
|
);
|
|
7212
7497
|
}
|
|
@@ -7922,7 +8207,7 @@ var init_src2 = __esm({
|
|
|
7922
8207
|
});
|
|
7923
8208
|
|
|
7924
8209
|
// packages/runtime/src/node.ts
|
|
7925
|
-
function createNodeRuntimeHost(
|
|
8210
|
+
function createNodeRuntimeHost(options2) {
|
|
7926
8211
|
const {
|
|
7927
8212
|
modules,
|
|
7928
8213
|
legacyShell,
|
|
@@ -7930,7 +8215,7 @@ function createNodeRuntimeHost(options) {
|
|
|
7930
8215
|
report = () => {
|
|
7931
8216
|
},
|
|
7932
8217
|
...capabilities
|
|
7933
|
-
} =
|
|
8218
|
+
} = options2;
|
|
7934
8219
|
return {
|
|
7935
8220
|
environment: "server",
|
|
7936
8221
|
modules,
|
|
@@ -8481,12 +8766,12 @@ function normalizeManifest(raw) {
|
|
|
8481
8766
|
settings: Object.freeze(settingsRecord(raw.settings))
|
|
8482
8767
|
});
|
|
8483
8768
|
}
|
|
8484
|
-
function stringRecord(input,
|
|
8769
|
+
function stringRecord(input, label2) {
|
|
8485
8770
|
if (input === void 0) return {};
|
|
8486
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error(`${
|
|
8771
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error(`${label2} must be an object of strings`);
|
|
8487
8772
|
const entries2 = Object.entries(input);
|
|
8488
8773
|
if (entries2.some(([key2, value]) => !CREDENTIAL_NAME.test(key2) || typeof value !== "string" || value.includes("\0"))) {
|
|
8489
|
-
throw new Error(`${
|
|
8774
|
+
throw new Error(`${label2} must contain safe names and string values`);
|
|
8490
8775
|
}
|
|
8491
8776
|
return Object.fromEntries(entries2);
|
|
8492
8777
|
}
|
|
@@ -8630,7 +8915,7 @@ function within(root, candidate) {
|
|
|
8630
8915
|
function emptyResult() {
|
|
8631
8916
|
return { stdout: "", stderr: "", code: null, timedOut: false, cancelled: false, outputLimited: false };
|
|
8632
8917
|
}
|
|
8633
|
-
function execute(executable, args,
|
|
8918
|
+
function execute(executable, args, options2) {
|
|
8634
8919
|
return new Promise((resolve2, reject) => {
|
|
8635
8920
|
let terminal = null;
|
|
8636
8921
|
let spawnError;
|
|
@@ -8640,8 +8925,8 @@ function execute(executable, args, options) {
|
|
|
8640
8925
|
let stdoutBytes = 0;
|
|
8641
8926
|
let stderrBytes = 0;
|
|
8642
8927
|
const child = spawn(executable, args, {
|
|
8643
|
-
cwd:
|
|
8644
|
-
env:
|
|
8928
|
+
cwd: options2.cwd,
|
|
8929
|
+
env: options2.env,
|
|
8645
8930
|
detached: process.platform !== "win32",
|
|
8646
8931
|
shell: false,
|
|
8647
8932
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -8651,9 +8936,9 @@ function execute(executable, args, options) {
|
|
|
8651
8936
|
terminal = cause;
|
|
8652
8937
|
if (cause === "timeout" || cause === "cancelled" || cause === "output-limit") termination = terminateTree(child);
|
|
8653
8938
|
};
|
|
8654
|
-
const timer = setTimeout(() => finishCause("timeout"),
|
|
8939
|
+
const timer = setTimeout(() => finishCause("timeout"), options2.timeout);
|
|
8655
8940
|
const abort = () => finishCause("cancelled");
|
|
8656
|
-
|
|
8941
|
+
options2.signal?.addEventListener("abort", abort, { once: true });
|
|
8657
8942
|
child.stdout.on("data", (chunk) => {
|
|
8658
8943
|
stdoutBytes += chunk.length;
|
|
8659
8944
|
if (stdoutBytes <= MAX_BUFFER) stdout.push(chunk);
|
|
@@ -8671,7 +8956,7 @@ function execute(executable, args, options) {
|
|
|
8671
8956
|
child.once("exit", (code, signal) => finishCause(code === null || signal ? "signal" : "exit"));
|
|
8672
8957
|
child.once("close", async (code, signal) => {
|
|
8673
8958
|
clearTimeout(timer);
|
|
8674
|
-
|
|
8959
|
+
options2.signal?.removeEventListener("abort", abort);
|
|
8675
8960
|
await termination?.beforeSettle();
|
|
8676
8961
|
const output = { stdout: Buffer.concat(stdout).toString("utf8"), stderr: Buffer.concat(stderr).toString("utf8") };
|
|
8677
8962
|
if (terminal === "timeout" || terminal === "cancelled" || terminal === "output-limit") {
|
|
@@ -8684,9 +8969,9 @@ function execute(executable, args, options) {
|
|
|
8684
8969
|
resolve2({ ...output, code, timedOut: false, cancelled: false, outputLimited: false });
|
|
8685
8970
|
}
|
|
8686
8971
|
});
|
|
8687
|
-
if (
|
|
8972
|
+
if (options2.stdin !== void 0) child.stdin.end(options2.stdin);
|
|
8688
8973
|
else child.stdin.end();
|
|
8689
|
-
if (
|
|
8974
|
+
if (options2.signal?.aborted) abort();
|
|
8690
8975
|
});
|
|
8691
8976
|
}
|
|
8692
8977
|
function terminateTree(child) {
|
|
@@ -8758,7 +9043,7 @@ var init_service = __esm({
|
|
|
8758
9043
|
setAuditSink(sink) {
|
|
8759
9044
|
this.auditSink = sink;
|
|
8760
9045
|
}
|
|
8761
|
-
async run(command, args = [],
|
|
9046
|
+
async run(command, args = [], options2 = {}) {
|
|
8762
9047
|
const started = Date.now();
|
|
8763
9048
|
const id = randomUUID();
|
|
8764
9049
|
let cwd = ".";
|
|
@@ -8767,14 +9052,14 @@ var init_service = __esm({
|
|
|
8767
9052
|
try {
|
|
8768
9053
|
this.reloadConfig();
|
|
8769
9054
|
const executable = this.resolveCommand(command);
|
|
8770
|
-
const validated = this.validate(args,
|
|
9055
|
+
const validated = this.validate(args, options2);
|
|
8771
9056
|
cwd = validated.relativeCwd;
|
|
8772
9057
|
result = await execute(executable, validated.args, {
|
|
8773
9058
|
cwd: validated.cwd,
|
|
8774
9059
|
timeout: validated.timeout,
|
|
8775
9060
|
stdin: validated.stdin,
|
|
8776
9061
|
env: validated.env,
|
|
8777
|
-
signal:
|
|
9062
|
+
signal: options2.signal
|
|
8778
9063
|
});
|
|
8779
9064
|
return result;
|
|
8780
9065
|
} catch (error) {
|
|
@@ -8810,8 +9095,8 @@ var init_service = __esm({
|
|
|
8810
9095
|
this.executables.set(alias, resolveExecutable(this.project.root, target));
|
|
8811
9096
|
}
|
|
8812
9097
|
}
|
|
8813
|
-
async runJson(command, args = [],
|
|
8814
|
-
const result = await this.run(command, args,
|
|
9098
|
+
async runJson(command, args = [], options2 = {}) {
|
|
9099
|
+
const result = await this.run(command, args, options2);
|
|
8815
9100
|
if (result.code !== 0) throw new ShellProcessError("nonzero", result, result.stderr || `Command exited with code ${result.code}`);
|
|
8816
9101
|
const lines = result.stdout.split(/\r?\n/).filter((value) => value.trim());
|
|
8817
9102
|
const line2 = lines[lines.length - 1] ?? "";
|
|
@@ -8833,15 +9118,15 @@ var init_service = __esm({
|
|
|
8833
9118
|
if (!executable) throw new ShellRequestError("MISSING_EXECUTABLE", `Configured command "${command}" is not available`);
|
|
8834
9119
|
return executable;
|
|
8835
9120
|
}
|
|
8836
|
-
validate(args,
|
|
9121
|
+
validate(args, options2) {
|
|
8837
9122
|
if (!Array.isArray(args) || args.length > MAX_ARGS || args.some((arg) => typeof arg !== "string" || Buffer.byteLength(arg) > MAX_ARG_BYTES || arg.includes("\0"))) {
|
|
8838
9123
|
throw new ShellRequestError("INVALID_REQUEST", "args must be an array of bounded strings");
|
|
8839
9124
|
}
|
|
8840
|
-
if (
|
|
9125
|
+
if (options2.stdin !== void 0 && (typeof options2.stdin !== "string" || Buffer.byteLength(options2.stdin) > MAX_STDIN_BYTES || options2.stdin.includes("\0"))) {
|
|
8841
9126
|
throw new ShellRequestError("INVALID_REQUEST", "stdin exceeds the 16 MiB limit or is invalid");
|
|
8842
9127
|
}
|
|
8843
|
-
const { cwd, relativeCwd } = resolveCwd(this.project.root,
|
|
8844
|
-
const requestEnv =
|
|
9128
|
+
const { cwd, relativeCwd } = resolveCwd(this.project.root, options2.cwd ?? ".");
|
|
9129
|
+
const requestEnv = options2.env ?? {};
|
|
8845
9130
|
const entries2 = Object.entries(requestEnv);
|
|
8846
9131
|
if (entries2.length > MAX_ENV_KEYS || entries2.reduce((sum2, [key2, value]) => sum2 + Buffer.byteLength(key2) + Buffer.byteLength(String(value)), 0) > MAX_ENV_BYTES) {
|
|
8847
9132
|
throw new ShellRequestError("INVALID_REQUEST", "request environment exceeds its limit");
|
|
@@ -8851,17 +9136,17 @@ var init_service = __esm({
|
|
|
8851
9136
|
throw new ShellRequestError("INVALID_REQUEST", `request environment variable ${JSON.stringify(key2)} is not allowed`);
|
|
8852
9137
|
}
|
|
8853
9138
|
}
|
|
8854
|
-
if (
|
|
9139
|
+
if (options2.timeout !== void 0 && (typeof options2.timeout !== "number" || !Number.isFinite(options2.timeout))) {
|
|
8855
9140
|
throw new ShellRequestError("INVALID_REQUEST", "timeout must be a finite number");
|
|
8856
9141
|
}
|
|
8857
|
-
const timeout = Math.min(6e5, Math.max(1, Math.trunc(
|
|
9142
|
+
const timeout = Math.min(6e5, Math.max(1, Math.trunc(options2.timeout ?? this.config.shell.timeout)));
|
|
8858
9143
|
const credentialEnv = new CredentialStore().environment(readProjectManifest(this.project.root).credentials);
|
|
8859
9144
|
return {
|
|
8860
9145
|
args: [...args],
|
|
8861
9146
|
cwd,
|
|
8862
9147
|
relativeCwd,
|
|
8863
9148
|
timeout,
|
|
8864
|
-
stdin:
|
|
9149
|
+
stdin: options2.stdin,
|
|
8865
9150
|
env: { ...process.env, ...this.config.shell.env, ...requestEnv, ...credentialEnv }
|
|
8866
9151
|
};
|
|
8867
9152
|
}
|
|
@@ -9543,7 +9828,7 @@ async function runDeterministicProjectGraph(file, document2, entryNode) {
|
|
|
9543
9828
|
}
|
|
9544
9829
|
}
|
|
9545
9830
|
}
|
|
9546
|
-
async function renderDeterministicProjectFrames(file, document2,
|
|
9831
|
+
async function renderDeterministicProjectFrames(file, document2, options2) {
|
|
9547
9832
|
const prepared = await prepare(file, document2, true);
|
|
9548
9833
|
reportUnresolved(prepared);
|
|
9549
9834
|
if (!usesDeterministicHost(document2, prepared)) return null;
|
|
@@ -9554,7 +9839,7 @@ async function renderDeterministicProjectFrames(file, document2, options) {
|
|
|
9554
9839
|
nodes: prepared.registrations
|
|
9555
9840
|
});
|
|
9556
9841
|
let graph;
|
|
9557
|
-
const width = sequenceWidth(
|
|
9842
|
+
const width = sequenceWidth(options2.end);
|
|
9558
9843
|
const frames = [];
|
|
9559
9844
|
const files = [];
|
|
9560
9845
|
let aborted = false;
|
|
@@ -9563,24 +9848,24 @@ async function renderDeterministicProjectFrames(file, document2, options) {
|
|
|
9563
9848
|
try {
|
|
9564
9849
|
graph = await runtime.load(document2);
|
|
9565
9850
|
reportPreflightWarnings(host, classifyPreflight(graph.preflight()).warnings);
|
|
9566
|
-
const outDirectory = project.resolve(
|
|
9851
|
+
const outDirectory = project.resolve(options2.out);
|
|
9567
9852
|
await fs7.mkdir(outDirectory, { recursive: true });
|
|
9568
|
-
for (const frame of frameRange(
|
|
9569
|
-
if (
|
|
9853
|
+
for (const frame of frameRange(options2.start, options2.end, options2.step ?? 1)) {
|
|
9854
|
+
if (options2.signal?.aborted) {
|
|
9570
9855
|
aborted = true;
|
|
9571
9856
|
break;
|
|
9572
9857
|
}
|
|
9573
9858
|
const result = await graph.run({
|
|
9574
9859
|
frame,
|
|
9575
|
-
...
|
|
9576
|
-
...
|
|
9860
|
+
...options2.fps === void 0 ? {} : { fps: options2.fps },
|
|
9861
|
+
...options2.entryNode ? { target: { kind: "node", nodeId: options2.entryNode } } : {}
|
|
9577
9862
|
});
|
|
9578
9863
|
if (result.status !== "completed") {
|
|
9579
9864
|
throw new Error(
|
|
9580
9865
|
`frame ${frame} ${result.status} \u2014 ${result.diagnostics.map((item) => item.message).join("; ") || "no diagnostics"}`
|
|
9581
9866
|
);
|
|
9582
9867
|
}
|
|
9583
|
-
const outputs = imageOutputs(graph,
|
|
9868
|
+
const outputs = imageOutputs(graph, options2.entryNode);
|
|
9584
9869
|
if (!outputs.length) {
|
|
9585
9870
|
throw new Error(
|
|
9586
9871
|
"No image output to save: the graph has no unconsumed image port. Name the node to render with --entry-node."
|
|
@@ -9591,10 +9876,10 @@ async function renderDeterministicProjectFrames(file, document2, options) {
|
|
|
9591
9876
|
if (!source) continue;
|
|
9592
9877
|
const name = sequenceFileName(nodeId, frame, source, width);
|
|
9593
9878
|
await fs7.copyFile(project.resolveMedia(source.replace(/^\.?\//, "")), path9.join(outDirectory, name));
|
|
9594
|
-
files.push(path9.posix.join(
|
|
9879
|
+
files.push(path9.posix.join(options2.out, name));
|
|
9595
9880
|
}
|
|
9596
9881
|
frames.push(frame);
|
|
9597
|
-
if (
|
|
9882
|
+
if (options2.verbose) console.log(` frame ${frame}`);
|
|
9598
9883
|
}
|
|
9599
9884
|
try {
|
|
9600
9885
|
gpu = { renderer: "dawn", adapter: host.capabilities.gpu.adapterInfo };
|
|
@@ -9835,7 +10120,7 @@ function jsonValue(value) {
|
|
|
9835
10120
|
}
|
|
9836
10121
|
}
|
|
9837
10122
|
function resolver(registrations) {
|
|
9838
|
-
const modules = new Map(registrations.map((
|
|
10123
|
+
const modules = new Map(registrations.map((registration2) => [registration2.moduleId, registration2]));
|
|
9839
10124
|
return { resolve: async (id) => modules.get(id) ?? null };
|
|
9840
10125
|
}
|
|
9841
10126
|
function formatDiagnostic(diagnostic2) {
|
|
@@ -10038,7 +10323,7 @@ function readStageConfig(project) {
|
|
|
10038
10323
|
}
|
|
10039
10324
|
return { python, entrypoint, ...worker ? { worker } : {} };
|
|
10040
10325
|
}
|
|
10041
|
-
async function runProjectStage(project, stage, args,
|
|
10326
|
+
async function runProjectStage(project, stage, args, options2 = {}) {
|
|
10042
10327
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(stage)) {
|
|
10043
10328
|
throw new Error("stage contains unsupported characters");
|
|
10044
10329
|
}
|
|
@@ -10051,10 +10336,10 @@ async function runProjectStage(project, stage, args, options = {}) {
|
|
|
10051
10336
|
[script, "--stage", stage, "--args", "-"],
|
|
10052
10337
|
{
|
|
10053
10338
|
cwd: project.root,
|
|
10054
|
-
timeout:
|
|
10339
|
+
timeout: options2.timeout ?? TIMEOUT_MS,
|
|
10055
10340
|
maxBuffer: MAX_BUFFER2,
|
|
10056
|
-
env:
|
|
10057
|
-
signal:
|
|
10341
|
+
env: options2.env ?? process.env,
|
|
10342
|
+
signal: options2.signal
|
|
10058
10343
|
},
|
|
10059
10344
|
(error, out, err) => {
|
|
10060
10345
|
if (error) {
|
|
@@ -10088,7 +10373,7 @@ var init_stageRunner = __esm({
|
|
|
10088
10373
|
});
|
|
10089
10374
|
|
|
10090
10375
|
// packages/runtime/src/browser.ts
|
|
10091
|
-
function createBrowserRuntimeHost(
|
|
10376
|
+
function createBrowserRuntimeHost(options2) {
|
|
10092
10377
|
const {
|
|
10093
10378
|
modules,
|
|
10094
10379
|
legacyShell,
|
|
@@ -10096,7 +10381,7 @@ function createBrowserRuntimeHost(options) {
|
|
|
10096
10381
|
report = () => {
|
|
10097
10382
|
},
|
|
10098
10383
|
...capabilities
|
|
10099
|
-
} =
|
|
10384
|
+
} = options2;
|
|
10100
10385
|
return {
|
|
10101
10386
|
environment: "browser",
|
|
10102
10387
|
modules,
|
|
@@ -10123,10 +10408,10 @@ import { builtinModules } from "node:module";
|
|
|
10123
10408
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
10124
10409
|
import { build as build3 } from "esbuild";
|
|
10125
10410
|
import ts3 from "typescript";
|
|
10126
|
-
async function buildPlayer(file,
|
|
10127
|
-
if (!
|
|
10411
|
+
async function buildPlayer(file, options2) {
|
|
10412
|
+
if (!options2.out) throw new Error("cascade build requires --out <new-directory>");
|
|
10128
10413
|
const project = new ProjectRoot(path14.dirname(path14.resolve(file)));
|
|
10129
|
-
const out = path14.resolve(project.root,
|
|
10414
|
+
const out = path14.resolve(project.root, options2.out);
|
|
10130
10415
|
if (await exists2(out)) throw new Error(`Player output already exists: ${out}. Choose a new directory.`);
|
|
10131
10416
|
const canonicalOut = await canonicalFuturePath(out);
|
|
10132
10417
|
for (const sourceDirectory of ["assets", "nodes"]) {
|
|
@@ -10169,7 +10454,7 @@ ${extracted.diagnostics.map((d) => `${d.code}: ${d.message}`).join("\n")}`);
|
|
|
10169
10454
|
assets: {},
|
|
10170
10455
|
gpu: {}
|
|
10171
10456
|
}), nodes: registrations });
|
|
10172
|
-
const assets = new Set(
|
|
10457
|
+
const assets = new Set(options2.assets ?? []);
|
|
10173
10458
|
try {
|
|
10174
10459
|
const graph = await runtime.load(document2);
|
|
10175
10460
|
const diagnostics = graph.preflight();
|
|
@@ -11124,12 +11409,12 @@ function isLoopbackHost(host) {
|
|
|
11124
11409
|
const normalized = host.toLowerCase().replace(/^\[|\]$/g, "");
|
|
11125
11410
|
return normalized === "127.0.0.1" || normalized === "localhost" || normalized === "::1";
|
|
11126
11411
|
}
|
|
11127
|
-
function allowsSensitiveCapabilities(
|
|
11128
|
-
return
|
|
11412
|
+
function allowsSensitiveCapabilities(options2) {
|
|
11413
|
+
return options2.sensitiveCapabilities;
|
|
11129
11414
|
}
|
|
11130
|
-
function createProjectRequestBoundary(
|
|
11131
|
-
const origins = new Set(
|
|
11132
|
-
const authorities = allowedAuthorities(
|
|
11415
|
+
function createProjectRequestBoundary(options2) {
|
|
11416
|
+
const origins = new Set(options2.trustedOrigins.map((origin) => validateOrigin(origin, "Project")));
|
|
11417
|
+
const authorities = allowedAuthorities(options2, origins);
|
|
11133
11418
|
return {
|
|
11134
11419
|
guard(req, res, next) {
|
|
11135
11420
|
const host = req.get("Host");
|
|
@@ -11150,9 +11435,9 @@ function createProjectRequestBoundary(options) {
|
|
|
11150
11435
|
}
|
|
11151
11436
|
};
|
|
11152
11437
|
}
|
|
11153
|
-
function createBrowserCapabilityBoundary(
|
|
11154
|
-
const origins = new Set(
|
|
11155
|
-
const authorities = allowedAuthorities(
|
|
11438
|
+
function createBrowserCapabilityBoundary(options2, label2, header) {
|
|
11439
|
+
const origins = new Set(options2.trustedOrigins.map((origin) => validateOrigin(origin, label2)));
|
|
11440
|
+
const authorities = allowedAuthorities(options2, origins);
|
|
11156
11441
|
const capability2 = randomBytes(32).toString("base64url");
|
|
11157
11442
|
const expectedBytes = Buffer.from(capability2);
|
|
11158
11443
|
return {
|
|
@@ -11160,7 +11445,7 @@ function createBrowserCapabilityBoundary(options, label, header) {
|
|
|
11160
11445
|
const origin = req.get("Origin");
|
|
11161
11446
|
const host = req.get("Host");
|
|
11162
11447
|
if (!host || !authorities.has(host.toLowerCase()) || origin === "null" || origin && !origins.has(origin)) {
|
|
11163
|
-
res.status(403).json({ ok: false, error: `${
|
|
11448
|
+
res.status(403).json({ ok: false, error: `${label2} access denied` });
|
|
11164
11449
|
return;
|
|
11165
11450
|
}
|
|
11166
11451
|
if (origin) setCorsOrigin(res, origin);
|
|
@@ -11180,23 +11465,23 @@ function createBrowserCapabilityBoundary(options, label, header) {
|
|
|
11180
11465
|
const supplied = req.get(header);
|
|
11181
11466
|
const suppliedBytes = supplied ? Buffer.from(supplied) : Buffer.alloc(0);
|
|
11182
11467
|
if (suppliedBytes.length !== expectedBytes.length || !timingSafeEqual(suppliedBytes, expectedBytes)) {
|
|
11183
|
-
res.status(403).json({ ok: false, error: `${
|
|
11468
|
+
res.status(403).json({ ok: false, error: `${label2} capability required` });
|
|
11184
11469
|
return;
|
|
11185
11470
|
}
|
|
11186
11471
|
next();
|
|
11187
11472
|
}
|
|
11188
11473
|
};
|
|
11189
11474
|
}
|
|
11190
|
-
function allowedAuthorities(
|
|
11475
|
+
function allowedAuthorities(options2, origins) {
|
|
11191
11476
|
const authorities = new Set([...origins].map((origin) => new URL(origin).host.toLowerCase()));
|
|
11192
|
-
if (isLoopbackHost(
|
|
11193
|
-
authorities.add(`127.0.0.1:${
|
|
11194
|
-
authorities.add(`localhost:${
|
|
11195
|
-
} else if (!isWildcardHost(
|
|
11196
|
-
authorities.add(authority(
|
|
11197
|
-
}
|
|
11198
|
-
for (const host of
|
|
11199
|
-
const value = trustedAuthority(host,
|
|
11477
|
+
if (isLoopbackHost(options2.host)) {
|
|
11478
|
+
authorities.add(`127.0.0.1:${options2.port}`);
|
|
11479
|
+
authorities.add(`localhost:${options2.port}`);
|
|
11480
|
+
} else if (!isWildcardHost(options2.host)) {
|
|
11481
|
+
authorities.add(authority(options2.host, options2.port));
|
|
11482
|
+
}
|
|
11483
|
+
for (const host of options2.trustedHosts) {
|
|
11484
|
+
const value = trustedAuthority(host, options2.port);
|
|
11200
11485
|
authorities.add(value);
|
|
11201
11486
|
const bare = value.replace(/:(?:80|443)$/, "");
|
|
11202
11487
|
if (bare !== value) authorities.add(bare);
|
|
@@ -11232,10 +11517,10 @@ function setCorsOrigin(res, origin) {
|
|
|
11232
11517
|
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
11233
11518
|
res.setHeader("Vary", "Origin");
|
|
11234
11519
|
}
|
|
11235
|
-
function validateOrigin(value,
|
|
11520
|
+
function validateOrigin(value, label2) {
|
|
11236
11521
|
const url = new URL(value);
|
|
11237
11522
|
if (!/^https?:$/.test(url.protocol) || url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
|
|
11238
|
-
throw new Error(`Invalid trusted ${
|
|
11523
|
+
throw new Error(`Invalid trusted ${label2.toLowerCase()} origin: ${value}`);
|
|
11239
11524
|
}
|
|
11240
11525
|
return url.origin;
|
|
11241
11526
|
}
|
|
@@ -11367,10 +11652,10 @@ var init_exec = __esm({
|
|
|
11367
11652
|
|
|
11368
11653
|
// server/src/routes/shell.ts
|
|
11369
11654
|
import { Router as Router6, json as json2 } from "express";
|
|
11370
|
-
function createShellRouter(shell,
|
|
11655
|
+
function createShellRouter(shell, options2) {
|
|
11371
11656
|
const router = Router6();
|
|
11372
|
-
if (!allowsSensitiveCapabilities(
|
|
11373
|
-
const boundary = createBrowserCapabilityBoundary(
|
|
11657
|
+
if (!allowsSensitiveCapabilities(options2)) return router.use((_req, res) => res.status(404).end());
|
|
11658
|
+
const boundary = createBrowserCapabilityBoundary(options2, "Shell", "X-Cascade-Shell-Capability");
|
|
11374
11659
|
router.use(boundary.guardOrigin);
|
|
11375
11660
|
router.options("{*path}", boundary.preflight);
|
|
11376
11661
|
router.get("/capability", boundary.issueCapability);
|
|
@@ -13477,19 +13762,19 @@ var Node = class _Node {
|
|
|
13477
13762
|
else if (!promoted && index >= 0) parent.promotions.splice(index, 1);
|
|
13478
13763
|
}
|
|
13479
13764
|
// ============ Port Creation ============
|
|
13480
|
-
in(name, defaultValue,
|
|
13765
|
+
in(name, defaultValue, options2 = {}) {
|
|
13481
13766
|
const portType = name === "trigger" ? "trigger" : "param";
|
|
13482
13767
|
const existingPort = this.inputs.find((p) => p.name === name);
|
|
13483
13768
|
if (existingPort) {
|
|
13484
13769
|
this.portsUsedDuringSetup.add(`input_${name}`);
|
|
13485
|
-
if (
|
|
13770
|
+
if (options2.type) existingPort.dataType = options2.type;
|
|
13486
13771
|
if (defaultValue !== void 0 && existingPort.defaultValue !== defaultValue) {
|
|
13487
13772
|
existingPort.defaultValue = defaultValue;
|
|
13488
13773
|
if (existingPort.value === void 0 || existingPort.value === existingPort.defaultValue) {
|
|
13489
13774
|
existingPort.value = defaultValue;
|
|
13490
13775
|
}
|
|
13491
13776
|
}
|
|
13492
|
-
existingPort.options = Object.assign(existingPort.options ?? {},
|
|
13777
|
+
existingPort.options = Object.assign(existingPort.options ?? {}, options2);
|
|
13493
13778
|
return existingPort;
|
|
13494
13779
|
}
|
|
13495
13780
|
const portIndex = this.inputs.length;
|
|
@@ -13497,10 +13782,10 @@ var Node = class _Node {
|
|
|
13497
13782
|
id: `${this.id}_in_${portIndex}`,
|
|
13498
13783
|
name,
|
|
13499
13784
|
portType,
|
|
13500
|
-
dataType:
|
|
13785
|
+
dataType: options2.type || "any",
|
|
13501
13786
|
value: defaultValue,
|
|
13502
13787
|
defaultValue,
|
|
13503
|
-
options,
|
|
13788
|
+
options: options2,
|
|
13504
13789
|
connections: []
|
|
13505
13790
|
};
|
|
13506
13791
|
this.inputs.push(port);
|
|
@@ -13514,13 +13799,13 @@ var Node = class _Node {
|
|
|
13514
13799
|
* only ever sees `any` on one side, and the port draws in the neutral colour
|
|
13515
13800
|
* whatever it actually carries.
|
|
13516
13801
|
*/
|
|
13517
|
-
out(name, portType = "param",
|
|
13802
|
+
out(name, portType = "param", options2 = {}) {
|
|
13518
13803
|
const existingPort = this.outputs.find((p) => p.name === name);
|
|
13519
13804
|
if (existingPort) {
|
|
13520
13805
|
this.portsUsedDuringSetup.add(`output_${name}`);
|
|
13521
13806
|
if (existingPort.portType !== portType) existingPort.portType = portType;
|
|
13522
|
-
if (
|
|
13523
|
-
existingPort.options = { ...existingPort.options ?? {}, ...
|
|
13807
|
+
if (options2.type) existingPort.dataType = options2.type;
|
|
13808
|
+
existingPort.options = { ...existingPort.options ?? {}, ...options2 };
|
|
13524
13809
|
return existingPort;
|
|
13525
13810
|
}
|
|
13526
13811
|
const portIndex = this.outputs.length;
|
|
@@ -13528,10 +13813,10 @@ var Node = class _Node {
|
|
|
13528
13813
|
id: `${this.id}_out_${portIndex}`,
|
|
13529
13814
|
name,
|
|
13530
13815
|
portType,
|
|
13531
|
-
dataType:
|
|
13816
|
+
dataType: options2.type || "any",
|
|
13532
13817
|
value: void 0,
|
|
13533
13818
|
connections: [],
|
|
13534
|
-
options,
|
|
13819
|
+
options: options2,
|
|
13535
13820
|
setValue: (value) => this.setOutputValue(port, value),
|
|
13536
13821
|
trigger: (props) => {
|
|
13537
13822
|
port.connections.forEach((conn) => {
|
|
@@ -13877,26 +14162,26 @@ var Node = class _Node {
|
|
|
13877
14162
|
* say. Promotion is per parameter and off by default: making every setting a
|
|
13878
14163
|
* pin is how the two got conflated in the first place.
|
|
13879
14164
|
*/
|
|
13880
|
-
param(name, defaultValue,
|
|
14165
|
+
param(name, defaultValue, options2 = {}) {
|
|
13881
14166
|
let parameter = this.parameters.find((p) => p.name === name);
|
|
13882
14167
|
if (!parameter) {
|
|
13883
14168
|
parameter = {
|
|
13884
14169
|
name,
|
|
13885
14170
|
value: defaultValue,
|
|
13886
14171
|
defaultValue,
|
|
13887
|
-
dataType:
|
|
14172
|
+
dataType: options2.type || inferParamType(defaultValue),
|
|
13888
14173
|
promoted: false,
|
|
13889
|
-
options
|
|
14174
|
+
options: options2
|
|
13890
14175
|
};
|
|
13891
14176
|
this.parameters.push(parameter);
|
|
13892
14177
|
} else {
|
|
13893
|
-
if (
|
|
14178
|
+
if (options2.type) parameter.dataType = options2.type;
|
|
13894
14179
|
parameter.defaultValue = defaultValue;
|
|
13895
|
-
Object.assign(parameter.options,
|
|
14180
|
+
Object.assign(parameter.options, options2);
|
|
13896
14181
|
}
|
|
13897
14182
|
this.parametersUsedDuringSetup.add(name);
|
|
13898
|
-
this.reconcileParameter(parameter, defaultValue,
|
|
13899
|
-
this.bindParameterProp(parameter, name,
|
|
14183
|
+
this.reconcileParameter(parameter, defaultValue, options2);
|
|
14184
|
+
this.bindParameterProp(parameter, name, options2);
|
|
13900
14185
|
if (parameter.promoted) {
|
|
13901
14186
|
const port = this.in(name, parameter.value, {
|
|
13902
14187
|
...parameter.options,
|
|
@@ -13920,7 +14205,7 @@ var Node = class _Node {
|
|
|
13920
14205
|
* rather than replaced for the same reason the Inspector does not re-key a
|
|
13921
14206
|
* row on commit — replacing it mid-drag destroys the control in use.
|
|
13922
14207
|
*/
|
|
13923
|
-
bindParameterProp(parameter, name,
|
|
14208
|
+
bindParameterProp(parameter, name, options2) {
|
|
13924
14209
|
const descriptor = Object.getOwnPropertyDescriptor(parameter, "value");
|
|
13925
14210
|
const seeded = descriptor && !descriptor.get ? descriptor.value : void 0;
|
|
13926
14211
|
let prop = this.props[name];
|
|
@@ -13929,10 +14214,10 @@ var Node = class _Node {
|
|
|
13929
14214
|
this.props[name] = prop;
|
|
13930
14215
|
this.props = { ...this.props };
|
|
13931
14216
|
}
|
|
13932
|
-
if (
|
|
14217
|
+
if (options2.defaultExpression && !this.defaultExpressionsApplied.has(name)) {
|
|
13933
14218
|
this.defaultExpressionsApplied.add(name);
|
|
13934
14219
|
if (!this.plainPropOverrides.has(name) && !prop.expression) {
|
|
13935
|
-
prop.expression =
|
|
14220
|
+
prop.expression = options2.defaultExpression;
|
|
13936
14221
|
this.props = { ...this.props };
|
|
13937
14222
|
this.updateTimeDependent();
|
|
13938
14223
|
}
|
|
@@ -13942,9 +14227,9 @@ var Node = class _Node {
|
|
|
13942
14227
|
const control = paramControlType(parameter.dataType);
|
|
13943
14228
|
if (control) prop.type = control;
|
|
13944
14229
|
const params = { ...prop.params ?? {} };
|
|
13945
|
-
if (
|
|
13946
|
-
if (
|
|
13947
|
-
if (
|
|
14230
|
+
if (options2.min !== void 0) params.min = options2.min;
|
|
14231
|
+
if (options2.max !== void 0) params.max = options2.max;
|
|
14232
|
+
if (options2.step !== void 0) params.step = options2.step;
|
|
13948
14233
|
if (normalizeType(parameter.dataType ?? "any") === "int") params.integer = true;
|
|
13949
14234
|
prop.params = params;
|
|
13950
14235
|
if (descriptor?.get) return;
|
|
@@ -14177,13 +14462,13 @@ var Node = class _Node {
|
|
|
14177
14462
|
return carry.report;
|
|
14178
14463
|
}
|
|
14179
14464
|
/** Called from param() for every declaration the new definition makes. */
|
|
14180
|
-
reconcileParameter(parameter, defaultValue,
|
|
14465
|
+
reconcileParameter(parameter, defaultValue, options2) {
|
|
14181
14466
|
const carry = this.carryOver;
|
|
14182
14467
|
if (!carry) return;
|
|
14183
14468
|
const key2 = `parameter:${parameter.name}`;
|
|
14184
14469
|
if (carry.resolved.has(key2)) return;
|
|
14185
14470
|
carry.resolved.add(key2);
|
|
14186
|
-
const declared =
|
|
14471
|
+
const declared = options2.type ?? inferParamType(defaultValue);
|
|
14187
14472
|
parameter.dataType = declared;
|
|
14188
14473
|
const declaredType = carryType(declared);
|
|
14189
14474
|
const crossKey = `prop:${parameter.name}`;
|
|
@@ -14244,10 +14529,10 @@ var Node = class _Node {
|
|
|
14244
14529
|
}
|
|
14245
14530
|
}
|
|
14246
14531
|
// ============ Variadic Inputs ============
|
|
14247
|
-
setVariadic(defaultValue = null,
|
|
14532
|
+
setVariadic(defaultValue = null, options2 = {}) {
|
|
14248
14533
|
this.variadic = true;
|
|
14249
14534
|
this.variadicDefault = defaultValue;
|
|
14250
|
-
this.variadicOptions =
|
|
14535
|
+
this.variadicOptions = options2;
|
|
14251
14536
|
this.syncVariadicPorts();
|
|
14252
14537
|
}
|
|
14253
14538
|
getVariadicInputs() {
|
|
@@ -15996,8 +16281,8 @@ function parameterOptions(definition) {
|
|
|
15996
16281
|
promotable: false
|
|
15997
16282
|
};
|
|
15998
16283
|
}
|
|
15999
|
-
function attachDefinition(node,
|
|
16000
|
-
const definition =
|
|
16284
|
+
function attachDefinition(node, registration2, capabilities) {
|
|
16285
|
+
const definition = registration2.definition;
|
|
16001
16286
|
const pendingTriggers = /* @__PURE__ */ new Map();
|
|
16002
16287
|
let triggerSequence = 0;
|
|
16003
16288
|
const container = definition.container;
|
|
@@ -16060,10 +16345,10 @@ function attachDefinition(node, registration, capabilities) {
|
|
|
16060
16345
|
if (hasTriggerInputs && pendingTriggers.size === 0) return;
|
|
16061
16346
|
for (const name of definition.capabilities ?? []) {
|
|
16062
16347
|
if (!capabilities[name]) {
|
|
16063
|
-
throw new Error(`${
|
|
16348
|
+
throw new Error(`${registration2.moduleId} requires the Studio ${name} capability`);
|
|
16064
16349
|
}
|
|
16065
16350
|
}
|
|
16066
|
-
const execute2 = await (executePromise ??=
|
|
16351
|
+
const execute2 = await (executePromise ??= registration2.loadExecute("browser"));
|
|
16067
16352
|
const inputValues = {};
|
|
16068
16353
|
for (const [name, input] of Object.entries(definition.inputs ?? {})) {
|
|
16069
16354
|
inputValues[name] = input.kind === "trigger" ? pendingTriggers.get(name) : input.variadic ? node.getVariadicInputs().map((port) => port.value ?? void 0) : node.inputs.find((port) => port.name === name)?.value;
|
|
@@ -16071,7 +16356,7 @@ function attachDefinition(node, registration, capabilities) {
|
|
|
16071
16356
|
pendingTriggers.clear();
|
|
16072
16357
|
const outputs = Object.fromEntries(Object.entries(definition.outputs ?? {}).map(([name, output]) => {
|
|
16073
16358
|
const port = node.outputs.find((candidate) => candidate.name === name);
|
|
16074
|
-
if (!port) throw new Error(`Missing output ${
|
|
16359
|
+
if (!port) throw new Error(`Missing output ${registration2.moduleId}.${name}`);
|
|
16075
16360
|
return [name, output.kind === "trigger" ? { trigger: (payload) => port.trigger(payload) } : { set: (value) => port.setValue(value) }];
|
|
16076
16361
|
}));
|
|
16077
16362
|
let nodeCapabilities = capabilities;
|
|
@@ -16171,8 +16456,8 @@ async function post(body, signal) {
|
|
|
16171
16456
|
}
|
|
16172
16457
|
return response;
|
|
16173
16458
|
}
|
|
16174
|
-
function requestBody(command, args,
|
|
16175
|
-
const { signal: _signal, ...rest } =
|
|
16459
|
+
function requestBody(command, args, options2) {
|
|
16460
|
+
const { signal: _signal, ...rest } = options2 ?? {};
|
|
16176
16461
|
return {
|
|
16177
16462
|
command,
|
|
16178
16463
|
...args ? { args } : {},
|
|
@@ -16192,14 +16477,14 @@ async function fail2(response) {
|
|
|
16192
16477
|
throw new Error(message2);
|
|
16193
16478
|
}
|
|
16194
16479
|
var browserShellCapability = {
|
|
16195
|
-
async run(command, args,
|
|
16196
|
-
const response = await post(requestBody(command, args,
|
|
16480
|
+
async run(command, args, options2) {
|
|
16481
|
+
const response = await post(requestBody(command, args, options2), options2?.signal);
|
|
16197
16482
|
if (!response.ok) await fail2(response);
|
|
16198
16483
|
const { ok: _ok, ...result } = await response.json();
|
|
16199
16484
|
return result;
|
|
16200
16485
|
},
|
|
16201
|
-
async runJson(command, args,
|
|
16202
|
-
const result = await this.run(command, args,
|
|
16486
|
+
async runJson(command, args, options2) {
|
|
16487
|
+
const result = await this.run(command, args, options2);
|
|
16203
16488
|
try {
|
|
16204
16489
|
return JSON.parse(result.stdout);
|
|
16205
16490
|
} catch {
|
|
@@ -16312,13 +16597,13 @@ function adaptModule(node, moduleId2, module, capabilities = studioCapabilities)
|
|
|
16312
16597
|
const invalid = definitionAdapterError(module.definition);
|
|
16313
16598
|
if (invalid) throw new Error(`${moduleId2} exports an invalid definition-v1 literal:
|
|
16314
16599
|
${invalid}`);
|
|
16315
|
-
const
|
|
16600
|
+
const registration2 = {
|
|
16316
16601
|
kind: "definition-v1",
|
|
16317
16602
|
moduleId: moduleId2,
|
|
16318
16603
|
definition: module.definition,
|
|
16319
16604
|
loadExecute: async () => module.execute
|
|
16320
16605
|
};
|
|
16321
|
-
return attachDefinition(node,
|
|
16606
|
+
return attachDefinition(node, registration2, capabilities);
|
|
16322
16607
|
}
|
|
16323
16608
|
|
|
16324
16609
|
// src/nodes/CookScheduler.ts
|
|
@@ -16550,9 +16835,9 @@ var CookScheduler = class {
|
|
|
16550
16835
|
* interactive queue, not to weaken the preemption; the preemption is the
|
|
16551
16836
|
* only thing making the lane honest.
|
|
16552
16837
|
*/
|
|
16553
|
-
async runBackground(task,
|
|
16838
|
+
async runBackground(task, options2 = {}) {
|
|
16554
16839
|
this.preemptBackground("superseded by a newer background task");
|
|
16555
|
-
await this.whenSettled(
|
|
16840
|
+
await this.whenSettled(options2.settleMs ?? this.debounceMs * 4);
|
|
16556
16841
|
const abort = new AbortController();
|
|
16557
16842
|
this.backgroundAbort = abort;
|
|
16558
16843
|
try {
|
|
@@ -16967,13 +17252,13 @@ var Graph = class _Graph {
|
|
|
16967
17252
|
* them the result is `deferred: true` — a module's parameters are only known
|
|
16968
17253
|
* once its code declares them, which happens on the next cook.
|
|
16969
17254
|
*/
|
|
16970
|
-
retargetDefinition(nodeId, modulePath, source, code,
|
|
17255
|
+
retargetDefinition(nodeId, modulePath, source, code, options2 = {}) {
|
|
16971
17256
|
const blank = () => ({ kept: [], defaulted: [], dropped: [], retyped: [] });
|
|
16972
17257
|
const node = this.getNode(nodeId);
|
|
16973
17258
|
if (!node) {
|
|
16974
17259
|
return { ok: false, deferred: false, ...blank(), error: `no node with id ${nodeId}` };
|
|
16975
17260
|
}
|
|
16976
|
-
const preserve =
|
|
17261
|
+
const preserve = options2.preserveParameters !== false;
|
|
16977
17262
|
if (preserve) node.beginParameterCarryOver();
|
|
16978
17263
|
node.modulePath = modulePath;
|
|
16979
17264
|
node.sourceType = source;
|
|
@@ -16985,8 +17270,8 @@ var Graph = class _Graph {
|
|
|
16985
17270
|
console.warn("Failed to compile " + modulePath + ":", error);
|
|
16986
17271
|
});
|
|
16987
17272
|
node.markDirty();
|
|
16988
|
-
if (preserve &&
|
|
16989
|
-
const report = node.applyParameterDeclarations(
|
|
17273
|
+
if (preserve && options2.parameters) {
|
|
17274
|
+
const report = node.applyParameterDeclarations(options2.parameters) ?? blank();
|
|
16990
17275
|
return { ok: true, deferred: false, ...report };
|
|
16991
17276
|
}
|
|
16992
17277
|
return { ok: true, deferred: preserve, ...blank() };
|
|
@@ -18157,10 +18442,10 @@ async function installHeadlessCanvas() {
|
|
|
18157
18442
|
const canvas = await loadCanvasModule();
|
|
18158
18443
|
const globals2 = globalThis;
|
|
18159
18444
|
class HeadlessOffscreenCanvas extends canvas.Canvas {
|
|
18160
|
-
async convertToBlob(
|
|
18161
|
-
const type =
|
|
18445
|
+
async convertToBlob(options2 = {}) {
|
|
18446
|
+
const type = options2.type ?? "image/png";
|
|
18162
18447
|
const format2 = type.replace(/^image\//, "");
|
|
18163
|
-
const quality =
|
|
18448
|
+
const quality = options2.quality === void 0 ? void 0 : Math.round(options2.quality * 100);
|
|
18164
18449
|
return new Blob([await this.encode(format2, quality)], { type });
|
|
18165
18450
|
}
|
|
18166
18451
|
}
|
|
@@ -18456,8 +18741,8 @@ var cascade = new CascadeContext();
|
|
|
18456
18741
|
|
|
18457
18742
|
// src/engine/animation/frameRange.ts
|
|
18458
18743
|
init_animation2();
|
|
18459
|
-
async function evaluateFrameRange(
|
|
18460
|
-
const { fps, context = cascade, ...rest } =
|
|
18744
|
+
async function evaluateFrameRange(options2) {
|
|
18745
|
+
const { fps, context = cascade, ...rest } = options2;
|
|
18461
18746
|
const previousFps = context.fps();
|
|
18462
18747
|
if (fps !== void 0) context.setFps(fps);
|
|
18463
18748
|
try {
|
|
@@ -18497,8 +18782,8 @@ function outputPorts(graph, entryNode) {
|
|
|
18497
18782
|
function outputSnapshot(graph) {
|
|
18498
18783
|
return JSON.stringify(graph.nodes.map((node) => [node.id, node.outputs.map((port) => port.value ?? null)]));
|
|
18499
18784
|
}
|
|
18500
|
-
async function cookUntilSettled(graph, entryNode,
|
|
18501
|
-
const { fixpoint = false, passes = 8 } =
|
|
18785
|
+
async function cookUntilSettled(graph, entryNode, options2 = {}) {
|
|
18786
|
+
const { fixpoint = false, passes = 8 } = options2;
|
|
18502
18787
|
const dirtyAll = () => {
|
|
18503
18788
|
for (const node of graph.nodes) node.markDirty?.();
|
|
18504
18789
|
};
|
|
@@ -18520,8 +18805,8 @@ async function cookUntilSettled(graph, entryNode, options = {}) {
|
|
|
18520
18805
|
}
|
|
18521
18806
|
throw new Error(`graph did not settle after ${passes} cook passes`);
|
|
18522
18807
|
}
|
|
18523
|
-
async function renderFrameRange(
|
|
18524
|
-
const { graph, project, out, start, end, step: step2, fps, entryNode, verbose, signal } =
|
|
18808
|
+
async function renderFrameRange(options2) {
|
|
18809
|
+
const { graph, project, out, start, end, step: step2, fps, entryNode, verbose, signal } = options2;
|
|
18525
18810
|
cascade.setGraph(graph);
|
|
18526
18811
|
const outDirectory = project.resolve(out);
|
|
18527
18812
|
await fs10.mkdir(outDirectory, { recursive: true });
|
|
@@ -21629,8 +21914,8 @@ function reportMissingCanvas(messages, canvasError) {
|
|
|
21629
21914
|
if (canvasError && messages.some(looksLikeCanvasFailure)) console.error(`
|
|
21630
21915
|
${MISSING_CANVAS_MESSAGE}`);
|
|
21631
21916
|
}
|
|
21632
|
-
async function runGraph(
|
|
21633
|
-
const { file, entryNode, validateOnly, checkOnly, inspectOnly, verbose, frames, fps, out } =
|
|
21917
|
+
async function runGraph(options2) {
|
|
21918
|
+
const { file, entryNode, validateOnly, checkOnly, inspectOnly, verbose, frames, fps, out } = options2;
|
|
21634
21919
|
if (verbose) {
|
|
21635
21920
|
console.log(`Loading graph from: ${file}`);
|
|
21636
21921
|
}
|
|
@@ -21710,11 +21995,11 @@ async function runGraph(options) {
|
|
|
21710
21995
|
});
|
|
21711
21996
|
if (rendered) {
|
|
21712
21997
|
releaseHost();
|
|
21713
|
-
if (
|
|
21998
|
+
if (options2.json) process.stdout.write(JSON.stringify({ status: "completed", graph: path13.resolve(file), ...rendered }) + "\n");
|
|
21714
21999
|
else console.log(`Rendered ${rendered.frames.length} frames, ${rendered.files.length} files -> ${out ?? "renders"}/`);
|
|
21715
22000
|
return;
|
|
21716
22001
|
}
|
|
21717
|
-
if (
|
|
22002
|
+
if (options2.json) throw new Error("--json rendering requires a fully definition-v1 graph");
|
|
21718
22003
|
} else if (await runDeterministicProjectGraph(file, graphData, entryNode)) {
|
|
21719
22004
|
if (verbose) console.log("Graph execution completed");
|
|
21720
22005
|
releaseHost();
|
|
@@ -22000,7 +22285,7 @@ image output nothing downstream consumes, or per output of --entry-node.
|
|
|
22000
22285
|
console.error(`Error: File not found: ${fileArg}`);
|
|
22001
22286
|
process.exit(1);
|
|
22002
22287
|
}
|
|
22003
|
-
const
|
|
22288
|
+
const options2 = {
|
|
22004
22289
|
file: fileArg,
|
|
22005
22290
|
validateOnly: command === "validate",
|
|
22006
22291
|
checkOnly: command === "check",
|
|
@@ -22008,11 +22293,11 @@ image output nothing downstream consumes, or per output of --entry-node.
|
|
|
22008
22293
|
};
|
|
22009
22294
|
const verboseIndex = args.indexOf("--verbose") !== -1 ? args.indexOf("--verbose") : args.indexOf("-v");
|
|
22010
22295
|
if (verboseIndex !== -1) {
|
|
22011
|
-
|
|
22296
|
+
options2.verbose = true;
|
|
22012
22297
|
}
|
|
22013
22298
|
const entryNodeIndex = args.indexOf("--entry-node");
|
|
22014
22299
|
if (entryNodeIndex !== -1 && args[entryNodeIndex + 1]) {
|
|
22015
|
-
|
|
22300
|
+
options2.entryNode = args[entryNodeIndex + 1];
|
|
22016
22301
|
}
|
|
22017
22302
|
const valueOf = (flag) => {
|
|
22018
22303
|
const index = args.indexOf(flag);
|
|
@@ -22025,7 +22310,7 @@ image output nothing downstream consumes, or per output of --entry-node.
|
|
|
22025
22310
|
return value;
|
|
22026
22311
|
};
|
|
22027
22312
|
const frames = valueOf("--frames");
|
|
22028
|
-
if (frames)
|
|
22313
|
+
if (frames) options2.frames = frames;
|
|
22029
22314
|
const fps = valueOf("--fps");
|
|
22030
22315
|
if (fps !== void 0) {
|
|
22031
22316
|
const rate = Number(fps);
|
|
@@ -22033,13 +22318,13 @@ image output nothing downstream consumes, or per output of --entry-node.
|
|
|
22033
22318
|
console.error(`Error: --fps must be a positive number (got "${fps}")`);
|
|
22034
22319
|
process.exit(1);
|
|
22035
22320
|
}
|
|
22036
|
-
|
|
22321
|
+
options2.fps = rate;
|
|
22037
22322
|
}
|
|
22038
22323
|
const out = valueOf("--out");
|
|
22039
|
-
if (out)
|
|
22324
|
+
if (out) options2.out = out;
|
|
22040
22325
|
if (args.includes("--json")) {
|
|
22041
|
-
if (command !== "run" || !
|
|
22042
|
-
|
|
22326
|
+
if (command !== "run" || !options2.frames) throw new Error("--json requires run --frames (use --frames 1 for a still)");
|
|
22327
|
+
options2.json = true;
|
|
22043
22328
|
}
|
|
22044
22329
|
const timeout = valueOf("--timeout");
|
|
22045
22330
|
if (timeout !== void 0) {
|
|
@@ -22054,11 +22339,11 @@ image output nothing downstream consumes, or per output of --entry-node.
|
|
|
22054
22339
|
return;
|
|
22055
22340
|
}
|
|
22056
22341
|
try {
|
|
22057
|
-
if (
|
|
22058
|
-
await runGraph(
|
|
22342
|
+
if (options2.json) console.log = console.error;
|
|
22343
|
+
await runGraph(options2);
|
|
22059
22344
|
} catch (error) {
|
|
22060
22345
|
console.error(`Error: ${error.message}`);
|
|
22061
|
-
if (
|
|
22346
|
+
if (options2.verbose && error.stack) {
|
|
22062
22347
|
console.error(error.stack);
|
|
22063
22348
|
}
|
|
22064
22349
|
process.exit(1);
|