@field/cascade 0.2.22 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +47 -7
- package/ARCHITECTURE.md +30 -2
- package/CHANGELOG.md +89 -0
- package/DESIGN.md +10 -5
- package/README.md +103 -7
- package/dist/assets/CodeEditor-BADFbTJS.js +623 -0
- package/dist/assets/CodePanel-faK6PRfz.js +2 -0
- package/dist/assets/CustomNodeDialog-DhlKuviy.js +1 -0
- package/dist/assets/{ExportDialog-DWN4nhXI.js → ExportDialog-BJu2Bpvv.js} +2 -2
- package/dist/assets/ProjectSettings-D6a6kjqR.js +2 -0
- package/dist/assets/SettingsDialog-DJZdIvLC.js +1 -0
- package/dist/assets/VersionHistoryDialog-C1X3HOhc.js +3 -0
- package/dist/assets/{core-Bji4aZUU.js → core-CiuiuWZi.js} +29 -38
- package/dist/assets/{cssMode-B6Z_Q1Kh.js → cssMode-D-NwZSMJ.js} +1 -1
- package/dist/assets/{editor.api-jMoW_43X.js → editor.api-DT3WEvBd.js} +1 -1
- package/dist/assets/{freemarker2-DvvPV6m5.js → freemarker2-eKNYQaiz.js} +1 -1
- package/dist/assets/geo-DUvVbLnx.js +1 -0
- package/dist/assets/{handlebars-B8rfuSIa.js → handlebars-C2w1ggK2.js} +1 -1
- package/dist/assets/{html-DyHm6JCp.js → html-DQb41jyo.js} +1 -1
- package/dist/assets/{htmlMode-E9XLWE5u.js → htmlMode-IhNlh6Lv.js} +1 -1
- package/dist/assets/{image-BUcQC7PG.js → image-DMCXBY-_.js} +26 -40
- package/dist/assets/index-BDV5xGBZ.css +1 -0
- package/dist/assets/index-HTCN44kj.js +212 -0
- package/dist/assets/index-client-BoJgsN9M.js +1 -0
- package/dist/assets/{javascript-C_bM5PCN.js → javascript-BIT6jMLC.js} +1 -1
- package/dist/assets/{jsonMode-BdyVS7G4.js → jsonMode-CNfyB1ro.js} +1 -1
- package/dist/assets/{legacy-DIu3XRwl.js → legacy-CAj2_7QE.js} +2 -2
- package/dist/assets/{liquid-CDkn3spA.js → liquid-CmSmJmOG.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-AB5DMAsr.js → lspLanguageFeatures-BqMm3uMP.js} +1 -1
- package/dist/assets/{mdx-BvH_NjDN.js → mdx-6r6YgOFw.js} +1 -1
- package/dist/assets/{nodeTypeUtils-CweA3NHd.js → nodeTypeUtils-BBA1JqHx.js} +1 -1
- package/dist/assets/{python-B7uii4fi.js → python-x1H0TQuI.js} +1 -1
- package/dist/assets/{razor-Z48fWdJc.js → razor-Dzl1vZFm.js} +1 -1
- package/dist/assets/{tsMode-BDgacVG4.js → tsMode-n6DMMe3a.js} +1 -1
- package/dist/assets/{typescript-Derb6Oqa.js → typescript-ziEz65xN.js} +1 -1
- package/dist/assets/{workers-BtoMX_pm.js → workers-D-qUdp-r.js} +1 -1
- package/dist/assets/{xml-B1CaFSrG.js → xml-DMZjt5lE.js} +1 -1
- package/dist/assets/{yaml-HmIeA0KH.js → yaml-DFe5qZSO.js} +1 -1
- package/dist/cli/index.js +16194 -10195
- package/dist/cli/runtime/io.ts +93 -7
- package/dist/contracts/animation.d.ts +40 -0
- package/dist/contracts/animation.js +14 -0
- package/dist/contracts/definition.d.ts +39 -1
- package/dist/contracts/document.d.ts +15 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/validate.d.ts +10 -1
- package/dist/contracts/validate.js +9 -1
- package/dist/graphs/default.cascade +1 -1
- package/dist/index.html +5 -5
- package/dist/io.d.ts +196 -0
- package/dist/io.js +303 -0
- package/dist/net.d.ts +1 -0
- package/dist/net.js +28 -0
- package/dist/runtime/animation/channel.d.ts +108 -0
- package/dist/runtime/animation/channel.js +204 -0
- package/dist/runtime/animation/frameRange.d.ts +78 -0
- package/dist/runtime/animation/frameRange.js +76 -0
- package/dist/runtime/animation/index.d.ts +10 -0
- package/dist/runtime/animation/index.js +8 -0
- package/dist/runtime/builtins/core/random.d.ts +1 -1
- package/dist/runtime/builtins/core/remap.d.ts +1 -1
- package/dist/runtime/builtins/geo/copyToPoints.d.ts +1 -1
- package/dist/runtime/builtins/geo/copyToPoints.js +1 -1
- package/dist/runtime/builtins/geo/generators.d.ts +1 -1
- package/dist/runtime/builtins/geo/merge.d.ts +1 -1
- package/dist/runtime/builtins/geo/svgExport.d.ts +1 -1
- package/dist/runtime/builtins/geo/svgExport.js +1 -1
- package/dist/runtime/builtins/geo/transform.d.ts +1 -1
- package/dist/runtime/builtins/geo/transform.js +1 -1
- package/dist/runtime/definition/architecture.d.ts +1 -1
- package/dist/runtime/definition/extract.d.ts +1 -1
- package/dist/runtime/definition/extract.js +1 -1
- package/dist/runtime/error.d.ts +1 -1
- package/dist/runtime/expressions/evaluator.d.ts +53 -0
- package/dist/runtime/expressions/evaluator.js +193 -0
- package/dist/runtime/expressions/index.d.ts +15 -0
- package/dist/runtime/expressions/index.js +12 -0
- package/dist/runtime/expressions/math.d.ts +75 -0
- package/dist/runtime/expressions/math.js +140 -0
- package/dist/runtime/expressions/preprocess.d.ts +33 -0
- package/dist/runtime/expressions/preprocess.js +102 -0
- package/dist/runtime/expressions/scope.d.ts +27 -0
- package/dist/runtime/expressions/scope.js +10 -0
- package/dist/runtime/expressions/time.d.ts +54 -0
- package/dist/runtime/expressions/time.js +71 -0
- package/dist/runtime/expressions/types.d.ts +66 -0
- package/dist/runtime/expressions/types.js +9 -0
- package/dist/runtime/geometry/attributes.d.ts +2 -2
- package/dist/runtime/geometry/attributes.js +1 -1
- package/dist/runtime/geometry/builder.d.ts +1 -1
- package/dist/runtime/geometry/builder.js +1 -1
- package/dist/runtime/geometry/copy.d.ts +1 -1
- package/dist/runtime/geometry/copy.js +1 -1
- package/dist/runtime/geometry/generate.d.ts +1 -1
- package/dist/runtime/geometry/groups.d.ts +1 -1
- package/dist/runtime/geometry/groups.js +1 -1
- package/dist/runtime/geometry/matrix.d.ts +1 -1
- package/dist/runtime/geometry/merge.d.ts +1 -1
- package/dist/runtime/geometry/merge.js +1 -1
- package/dist/runtime/geometry/primitives.d.ts +1 -1
- package/dist/runtime/geometry/primitives.js +1 -1
- package/dist/runtime/geometry/promote.d.ts +1 -1
- package/dist/runtime/geometry/promote.js +1 -1
- package/dist/runtime/geometry/resample.d.ts +1 -1
- package/dist/runtime/geometry/resample.js +1 -1
- package/dist/runtime/geometry/svg.d.ts +1 -1
- package/dist/runtime/geometry/svg.js +1 -1
- package/dist/runtime/geometry/transform.d.ts +1 -1
- package/dist/runtime/geometry/transform.js +1 -1
- package/dist/runtime/index.d.ts +4 -1
- package/dist/runtime/index.js +4 -1
- package/dist/runtime/params/animator.d.ts +74 -0
- package/dist/runtime/params/animator.js +137 -0
- package/dist/runtime/params/index.d.ts +11 -0
- package/dist/runtime/params/index.js +9 -0
- package/dist/runtime/params/resolve.d.ts +73 -0
- package/dist/runtime/params/resolve.js +62 -0
- package/dist/runtime/runtime.d.ts +22 -0
- package/dist/runtime/runtime.js +242 -14
- package/dist/runtime/types.d.ts +30 -4
- package/dist/shell.d.ts +3 -3
- package/doc/NODE_REFERENCE.md +395 -0
- package/doc/PROJECT_AUTHORING.md +148 -6
- package/package.json +26 -3
- package/dist/assets/CodeEditor-DoaNEUaM.js +0 -641
- package/dist/assets/CodePanel-B0_2XJ-t.js +0 -2
- package/dist/assets/CustomNodeDialog-026lzecD.js +0 -1
- package/dist/assets/ProjectSettings-BzT164Yx.js +0 -2
- package/dist/assets/SettingsDialog-DmHb1V0r.js +0 -1
- package/dist/assets/VersionHistoryDialog-hH6VsXLX.js +0 -3
- package/dist/assets/geo-CXmCtzMM.js +0 -2
- package/dist/assets/index-BXYXSdgh.js +0 -224
- package/dist/assets/index-CrNke7SW.css +0 -1
- package/dist/assets/index-client-DN_FvjN8.js +0 -1
- package/dist/assets/quill-DjZ69wL_.js +0 -121
- package/dist/cli/index.js.map +0 -7
- package/dist/contracts/capabilities.d.ts.map +0 -1
- package/dist/contracts/capabilities.js.map +0 -1
- package/dist/contracts/color.d.ts.map +0 -1
- package/dist/contracts/color.js.map +0 -1
- package/dist/contracts/definition.d.ts.map +0 -1
- package/dist/contracts/definition.js.map +0 -1
- package/dist/contracts/document.d.ts.map +0 -1
- package/dist/contracts/document.js.map +0 -1
- package/dist/contracts/geometry.d.ts.map +0 -1
- package/dist/contracts/geometry.js.map +0 -1
- package/dist/contracts/index.d.ts.map +0 -1
- package/dist/contracts/index.js.map +0 -1
- package/dist/contracts/schema.d.ts.map +0 -1
- package/dist/contracts/schema.js.map +0 -1
- package/dist/contracts/validate.d.ts.map +0 -1
- package/dist/contracts/validate.js.map +0 -1
- package/dist/contracts/values.d.ts.map +0 -1
- package/dist/contracts/values.js.map +0 -1
- package/dist/graphs/default-orig.cascade +0 -128
- package/dist/runtime/browser.d.ts.map +0 -1
- package/dist/runtime/browser.js.map +0 -1
- package/dist/runtime/builtins/core/index.d.ts.map +0 -1
- package/dist/runtime/builtins/core/index.js.map +0 -1
- package/dist/runtime/builtins/core/random.d.ts.map +0 -1
- package/dist/runtime/builtins/core/random.js.map +0 -1
- package/dist/runtime/builtins/core/remap.d.ts.map +0 -1
- package/dist/runtime/builtins/core/remap.js.map +0 -1
- package/dist/runtime/builtins/core/routing.d.ts.map +0 -1
- package/dist/runtime/builtins/core/routing.js.map +0 -1
- package/dist/runtime/builtins/core/structural.d.ts.map +0 -1
- package/dist/runtime/builtins/core/structural.js.map +0 -1
- package/dist/runtime/builtins/geo/copyToPoints.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/copyToPoints.js.map +0 -1
- package/dist/runtime/builtins/geo/definitions.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/definitions.js.map +0 -1
- package/dist/runtime/builtins/geo/generators.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/generators.js.map +0 -1
- package/dist/runtime/builtins/geo/index.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/index.js.map +0 -1
- package/dist/runtime/builtins/geo/merge.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/merge.js.map +0 -1
- package/dist/runtime/builtins/geo/namespace.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/namespace.js.map +0 -1
- package/dist/runtime/builtins/geo/svgExport.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/svgExport.js.map +0 -1
- package/dist/runtime/builtins/geo/transform.d.ts.map +0 -1
- package/dist/runtime/builtins/geo/transform.js.map +0 -1
- package/dist/runtime/builtins/index.d.ts.map +0 -1
- package/dist/runtime/builtins/index.js.map +0 -1
- package/dist/runtime/definition/architecture.d.ts.map +0 -1
- package/dist/runtime/definition/architecture.js.map +0 -1
- package/dist/runtime/definition/extract.d.ts.map +0 -1
- package/dist/runtime/definition/extract.js.map +0 -1
- package/dist/runtime/error.d.ts.map +0 -1
- package/dist/runtime/error.js.map +0 -1
- package/dist/runtime/geometry/attributes.d.ts.map +0 -1
- package/dist/runtime/geometry/attributes.js.map +0 -1
- package/dist/runtime/geometry/builder.d.ts.map +0 -1
- package/dist/runtime/geometry/builder.js.map +0 -1
- package/dist/runtime/geometry/copy.d.ts.map +0 -1
- package/dist/runtime/geometry/copy.js.map +0 -1
- package/dist/runtime/geometry/generate.d.ts.map +0 -1
- package/dist/runtime/geometry/generate.js.map +0 -1
- package/dist/runtime/geometry/groups.d.ts.map +0 -1
- package/dist/runtime/geometry/groups.js.map +0 -1
- package/dist/runtime/geometry/index.d.ts.map +0 -1
- package/dist/runtime/geometry/index.js.map +0 -1
- package/dist/runtime/geometry/matrix.d.ts.map +0 -1
- package/dist/runtime/geometry/matrix.js.map +0 -1
- package/dist/runtime/geometry/merge.d.ts.map +0 -1
- package/dist/runtime/geometry/merge.js.map +0 -1
- package/dist/runtime/geometry/primitives.d.ts.map +0 -1
- package/dist/runtime/geometry/primitives.js.map +0 -1
- package/dist/runtime/geometry/promote.d.ts.map +0 -1
- package/dist/runtime/geometry/promote.js.map +0 -1
- package/dist/runtime/geometry/resample.d.ts.map +0 -1
- package/dist/runtime/geometry/resample.js.map +0 -1
- package/dist/runtime/geometry/svg.d.ts.map +0 -1
- package/dist/runtime/geometry/svg.js.map +0 -1
- package/dist/runtime/geometry/transform.d.ts.map +0 -1
- package/dist/runtime/geometry/transform.js.map +0 -1
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/node.d.ts.map +0 -1
- package/dist/runtime/node.js.map +0 -1
- package/dist/runtime/runtime.d.ts.map +0 -1
- package/dist/runtime/runtime.js.map +0 -1
- package/dist/runtime/types.d.ts.map +0 -1
- package/dist/runtime/types.js.map +0 -1
- package/dist/shell.js.map +0 -7
- package/dist/stage.js.map +0 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Color, isStringAttribute, } from "cascade/contracts";
|
|
1
|
+
import { Color, isStringAttribute, } from "@field/cascade/contracts";
|
|
2
2
|
import { geometryError, numericAttribute, positionAttribute, readComponent, } from "./attributes.js";
|
|
3
3
|
import { groupNames } from "./groups.js";
|
|
4
4
|
import { bezierSegments, geometryBounds, isBezier, isClosed, loosePointMask, primitivePoints, } from "./primitives.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Geometry, type Mat3, type Mat4 } from "cascade/contracts";
|
|
1
|
+
import { type Geometry, type Mat3, type Mat4 } from "@field/cascade/contracts";
|
|
2
2
|
/**
|
|
3
3
|
* Transform `P`. Matrices are column-major, as the `mat3` and `mat4` types are
|
|
4
4
|
* already documented to be, so a `mat3`'s third column carries the 2D
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { POSITION_ATTRIBUTE, } from "cascade/contracts";
|
|
1
|
+
import { POSITION_ATTRIBUTE, } from "@field/cascade/contracts";
|
|
2
2
|
import { attributeSet, copyAttributeArray, geometryError, positionAttribute, withAttributeSet, } from "./attributes.js";
|
|
3
3
|
/**
|
|
4
4
|
* Transform `P`. Matrices are column-major, as the `mat3` and `mat4` types are
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { CascadeRuntimeError } from "./error.js";
|
|
2
|
+
export * from "./animation/index.js";
|
|
3
|
+
export * from "./expressions/index.js";
|
|
2
4
|
export * from "./geometry/index.js";
|
|
3
|
-
export
|
|
5
|
+
export * from "./params/index.js";
|
|
6
|
+
export { createRuntime, PREFLIGHT_WARNING_CODES } from "./runtime.js";
|
|
4
7
|
export type * from "./types.js";
|
|
5
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export { CascadeRuntimeError } from "./error.js";
|
|
2
|
+
export * from "./animation/index.js";
|
|
3
|
+
export * from "./expressions/index.js";
|
|
2
4
|
export * from "./geometry/index.js";
|
|
3
|
-
export
|
|
5
|
+
export * from "./params/index.js";
|
|
6
|
+
export { createRuntime, PREFLIGHT_WARNING_CODES } from "./runtime.js";
|
|
4
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolving a graph's bound parameters at a frame.
|
|
3
|
+
*
|
|
4
|
+
* `resolvePropBinding` answers "what is this one parameter worth" and owns the
|
|
5
|
+
* order. This is the layer above it: a graph's worth of parameters, an
|
|
6
|
+
* expression engine bound to that graph, and the frame they are all resolved
|
|
7
|
+
* at. The deterministic runtime had neither half — it read `saved.value` and
|
|
8
|
+
* stopped — so a definition-v1 prop carrying `$T` or a drawn curve rendered as
|
|
9
|
+
* a constant offline while the same document animated in Studio.
|
|
10
|
+
*
|
|
11
|
+
* It is generic over the node rather than importing the runtime's own, so this
|
|
12
|
+
* file has no dependency on `runtime.ts` and can be exercised on its own.
|
|
13
|
+
*
|
|
14
|
+
* Resolution is LAZY and cycle-guarded, which is not a detail: `ch('../a/x')`
|
|
15
|
+
* may name a parameter that is itself an expression, and resolving in node
|
|
16
|
+
* order would hand out last frame's value for half the graph depending on
|
|
17
|
+
* where the reference pointed. Pulling on demand gives the same answer
|
|
18
|
+
* whatever order the nodes are in, which is the whole promise of the word
|
|
19
|
+
* deterministic.
|
|
20
|
+
*/
|
|
21
|
+
import type { PropBinding } from "./resolve.js";
|
|
22
|
+
/** The minimum a node must be for its parameters to be resolvable. */
|
|
23
|
+
export interface AnimatableNode {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
/** Resolved values, written by `resolveAll`. */
|
|
26
|
+
readonly props: Record<string, unknown>;
|
|
27
|
+
readonly inputs: Record<string, unknown>;
|
|
28
|
+
/** Only the props that carry an expression or a channel. */
|
|
29
|
+
readonly bindings: Record<string, PropBinding>;
|
|
30
|
+
}
|
|
31
|
+
export interface PropAnimatorTopology<TNode extends AnimatableNode> {
|
|
32
|
+
readonly nodes: readonly TNode[];
|
|
33
|
+
node(id: string): TNode | undefined;
|
|
34
|
+
/** The node feeding `node`'s data input at `index`, for `opinput()`. */
|
|
35
|
+
inputNode(node: TNode, index: number): TNode | null;
|
|
36
|
+
/** A failed expression. The parameter has already fallen back to its stored
|
|
37
|
+
* value; this is so the host can say so rather than render a wrong number
|
|
38
|
+
* in silence. */
|
|
39
|
+
report?(nodeId: string, propName: string, error: string): void;
|
|
40
|
+
}
|
|
41
|
+
export declare class PropAnimator<TNode extends AnimatableNode> {
|
|
42
|
+
private readonly topology;
|
|
43
|
+
private readonly evaluator;
|
|
44
|
+
private readonly resolving;
|
|
45
|
+
constructor(topology: PropAnimatorTopology<TNode>);
|
|
46
|
+
/** True when any parameter in the graph is bound at all — so a host can skip
|
|
47
|
+
* the whole pass, and a graph with no animation costs nothing. */
|
|
48
|
+
get animated(): boolean;
|
|
49
|
+
setFrame(frame: number): void;
|
|
50
|
+
setFps(fps: number): void;
|
|
51
|
+
/** Write every bound parameter's value at the current frame into `props`. */
|
|
52
|
+
resolveAll(): void;
|
|
53
|
+
/**
|
|
54
|
+
* One parameter, at the current frame.
|
|
55
|
+
*
|
|
56
|
+
* Re-entry returns the stored value rather than throwing: a parameter whose
|
|
57
|
+
* expression refers back to itself is an author's mistake, and the render
|
|
58
|
+
* that names it is more use than the one that dies.
|
|
59
|
+
*/
|
|
60
|
+
private resolve;
|
|
61
|
+
/**
|
|
62
|
+
* The host binding the expression engine reads through.
|
|
63
|
+
*
|
|
64
|
+
* A path names a parameter — `./radius`, `../blur1/amount`,
|
|
65
|
+
* `/root/blur1/amount` — and the last segment is always the parameter, the
|
|
66
|
+
* one before it the node. Anything a graph does not have resolves to null,
|
|
67
|
+
* which the engine turns into 0 / '' / [] per accessor rather than an
|
|
68
|
+
* exception: one broken reference must not take a render down.
|
|
69
|
+
*/
|
|
70
|
+
private scope;
|
|
71
|
+
/** The node a path's leading segments name, or `from` when they name none. */
|
|
72
|
+
private owner;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=animator.d.ts.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolving a graph's bound parameters at a frame.
|
|
3
|
+
*
|
|
4
|
+
* `resolvePropBinding` answers "what is this one parameter worth" and owns the
|
|
5
|
+
* order. This is the layer above it: a graph's worth of parameters, an
|
|
6
|
+
* expression engine bound to that graph, and the frame they are all resolved
|
|
7
|
+
* at. The deterministic runtime had neither half — it read `saved.value` and
|
|
8
|
+
* stopped — so a definition-v1 prop carrying `$T` or a drawn curve rendered as
|
|
9
|
+
* a constant offline while the same document animated in Studio.
|
|
10
|
+
*
|
|
11
|
+
* It is generic over the node rather than importing the runtime's own, so this
|
|
12
|
+
* file has no dependency on `runtime.ts` and can be exercised on its own.
|
|
13
|
+
*
|
|
14
|
+
* Resolution is LAZY and cycle-guarded, which is not a detail: `ch('../a/x')`
|
|
15
|
+
* may name a parameter that is itself an expression, and resolving in node
|
|
16
|
+
* order would hand out last frame's value for half the graph depending on
|
|
17
|
+
* where the reference pointed. Pulling on demand gives the same answer
|
|
18
|
+
* whatever order the nodes are in, which is the whole promise of the word
|
|
19
|
+
* deterministic.
|
|
20
|
+
*/
|
|
21
|
+
import { ExpressionEvaluator } from "../expressions/evaluator.js";
|
|
22
|
+
import { isBoundProp, resolvePropBinding } from "./resolve.js";
|
|
23
|
+
export class PropAnimator {
|
|
24
|
+
topology;
|
|
25
|
+
evaluator;
|
|
26
|
+
resolving = new Set();
|
|
27
|
+
constructor(topology) {
|
|
28
|
+
this.topology = topology;
|
|
29
|
+
this.evaluator = new ExpressionEvaluator(this.scope());
|
|
30
|
+
}
|
|
31
|
+
/** True when any parameter in the graph is bound at all — so a host can skip
|
|
32
|
+
* the whole pass, and a graph with no animation costs nothing. */
|
|
33
|
+
get animated() {
|
|
34
|
+
return this.topology.nodes.some((node) => Object.values(node.bindings).some((binding) => isBoundProp(binding)));
|
|
35
|
+
}
|
|
36
|
+
setFrame(frame) {
|
|
37
|
+
this.evaluator.setFrame(frame);
|
|
38
|
+
}
|
|
39
|
+
setFps(fps) {
|
|
40
|
+
this.evaluator.setFps(fps);
|
|
41
|
+
}
|
|
42
|
+
/** Write every bound parameter's value at the current frame into `props`. */
|
|
43
|
+
resolveAll() {
|
|
44
|
+
for (const node of this.topology.nodes)
|
|
45
|
+
for (const name of Object.keys(node.bindings))
|
|
46
|
+
this.resolve(node, name);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* One parameter, at the current frame.
|
|
50
|
+
*
|
|
51
|
+
* Re-entry returns the stored value rather than throwing: a parameter whose
|
|
52
|
+
* expression refers back to itself is an author's mistake, and the render
|
|
53
|
+
* that names it is more use than the one that dies.
|
|
54
|
+
*/
|
|
55
|
+
resolve(node, name) {
|
|
56
|
+
const binding = node.bindings[name];
|
|
57
|
+
if (!binding)
|
|
58
|
+
return node.props[name];
|
|
59
|
+
const key = `${node.id}.${name}`;
|
|
60
|
+
if (this.resolving.has(key))
|
|
61
|
+
return binding.value;
|
|
62
|
+
this.resolving.add(key);
|
|
63
|
+
try {
|
|
64
|
+
const resolved = resolvePropBinding(binding, {
|
|
65
|
+
frame: this.evaluator.fframe,
|
|
66
|
+
evaluateExpression: (expression) => this.evaluator.evaluate(expression, node),
|
|
67
|
+
});
|
|
68
|
+
if (resolved.error)
|
|
69
|
+
this.topology.report?.(node.id, name, resolved.error);
|
|
70
|
+
node.props[name] = resolved.value;
|
|
71
|
+
return resolved.value;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
this.resolving.delete(key);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The host binding the expression engine reads through.
|
|
79
|
+
*
|
|
80
|
+
* A path names a parameter — `./radius`, `../blur1/amount`,
|
|
81
|
+
* `/root/blur1/amount` — and the last segment is always the parameter, the
|
|
82
|
+
* one before it the node. Anything a graph does not have resolves to null,
|
|
83
|
+
* which the engine turns into 0 / '' / [] per accessor rather than an
|
|
84
|
+
* exception: one broken reference must not take a render down.
|
|
85
|
+
*/
|
|
86
|
+
scope() {
|
|
87
|
+
return {
|
|
88
|
+
resolveParam: (from, path) => {
|
|
89
|
+
const segments = split(path);
|
|
90
|
+
if (!segments.length)
|
|
91
|
+
return null;
|
|
92
|
+
const name = segments[segments.length - 1];
|
|
93
|
+
const owner = this.owner(from, segments.slice(0, -1));
|
|
94
|
+
if (!owner)
|
|
95
|
+
return null;
|
|
96
|
+
// Through `resolve`, so a reference to a keyed or expressed parameter
|
|
97
|
+
// reads what it is worth at this frame rather than what it was saved
|
|
98
|
+
// as. Reading the stored value here is the bug that makes `ch()` look
|
|
99
|
+
// like it works until somebody keys the parameter it points at.
|
|
100
|
+
if (owner.bindings[name])
|
|
101
|
+
return { value: this.resolve(owner, name) };
|
|
102
|
+
if (name in owner.props)
|
|
103
|
+
return { value: owner.props[name] };
|
|
104
|
+
if (name in owner.inputs)
|
|
105
|
+
return { value: owner.inputs[name] };
|
|
106
|
+
return null;
|
|
107
|
+
},
|
|
108
|
+
nodeExists: (from, path) => {
|
|
109
|
+
const segments = split(path);
|
|
110
|
+
if (!segments.length)
|
|
111
|
+
return false;
|
|
112
|
+
const last = segments[segments.length - 1];
|
|
113
|
+
if (last === "..")
|
|
114
|
+
return true;
|
|
115
|
+
return last === from.id || !!this.topology.node(last);
|
|
116
|
+
},
|
|
117
|
+
inputNode: (from, index) => this.topology.inputNode(from, index),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** The node a path's leading segments name, or `from` when they name none. */
|
|
121
|
+
owner(from, segments) {
|
|
122
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
123
|
+
if (segments[i] === "..")
|
|
124
|
+
continue;
|
|
125
|
+
return this.topology.node(segments[i]);
|
|
126
|
+
}
|
|
127
|
+
return from;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** Path segments, with the no-ops (`.`, empty, a trailing root slash) dropped
|
|
131
|
+
* but `..` kept, because it is the one that means something. */
|
|
132
|
+
function split(path) {
|
|
133
|
+
return String(path ?? "")
|
|
134
|
+
.split("/")
|
|
135
|
+
.filter((segment) => segment.length > 0 && segment !== ".");
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=animator.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter resolution: the order in which a parameter becomes a value.
|
|
3
|
+
*
|
|
4
|
+
* One module, one order, both hosts. See ./resolve.ts for why evaluation
|
|
5
|
+
* itself is a callback rather than a dependency.
|
|
6
|
+
*/
|
|
7
|
+
export { PropAnimator } from "./animator.js";
|
|
8
|
+
export type { AnimatableNode, PropAnimatorTopology } from "./animator.js";
|
|
9
|
+
export { isBoundProp, resolvePropBinding, } from "./resolve.js";
|
|
10
|
+
export type { PropBinding, PropBindingSource, PropResolutionContext, ResolvedProp, } from "./resolve.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter resolution: the order in which a parameter becomes a value.
|
|
3
|
+
*
|
|
4
|
+
* One module, one order, both hosts. See ./resolve.ts for why evaluation
|
|
5
|
+
* itself is a callback rather than a dependency.
|
|
6
|
+
*/
|
|
7
|
+
export { PropAnimator } from "./animator.js";
|
|
8
|
+
export { isBoundProp, resolvePropBinding, } from "./resolve.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a parameter becomes a value.
|
|
3
|
+
*
|
|
4
|
+
* Three bindings, in one order: a keyframe channel, an expression, the stored
|
|
5
|
+
* value. That order was implemented once, in Studio's `Node.evalParm`, which
|
|
6
|
+
* meant the deterministic runtime had no answer at all — a definition-v1 prop
|
|
7
|
+
* carrying `$T` or a drawn curve rendered as a static number offline. Copying
|
|
8
|
+
* `evalParm` into the runtime would have produced a second answer to the same
|
|
9
|
+
* question, which is exactly the two-parameter-stores mistake this codebase
|
|
10
|
+
* has already paid for once. So the order moved here, into the neutral
|
|
11
|
+
* runtime, and both hosts call it.
|
|
12
|
+
*
|
|
13
|
+
* What it deliberately does NOT own: the expression *engine*. Evaluation is
|
|
14
|
+
* passed in as a callback, because each host has its own scope (Studio's
|
|
15
|
+
* `ExpressionEngine` reaches into the compatibility graph; the runtime binds
|
|
16
|
+
* its own node map) and its own error bookkeeping (Studio stores the message
|
|
17
|
+
* on the prop for the Inspector to show). Keeping evaluation out is also what
|
|
18
|
+
* keeps this module dependent on nothing but the channel sampler — no cycle
|
|
19
|
+
* between `animation` and `expressions`, and no clock anywhere: the frame is a
|
|
20
|
+
* value the caller hands in, which is what keeps a cook deterministic.
|
|
21
|
+
*/
|
|
22
|
+
import type { Channel } from "../animation/channel.js";
|
|
23
|
+
/**
|
|
24
|
+
* A parameter and everything bound to it. Structurally what Studio's `Prop`
|
|
25
|
+
* already is, and what `CascadeSerializedProp` deserialises to, so neither
|
|
26
|
+
* host has to build an adapter object to ask this question.
|
|
27
|
+
*/
|
|
28
|
+
export interface PropBinding {
|
|
29
|
+
/** The stored value — what the author typed, and what the file records. */
|
|
30
|
+
readonly value: unknown;
|
|
31
|
+
readonly expression?: string | undefined;
|
|
32
|
+
readonly channel?: Channel | null | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Which of the three bindings actually produced the value. */
|
|
35
|
+
export type PropBindingSource = "channel" | "expression" | "value";
|
|
36
|
+
export interface ResolvedProp {
|
|
37
|
+
readonly value: unknown;
|
|
38
|
+
readonly source: PropBindingSource;
|
|
39
|
+
/** An expression that failed. The value has fallen back to the stored one. */
|
|
40
|
+
readonly error?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface PropResolutionContext {
|
|
43
|
+
/** Fractional frame — a channel is sampled at it, and it is what the host's
|
|
44
|
+
* expression engine should already be set to. */
|
|
45
|
+
readonly frame: number;
|
|
46
|
+
/**
|
|
47
|
+
* Evaluate one expression. Omitted by a caller with no engine (a static
|
|
48
|
+
* inspection), in which case an expression is skipped rather than guessed
|
|
49
|
+
* at and the stored value stands.
|
|
50
|
+
*/
|
|
51
|
+
readonly evaluateExpression?: (expression: string) => {
|
|
52
|
+
value: unknown;
|
|
53
|
+
error?: string;
|
|
54
|
+
} | undefined;
|
|
55
|
+
}
|
|
56
|
+
/** True when a parameter carries something beyond its stored value, and so has
|
|
57
|
+
* to be resolved per frame rather than read once. */
|
|
58
|
+
export declare function isBoundProp(binding: PropBinding | null | undefined): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Resolve a parameter at a frame.
|
|
61
|
+
*
|
|
62
|
+
* A parameter may carry both a channel and an expression, and the channel
|
|
63
|
+
* wins. The expression is kept, inert, and comes back when the channel is
|
|
64
|
+
* deleted: silently discarding what an author wrote is the worse of the two
|
|
65
|
+
* failures. `contracts/animation.ts` states the same rule for the document, so
|
|
66
|
+
* the file format and the resolver agree by construction.
|
|
67
|
+
*
|
|
68
|
+
* An empty channel resolves to nothing rather than to zero, so a parameter
|
|
69
|
+
* whose last key was deleted falls through to its expression or its value
|
|
70
|
+
* instead of snapping to the origin.
|
|
71
|
+
*/
|
|
72
|
+
export declare function resolvePropBinding(binding: PropBinding, context: PropResolutionContext): ResolvedProp;
|
|
73
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a parameter becomes a value.
|
|
3
|
+
*
|
|
4
|
+
* Three bindings, in one order: a keyframe channel, an expression, the stored
|
|
5
|
+
* value. That order was implemented once, in Studio's `Node.evalParm`, which
|
|
6
|
+
* meant the deterministic runtime had no answer at all — a definition-v1 prop
|
|
7
|
+
* carrying `$T` or a drawn curve rendered as a static number offline. Copying
|
|
8
|
+
* `evalParm` into the runtime would have produced a second answer to the same
|
|
9
|
+
* question, which is exactly the two-parameter-stores mistake this codebase
|
|
10
|
+
* has already paid for once. So the order moved here, into the neutral
|
|
11
|
+
* runtime, and both hosts call it.
|
|
12
|
+
*
|
|
13
|
+
* What it deliberately does NOT own: the expression *engine*. Evaluation is
|
|
14
|
+
* passed in as a callback, because each host has its own scope (Studio's
|
|
15
|
+
* `ExpressionEngine` reaches into the compatibility graph; the runtime binds
|
|
16
|
+
* its own node map) and its own error bookkeeping (Studio stores the message
|
|
17
|
+
* on the prop for the Inspector to show). Keeping evaluation out is also what
|
|
18
|
+
* keeps this module dependent on nothing but the channel sampler — no cycle
|
|
19
|
+
* between `animation` and `expressions`, and no clock anywhere: the frame is a
|
|
20
|
+
* value the caller hands in, which is what keeps a cook deterministic.
|
|
21
|
+
*/
|
|
22
|
+
import { isEmptyChannel, sampleChannel } from "../animation/channel.js";
|
|
23
|
+
/** True when a parameter carries something beyond its stored value, and so has
|
|
24
|
+
* to be resolved per frame rather than read once. */
|
|
25
|
+
export function isBoundProp(binding) {
|
|
26
|
+
if (!binding)
|
|
27
|
+
return false;
|
|
28
|
+
return !!binding.expression || !isEmptyChannel(binding.channel);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve a parameter at a frame.
|
|
32
|
+
*
|
|
33
|
+
* A parameter may carry both a channel and an expression, and the channel
|
|
34
|
+
* wins. The expression is kept, inert, and comes back when the channel is
|
|
35
|
+
* deleted: silently discarding what an author wrote is the worse of the two
|
|
36
|
+
* failures. `contracts/animation.ts` states the same rule for the document, so
|
|
37
|
+
* the file format and the resolver agree by construction.
|
|
38
|
+
*
|
|
39
|
+
* An empty channel resolves to nothing rather than to zero, so a parameter
|
|
40
|
+
* whose last key was deleted falls through to its expression or its value
|
|
41
|
+
* instead of snapping to the origin.
|
|
42
|
+
*/
|
|
43
|
+
export function resolvePropBinding(binding, context) {
|
|
44
|
+
if (!isEmptyChannel(binding.channel)) {
|
|
45
|
+
const sampled = sampleChannel(binding.channel, context.frame);
|
|
46
|
+
if (sampled !== undefined)
|
|
47
|
+
return { value: sampled, source: "channel" };
|
|
48
|
+
}
|
|
49
|
+
if (binding.expression && context.evaluateExpression) {
|
|
50
|
+
const result = context.evaluateExpression(binding.expression);
|
|
51
|
+
// A failed expression falls back to the stored value and reports why. The
|
|
52
|
+
// alternative — a hole in the middle of a render — is the one outcome
|
|
53
|
+
// nobody can act on.
|
|
54
|
+
if (result?.error) {
|
|
55
|
+
return { value: binding.value, source: "value", error: result.error };
|
|
56
|
+
}
|
|
57
|
+
if (result)
|
|
58
|
+
return { value: result.value, source: "expression" };
|
|
59
|
+
}
|
|
60
|
+
return { value: binding.value, source: "value" };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -1,3 +1,25 @@
|
|
|
1
1
|
import type { CascadeRuntime, CreateRuntimeOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Preflight codes that describe something other than "this graph cannot run
|
|
4
|
+
* here", so `run` proceeds and a checker reports them as warnings.
|
|
5
|
+
*
|
|
6
|
+
* False positives are worse than blindness: a validator that cries wolf gets
|
|
7
|
+
* ignored, and then it is no better than the one that saw nothing. So the line
|
|
8
|
+
* is drawn at what the diagnostic is about.
|
|
9
|
+
*
|
|
10
|
+
* `preflight-environment` is about the checker's reach — a node saying
|
|
11
|
+
* `runsOn: 'browser'` claims nothing about the CLI and is not defective
|
|
12
|
+
* because somebody validated it from a terminal.
|
|
13
|
+
*
|
|
14
|
+
* `stray-params` is about the document — values were lost on the way in, which
|
|
15
|
+
* is worth saying loudly and is not a reason to refuse to run: a graph with a
|
|
16
|
+
* leftover `params` array runs perfectly well on its defaults, which is
|
|
17
|
+
* precisely the problem.
|
|
18
|
+
*
|
|
19
|
+
* This set lives here rather than in the CLI because the run path and the
|
|
20
|
+
* check path both need it, and it was a duplicated rule that let `validate`
|
|
21
|
+
* and `check` pass graphs `run` then rejected.
|
|
22
|
+
*/
|
|
23
|
+
export declare const PREFLIGHT_WARNING_CODES: ReadonlySet<string>;
|
|
2
24
|
export declare function createRuntime(options: CreateRuntimeOptions): CascadeRuntime;
|
|
3
25
|
//# sourceMappingURL=runtime.d.ts.map
|