@motionscript/plot 0.0.0-stage → 0.1.0-alpha.3
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 +21 -0
- package/LICENSE +201 -0
- package/dist/browser/chunks/chunk-37IWXGPH.js +2 -0
- package/dist/browser/chunks/chunk-37IWXGPH.js.map +7 -0
- package/dist/browser/index.js +84 -0
- package/dist/browser/index.js.map +7 -0
- package/dist/browser/kit.js +2 -0
- package/dist/browser/kit.js.map +7 -0
- package/dist/browser/manifest.json +12 -0
- package/dist/engine.d.ts +14 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +14 -0
- package/dist/engine.js.map +1 -0
- package/dist/graph2d/curve-cache.d.ts +60 -0
- package/dist/graph2d/curve-cache.d.ts.map +1 -0
- package/dist/graph2d/curve-cache.js +79 -0
- package/dist/graph2d/curve-cache.js.map +1 -0
- package/dist/graph2d/curve-error.d.ts +12 -0
- package/dist/graph2d/curve-error.d.ts.map +1 -0
- package/dist/graph2d/curve-error.js +15 -0
- package/dist/graph2d/curve-error.js.map +1 -0
- package/dist/graph2d/curve.d.ts +104 -0
- package/dist/graph2d/curve.d.ts.map +1 -0
- package/dist/graph2d/curve.js +531 -0
- package/dist/graph2d/curve.js.map +1 -0
- package/dist/graph2d/graph2d.d.ts +164 -0
- package/dist/graph2d/graph2d.d.ts.map +1 -0
- package/dist/graph2d/graph2d.js +404 -0
- package/dist/graph2d/graph2d.js.map +1 -0
- package/dist/graph2d/index.d.ts +32 -0
- package/dist/graph2d/index.d.ts.map +1 -0
- package/dist/graph2d/index.js +32 -0
- package/dist/graph2d/index.js.map +1 -0
- package/dist/graph2d/plane-fill.d.ts +110 -0
- package/dist/graph2d/plane-fill.d.ts.map +1 -0
- package/dist/graph2d/plane-fill.js +248 -0
- package/dist/graph2d/plane-fill.js.map +1 -0
- package/dist/graph2d/plane.d.ts +179 -0
- package/dist/graph2d/plane.d.ts.map +1 -0
- package/dist/graph2d/plane.js +359 -0
- package/dist/graph2d/plane.js.map +1 -0
- package/dist/graph2d/shared.d.ts +40 -0
- package/dist/graph2d/shared.d.ts.map +1 -0
- package/dist/graph2d/shared.js +70 -0
- package/dist/graph2d/shared.js.map +1 -0
- package/dist/graph3d/expression.d.ts +30 -0
- package/dist/graph3d/expression.d.ts.map +1 -0
- package/dist/graph3d/expression.js +35 -0
- package/dist/graph3d/expression.js.map +1 -0
- package/dist/graph3d/graph3d.d.ts +186 -0
- package/dist/graph3d/graph3d.d.ts.map +1 -0
- package/dist/graph3d/graph3d.js +404 -0
- package/dist/graph3d/graph3d.js.map +1 -0
- package/dist/graph3d/index.d.ts +22 -0
- package/dist/graph3d/index.d.ts.map +1 -0
- package/dist/graph3d/index.js +22 -0
- package/dist/graph3d/index.js.map +1 -0
- package/dist/graph3d/shared.d.ts +61 -0
- package/dist/graph3d/shared.d.ts.map +1 -0
- package/dist/graph3d/shared.js +101 -0
- package/dist/graph3d/shared.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/kit/equations.d.ts +56 -0
- package/dist/kit/equations.d.ts.map +1 -0
- package/dist/kit/equations.js +63 -0
- package/dist/kit/equations.js.map +1 -0
- package/dist/kit/expression.d.ts +60 -0
- package/dist/kit/expression.d.ts.map +1 -0
- package/dist/kit/expression.js +268 -0
- package/dist/kit/expression.js.map +1 -0
- package/dist/kit/index.d.ts +15 -0
- package/dist/kit/index.d.ts.map +1 -0
- package/dist/kit/index.js +13 -0
- package/dist/kit/index.js.map +1 -0
- package/dist/nodes.d.ts +19 -0
- package/dist/nodes.d.ts.map +1 -0
- package/dist/nodes.js +19 -0
- package/dist/nodes.js.map +1 -0
- package/package.json +68 -3
- package/registry.json +34 -0
- package/src/engine.ts +13 -0
- package/src/graph2d/curve-cache.ts +103 -0
- package/src/graph2d/curve-error.ts +19 -0
- package/src/graph2d/curve.ts +657 -0
- package/src/graph2d/graph2d.ts +586 -0
- package/src/graph2d/index.ts +31 -0
- package/src/graph2d/plane-fill.ts +308 -0
- package/src/graph2d/plane.ts +457 -0
- package/src/graph2d/shared.ts +103 -0
- package/src/graph3d/expression.ts +51 -0
- package/src/graph3d/graph3d.ts +615 -0
- package/src/graph3d/index.ts +21 -0
- package/src/graph3d/shared.ts +143 -0
- package/src/index.ts +3 -0
- package/src/kit/equations.ts +102 -0
- package/src/kit/expression.ts +323 -0
- package/src/kit/index.ts +29 -0
- package/src/nodes.ts +19 -0
- package/README.md +0 -4
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The mappers and tweens the {@link Graph2D} node is built from — the same shape
|
|
3
|
+
* `graph3d/impl/shared.ts` has, and mostly the same short list, because a
|
|
4
|
+
* `@property` is only as good as the `mapper`/`tween` it is declared with.
|
|
5
|
+
*
|
|
6
|
+
* Almost everything here is a re-export. That is the point: the match-by-id
|
|
7
|
+
* equation tween lives in `nodes/graph-kit` because both graphs animate a list of
|
|
8
|
+
* equations the same way, and colour normalisation lives in `nodes/view3d-kit`
|
|
9
|
+
* because the 3D nodes needed it first. What is genuinely this node's own is one
|
|
10
|
+
* function: turning a two-argument compiled expression into the one-argument
|
|
11
|
+
* curve the sampler asks for, without losing the identity the tween compares.
|
|
12
|
+
*/
|
|
13
|
+
import { CURVE_VARIABLES, compileExpressionCached, lerpGraphEquations, } from "../kit/index.js";
|
|
14
|
+
/**
|
|
15
|
+
* Colour normalisation and its tween, plus the two number tweens that fix what a
|
|
16
|
+
* plain lerp gets wrong.
|
|
17
|
+
*
|
|
18
|
+
* They live in `view3d-kit` because the 3D nodes needed them first, and there is
|
|
19
|
+
* nothing three-dimensional about any of them — a `NormalizedColor` is an RGBA
|
|
20
|
+
* tuple, which is both interpolatable and still a valid `Color` to hand back to
|
|
21
|
+
* `Graphics`. Renamed on the way through so the call sites don't read as though
|
|
22
|
+
* this node draws in perspective.
|
|
23
|
+
*/
|
|
24
|
+
export { resolveColor3D as resolveColor, lerpColor3D as lerpColor, lerpCount, snapFlag, snapValue, } from "@motionscript/sdk/component";
|
|
25
|
+
/**
|
|
26
|
+
* Compiles `source` as `y = f(x)`, memoised, returning `null` for anything that
|
|
27
|
+
* doesn't parse.
|
|
28
|
+
*
|
|
29
|
+
* Two caches deep and both earn their place. The inner one memoises the *parse*,
|
|
30
|
+
* which is what keeps a node that re-draws sixty times a second from re-reading
|
|
31
|
+
* its own expressions; this one memoises the **adapter**, and without it every
|
|
32
|
+
* write would produce a fresh closure over the same parse — which the equation
|
|
33
|
+
* tween reads as "this expression changed" and would blend a function into
|
|
34
|
+
* itself, at double the sampling cost, for no visible difference.
|
|
35
|
+
*
|
|
36
|
+
* The adapter exists because arity is fixed in the parser for the sake of the
|
|
37
|
+
* hot path (see `CompiledExpression`) while the sampler quite reasonably wants
|
|
38
|
+
* to call `f(x)`. The unused second argument is 0 and unreachable: a curve is
|
|
39
|
+
* compiled with `x` as its only variable, so nothing in the tree reads it.
|
|
40
|
+
*/
|
|
41
|
+
const curves = new Map();
|
|
42
|
+
export function compileCurveCached(source) {
|
|
43
|
+
const trimmed = source.trim();
|
|
44
|
+
if (trimmed === "")
|
|
45
|
+
return null;
|
|
46
|
+
const hit = curves.get(trimmed);
|
|
47
|
+
if (hit !== undefined)
|
|
48
|
+
return hit;
|
|
49
|
+
const compiled = compileExpressionCached(trimmed, CURVE_VARIABLES);
|
|
50
|
+
const curve = compiled === null ? null : (x) => compiled(x, 0);
|
|
51
|
+
curves.set(trimmed, curve);
|
|
52
|
+
return curve;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Tween for the curve list — the shared match-by-id walk, with the one thing a
|
|
56
|
+
* curve does differently: mid-morph its height is sampled from both functions
|
|
57
|
+
* and blended, so it deforms into the new one rather than cross-fading through
|
|
58
|
+
* a frame where both are drawn.
|
|
59
|
+
*/
|
|
60
|
+
export function lerpCurves(from, to, t) {
|
|
61
|
+
return lerpGraphEquations(from, to, t, blendCurve);
|
|
62
|
+
}
|
|
63
|
+
/** How two curves blend mid-tween. */
|
|
64
|
+
function blendCurve(a, b, t) {
|
|
65
|
+
return (x) => {
|
|
66
|
+
const start = a(x);
|
|
67
|
+
return start + (b(x) - start) * t;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/graph2d/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,kBAAkB,GAEnB,MAAM,QAAQ,CAAA;AAGf;;;;;;;;;GASG;AACH,OAAO,EACL,cAAc,IAAI,YAAY,EAC9B,WAAW,IAAI,SAAS,EACxB,SAAS,EACT,QAAQ,EACR,SAAS,GACV,MAAM,6BAA6B,CAAA;AASpC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAgC,CAAA;AAEtD,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAC7B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,IAAI,CAAA;IAE/B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC/B,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAA;IAEjC,MAAM,QAAQ,GAAG,uBAAuB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAClE,MAAM,KAAK,GACT,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1D,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC1B,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CACxB,IAAqB,EACrB,EAAmB,EACnB,CAAS;IAET,OAAO,kBAAkB,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAA;AACpD,CAAC;AAED,sCAAsC;AACtC,SAAS,UAAU,CACjB,CAAgB,EAChB,CAAgB,EAChB,CAAS;IAET,OAAO,CAAC,CAAC,EAAE,EAAE;QACX,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAClB,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;IACnC,CAAC,CAAA;AACH,CAAC","sourcesContent":["/**\n * The mappers and tweens the {@link Graph2D} node is built from — the same shape\n * `graph3d/impl/shared.ts` has, and mostly the same short list, because a\n * `@property` is only as good as the `mapper`/`tween` it is declared with.\n *\n * Almost everything here is a re-export. That is the point: the match-by-id\n * equation tween lives in `nodes/graph-kit` because both graphs animate a list of\n * equations the same way, and colour normalisation lives in `nodes/view3d-kit`\n * because the 3D nodes needed it first. What is genuinely this node's own is one\n * function: turning a two-argument compiled expression into the one-argument\n * curve the sampler asks for, without losing the identity the tween compares.\n */\n\nimport {\n CURVE_VARIABLES,\n compileExpressionCached,\n lerpGraphEquations,\n type GraphEquationResolved,\n} from \"../kit\"\nimport type { CurveFunction } from \"./curve\"\n\n/**\n * Colour normalisation and its tween, plus the two number tweens that fix what a\n * plain lerp gets wrong.\n *\n * They live in `view3d-kit` because the 3D nodes needed them first, and there is\n * nothing three-dimensional about any of them — a `NormalizedColor` is an RGBA\n * tuple, which is both interpolatable and still a valid `Color` to hand back to\n * `Graphics`. Renamed on the way through so the call sites don't read as though\n * this node draws in perspective.\n */\nexport {\n resolveColor3D as resolveColor,\n lerpColor3D as lerpColor,\n lerpCount,\n snapFlag,\n snapValue,\n} from \"@motionscript/sdk/component\"\n\n/**\n * One curve after {@link Graph2D}'s mapper has run: compiled, resolved and fully\n * defaulted, so the per-frame draw never re-derives anything and the tween never\n * tests for an absent field.\n */\nexport type CurveResolved = GraphEquationResolved<CurveFunction>\n\n/**\n * Compiles `source` as `y = f(x)`, memoised, returning `null` for anything that\n * doesn't parse.\n *\n * Two caches deep and both earn their place. The inner one memoises the *parse*,\n * which is what keeps a node that re-draws sixty times a second from re-reading\n * its own expressions; this one memoises the **adapter**, and without it every\n * write would produce a fresh closure over the same parse — which the equation\n * tween reads as \"this expression changed\" and would blend a function into\n * itself, at double the sampling cost, for no visible difference.\n *\n * The adapter exists because arity is fixed in the parser for the sake of the\n * hot path (see `CompiledExpression`) while the sampler quite reasonably wants\n * to call `f(x)`. The unused second argument is 0 and unreachable: a curve is\n * compiled with `x` as its only variable, so nothing in the tree reads it.\n */\nconst curves = new Map<string, CurveFunction | null>()\n\nexport function compileCurveCached(source: string): CurveFunction | null {\n const trimmed = source.trim()\n if (trimmed === \"\") return null\n\n const hit = curves.get(trimmed)\n if (hit !== undefined) return hit\n\n const compiled = compileExpressionCached(trimmed, CURVE_VARIABLES)\n const curve: CurveFunction | null =\n compiled === null ? null : (x: number) => compiled(x, 0)\n curves.set(trimmed, curve)\n return curve\n}\n\n/**\n * Tween for the curve list — the shared match-by-id walk, with the one thing a\n * curve does differently: mid-morph its height is sampled from both functions\n * and blended, so it deforms into the new one rather than cross-fading through\n * a frame where both are drawn.\n */\nexport function lerpCurves(\n from: CurveResolved[],\n to: CurveResolved[],\n t: number\n): CurveResolved[] {\n return lerpGraphEquations(from, to, t, blendCurve)\n}\n\n/** How two curves blend mid-tween. */\nfunction blendCurve(\n a: CurveFunction,\n b: CurveFunction,\n t: number\n): CurveFunction {\n return (x) => {\n const start = a(x)\n return start + (b(x) - start) * t\n }\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `z = f(x, y)` expression language, as this node reaches for it.
|
|
3
|
+
*
|
|
4
|
+
* The parser itself now lives in `nodes/graph-kit/expression`, because the 2D
|
|
5
|
+
* graph writes its curves in the same language and neither node owns it — the
|
|
6
|
+
* same move `shared.ts` made when the Protein node needed the colour and camera
|
|
7
|
+
* helpers. What is left here is the *binding*: a surface's two free variables
|
|
8
|
+
* are `x` and `y`, which is the one thing about the grammar that differs between
|
|
9
|
+
* the two graphs, and every function below has it applied.
|
|
10
|
+
*
|
|
11
|
+
* Re-exported rather than re-implemented so this stays the one import a graph3d
|
|
12
|
+
* module reaches for, and so the vocabulary the inspector lists cannot drift
|
|
13
|
+
* from the names the parser will actually accept.
|
|
14
|
+
*/
|
|
15
|
+
import { type CompiledExpression } from "../kit/expression.js";
|
|
16
|
+
export { EXPRESSION_VOCABULARY } from "../kit/expression.js";
|
|
17
|
+
export type { CompiledExpression, ExpressionVocabulary, } from "../kit/expression.js";
|
|
18
|
+
/** Compiles `source` as `z = f(x, y)`. Throws on a syntax error. */
|
|
19
|
+
export declare function compileExpression(source: string): CompiledExpression;
|
|
20
|
+
/** Why `source` won't compile as `z = f(x, y)`, or `null` when it does. */
|
|
21
|
+
export declare function expressionError(source: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Compiles with memoisation, returning `null` for anything that doesn't parse.
|
|
24
|
+
*
|
|
25
|
+
* The memoisation is what makes the equation tween cheap — equal source compiles
|
|
26
|
+
* to the identical closure, so "did this equation change" is an `===` — and what
|
|
27
|
+
* `surfaceRevision` reduces to a number. See the shared module for the rest.
|
|
28
|
+
*/
|
|
29
|
+
export declare function compileExpressionCached(source: string): CompiledExpression | null;
|
|
30
|
+
//# sourceMappingURL=expression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../src/graph3d/expression.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,YAAY,EACV,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAE1B,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAEpE;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,GACb,kBAAkB,GAAG,IAAI,CAE3B"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `z = f(x, y)` expression language, as this node reaches for it.
|
|
3
|
+
*
|
|
4
|
+
* The parser itself now lives in `nodes/graph-kit/expression`, because the 2D
|
|
5
|
+
* graph writes its curves in the same language and neither node owns it — the
|
|
6
|
+
* same move `shared.ts` made when the Protein node needed the colour and camera
|
|
7
|
+
* helpers. What is left here is the *binding*: a surface's two free variables
|
|
8
|
+
* are `x` and `y`, which is the one thing about the grammar that differs between
|
|
9
|
+
* the two graphs, and every function below has it applied.
|
|
10
|
+
*
|
|
11
|
+
* Re-exported rather than re-implemented so this stays the one import a graph3d
|
|
12
|
+
* module reaches for, and so the vocabulary the inspector lists cannot drift
|
|
13
|
+
* from the names the parser will actually accept.
|
|
14
|
+
*/
|
|
15
|
+
import { SURFACE_VARIABLES, compileExpression as compile, compileExpressionCached as compileCached, expressionError as errorOf, } from "../kit/expression.js";
|
|
16
|
+
export { EXPRESSION_VOCABULARY } from "../kit/expression.js";
|
|
17
|
+
/** Compiles `source` as `z = f(x, y)`. Throws on a syntax error. */
|
|
18
|
+
export function compileExpression(source) {
|
|
19
|
+
return compile(source, SURFACE_VARIABLES);
|
|
20
|
+
}
|
|
21
|
+
/** Why `source` won't compile as `z = f(x, y)`, or `null` when it does. */
|
|
22
|
+
export function expressionError(source) {
|
|
23
|
+
return errorOf(source, SURFACE_VARIABLES);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Compiles with memoisation, returning `null` for anything that doesn't parse.
|
|
27
|
+
*
|
|
28
|
+
* The memoisation is what makes the equation tween cheap — equal source compiles
|
|
29
|
+
* to the identical closure, so "did this equation change" is an `===` — and what
|
|
30
|
+
* `surfaceRevision` reduces to a number. See the shared module for the rest.
|
|
31
|
+
*/
|
|
32
|
+
export function compileExpressionCached(source) {
|
|
33
|
+
return compileCached(source, SURFACE_VARIABLES);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=expression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression.js","sourceRoot":"","sources":["../../src/graph3d/expression.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,iBAAiB,EACjB,iBAAiB,IAAI,OAAO,EAC5B,uBAAuB,IAAI,aAAa,EACxC,eAAe,IAAI,OAAO,GAE3B,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAMzD,oEAAoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAC3C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAc;IAEd,OAAO,aAAa,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AACjD,CAAC","sourcesContent":["/**\n * The `z = f(x, y)` expression language, as this node reaches for it.\n *\n * The parser itself now lives in `nodes/graph-kit/expression`, because the 2D\n * graph writes its curves in the same language and neither node owns it — the\n * same move `shared.ts` made when the Protein node needed the colour and camera\n * helpers. What is left here is the *binding*: a surface's two free variables\n * are `x` and `y`, which is the one thing about the grammar that differs between\n * the two graphs, and every function below has it applied.\n *\n * Re-exported rather than re-implemented so this stays the one import a graph3d\n * module reaches for, and so the vocabulary the inspector lists cannot drift\n * from the names the parser will actually accept.\n */\n\nimport {\n SURFACE_VARIABLES,\n compileExpression as compile,\n compileExpressionCached as compileCached,\n expressionError as errorOf,\n type CompiledExpression,\n} from \"../kit/expression\"\n\nexport { EXPRESSION_VOCABULARY } from \"../kit/expression\"\nexport type {\n CompiledExpression,\n ExpressionVocabulary,\n} from \"../kit/expression\"\n\n/** Compiles `source` as `z = f(x, y)`. Throws on a syntax error. */\nexport function compileExpression(source: string): CompiledExpression {\n return compile(source, SURFACE_VARIABLES)\n}\n\n/** Why `source` won't compile as `z = f(x, y)`, or `null` when it does. */\nexport function expressionError(source: string): string | null {\n return errorOf(source, SURFACE_VARIABLES)\n}\n\n/**\n * Compiles with memoisation, returning `null` for anything that doesn't parse.\n *\n * The memoisation is what makes the equation tween cheap — equal source compiles\n * to the identical closure, so \"did this equation change\" is an `===` — and what\n * `surfaceRevision` reduces to a number. See the shared module for the rest.\n */\nexport function compileExpressionCached(\n source: string\n): CompiledExpression | null {\n return compileCached(source, SURFACE_VARIABLES)\n}\n"]}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { type Command, type CommandArgs, Canvas3D, Scene3D, type Color, type NodeConfig, type Canvas3DProps } from "@motionscript/sdk";
|
|
2
|
+
import { type OrbitTarget } from "@motionscript/sdk/component";
|
|
3
|
+
/** One plotted surface, `z = f(x, y)`. */
|
|
4
|
+
export interface Graph3DEquation {
|
|
5
|
+
/** Identity across list changes — see {@link Graph3D.equations}. */
|
|
6
|
+
id: string | number;
|
|
7
|
+
/** The expression, evaluated as `z = f(x, y)` (e.g. `sin(x) + cos(y)`). */
|
|
8
|
+
expression: string;
|
|
9
|
+
/** The mesh's colour: any {@link Color} — a CSS string or an RGBA tuple. */
|
|
10
|
+
color: Color;
|
|
11
|
+
/** Whether the surface is drawn. Defaults to true. */
|
|
12
|
+
visible?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* How solid the mesh is, 0–1. Defaults to 1.
|
|
15
|
+
*
|
|
16
|
+
* Anything below 1 makes the surface blend rather than write depth, so
|
|
17
|
+
* overlapping surfaces layer instead of occluding each other. Left at 1 the
|
|
18
|
+
* surface is genuinely opaque and reads crisp — which is why that is the
|
|
19
|
+
* default, and why fading one in or out still looks right on the way through.
|
|
20
|
+
*/
|
|
21
|
+
opacity?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Where the camera may go.
|
|
25
|
+
*
|
|
26
|
+
* Deliberately *not* OrbitControls. Those drive a camera from live mouse input,
|
|
27
|
+
* and a rendered timeline has no pointer — worse, their damping is an
|
|
28
|
+
* accumulator, so a scrubbed frame would differ from a played one and export
|
|
29
|
+
* would stop being deterministic. What is honoured here is the framing
|
|
30
|
+
* ({@link initialPosition}) and the limits; to *move* the camera, animate
|
|
31
|
+
* {@link Graph3DProps.orbit} / {@link Graph3DProps.elevation} /
|
|
32
|
+
* {@link Graph3DProps.zoom} from the timeline, which stays seekable.
|
|
33
|
+
*/
|
|
34
|
+
export interface Graph3DCamera {
|
|
35
|
+
/** Initial camera position, which seeds the three spherical props. */
|
|
36
|
+
initialPosition?: {
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
z: number;
|
|
40
|
+
};
|
|
41
|
+
/** Closest the camera may come to the origin. */
|
|
42
|
+
minZoom?: number;
|
|
43
|
+
/** Furthest it may pull back. */
|
|
44
|
+
maxZoom?: number;
|
|
45
|
+
}
|
|
46
|
+
/** The helper grid and the axes drawn under the surfaces. */
|
|
47
|
+
export interface Graph3DGrid {
|
|
48
|
+
/** Whether to draw the ground grid at all. Defaults to true. */
|
|
49
|
+
showGrid?: boolean;
|
|
50
|
+
/** Total width and depth of the grid. Defaults to 20. */
|
|
51
|
+
size?: number;
|
|
52
|
+
/** How many cells across. Defaults to 20. */
|
|
53
|
+
divisions?: number;
|
|
54
|
+
/** Colour of the two lines through the origin. */
|
|
55
|
+
colorCenterLine?: Color;
|
|
56
|
+
/** Colour of every other grid line. */
|
|
57
|
+
colorGrid?: Color;
|
|
58
|
+
/** Whether to draw the X/Y/Z axes. Defaults to true. */
|
|
59
|
+
showAxes?: boolean;
|
|
60
|
+
/** How far each axis reaches from the origin. Defaults to 10. */
|
|
61
|
+
axesSize?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface Graph3DProps extends Canvas3DProps {
|
|
64
|
+
/** The surfaces to plot, each evaluated as `z = f(x, y)` over the domain. */
|
|
65
|
+
equations: Graph3DEquation[];
|
|
66
|
+
camera: Graph3DCamera;
|
|
67
|
+
grid: Graph3DGrid;
|
|
68
|
+
/** Half-width of the plotted domain: x and y run `-domain … +domain`. Default 10. */
|
|
69
|
+
domain: number;
|
|
70
|
+
/**
|
|
71
|
+
* Surface resolution per axis. Default 80, i.e. ~6.4k vertices per equation.
|
|
72
|
+
* Lower it when plotting several surfaces at once.
|
|
73
|
+
*/
|
|
74
|
+
segments: number;
|
|
75
|
+
/**
|
|
76
|
+
* Clamp on `|z|`. Default 20. Without it a function with an asymptote (`1/x`,
|
|
77
|
+
* `tan`) produces near-infinite vertices that stretch the mesh across the
|
|
78
|
+
* whole scene and wreck the framing.
|
|
79
|
+
*/
|
|
80
|
+
maxHeight: number;
|
|
81
|
+
/** Camera orbit about the vertical axis, in **degrees**. Animate this to spin. */
|
|
82
|
+
orbit: number;
|
|
83
|
+
/** Camera elevation above the ground plane, in **degrees**. */
|
|
84
|
+
elevation: number;
|
|
85
|
+
/** Camera distance from the origin, clamped by the camera's zoom limits. */
|
|
86
|
+
zoom: number;
|
|
87
|
+
/** The 3D scene's background. */
|
|
88
|
+
background: Color;
|
|
89
|
+
/** Skips the background entirely, letting the 2D scene behind show through. */
|
|
90
|
+
transparentBackground: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A 3D function grapher — any number of `z = f(x, y)` surfaces over a helper
|
|
94
|
+
* grid, with axes.
|
|
95
|
+
*
|
|
96
|
+
* Extends {@link Canvas3D} rather than `Node3D`: a grapher is a *viewport* on a
|
|
97
|
+
* scene it owns entirely, not a thing placed inside somebody else's. `Canvas3D`
|
|
98
|
+
* owns the bridge from the 2D scene graph into the 3D renderer, so subclassing
|
|
99
|
+
* it means this class only has to describe *what* to draw. It overrides
|
|
100
|
+
* `buildScene3D`, the single seam both the real render and the asset
|
|
101
|
+
* declaration pass go through.
|
|
102
|
+
*
|
|
103
|
+
* <Graph3D
|
|
104
|
+
* width="fill" height="fill"
|
|
105
|
+
* equations={[{ id: 1, expression: "sin(sqrt(x^2 + y^2))", color: "#3B82F6" }]}
|
|
106
|
+
* />
|
|
107
|
+
*
|
|
108
|
+
* Every prop is a `@property`, so a constant, a `() => signal()` binding, and
|
|
109
|
+
* `set()`/`to()` on a ref all work and agree. The non-scalar props each declare
|
|
110
|
+
* a `mapper` (loose authored shape → one canonical internal shape) and a `tween`
|
|
111
|
+
* (how that shape interpolates) — without the tween, `to({ grid: … })` would
|
|
112
|
+
* hold the old value and snap at the end, which is the standard trap for an
|
|
113
|
+
* object-valued attribute.
|
|
114
|
+
*
|
|
115
|
+
* **There is no OrbitControls and no pointer.** The camera is driven by the
|
|
116
|
+
* node's own `orbit`/`elevation`/`zoom` props, which is what keeps every frame
|
|
117
|
+
* reproducible under scrubbing and export — see {@link Graph3DCamera}.
|
|
118
|
+
*/
|
|
119
|
+
export declare class Graph3D extends Canvas3D<Graph3DProps> {
|
|
120
|
+
/**
|
|
121
|
+
* The plotted surfaces.
|
|
122
|
+
*
|
|
123
|
+
* The mapper compiles each expression **once per write** (memoised by source),
|
|
124
|
+
* so the builder — which re-runs every frame — never re-parses; and it folds
|
|
125
|
+
* `visible`/`opacity` into a single number, so hiding is expressible as a
|
|
126
|
+
* fade. An expression that doesn't parse is dropped and the rest still draw,
|
|
127
|
+
* which is what lets the inspector commit on every keystroke.
|
|
128
|
+
*
|
|
129
|
+
* The tween matches the two lists by `id` — see `lerpEquations`.
|
|
130
|
+
*/
|
|
131
|
+
equations: Graph3DEquation[];
|
|
132
|
+
/** The camera limits, and the framing that seeds the three spherical props. */
|
|
133
|
+
camera: Graph3DCamera;
|
|
134
|
+
/** The helper grid and axes. Flags snap at the end of a tween; the rest lerp. */
|
|
135
|
+
grid: Graph3DGrid;
|
|
136
|
+
domain: number;
|
|
137
|
+
/**
|
|
138
|
+
* Surface resolution. Tweenable, but *structural*: a geometry is immutable, so
|
|
139
|
+
* every intermediate value reallocates each surface's buffers. Set it once
|
|
140
|
+
* unless the resolution change is itself the point.
|
|
141
|
+
*/
|
|
142
|
+
segments: number;
|
|
143
|
+
maxHeight: number;
|
|
144
|
+
background: Color;
|
|
145
|
+
transparentBackground: boolean;
|
|
146
|
+
orbit: number;
|
|
147
|
+
elevation: number;
|
|
148
|
+
zoom: number;
|
|
149
|
+
constructor(props?: NodeConfig<Graph3D, Graph3DProps>);
|
|
150
|
+
/**
|
|
151
|
+
* Frame the scene at a spherical camera placement. Every axis is optional,
|
|
152
|
+
* so "pull back" and "spin round" stay separate intentions — see
|
|
153
|
+
* {@link OrbitTarget}.
|
|
154
|
+
*/
|
|
155
|
+
orbitTo(args: CommandArgs<{
|
|
156
|
+
target: OrbitTarget;
|
|
157
|
+
}> & {
|
|
158
|
+
duration: number;
|
|
159
|
+
}): Command<Graph3DProps>;
|
|
160
|
+
/**
|
|
161
|
+
* Seeds `orbit`/`elevation`/`zoom` from `camera.initialPosition`, so a caller
|
|
162
|
+
* who gives a raw position gets that framing and one who gives none gets
|
|
163
|
+
* {@link DEFAULT_POSITION} — without having to restate the other two axes.
|
|
164
|
+
*
|
|
165
|
+
* Bound reactively rather than copied, so the default *tracks* the camera and
|
|
166
|
+
* a camera signal keeps working. Writing any of the three (a `set`, or the
|
|
167
|
+
* first frame of a `to`) replaces the binding with the explicit value, which
|
|
168
|
+
* is exactly the handover wanted.
|
|
169
|
+
*/
|
|
170
|
+
private applyCameraDefaults;
|
|
171
|
+
protected buildScene3D(): Scene3D;
|
|
172
|
+
/**
|
|
173
|
+
* One `z = f(x, y)` surface, keyed by equation id rather than by position in
|
|
174
|
+
* the op list — see {@link Graph3D.equations}.
|
|
175
|
+
*/
|
|
176
|
+
private addSurface;
|
|
177
|
+
/**
|
|
178
|
+
* The ground grid, as two line ops — the centre cross and everything else —
|
|
179
|
+
* because a line op carries a single colour and the centre lines are drawn
|
|
180
|
+
* differently from the rest.
|
|
181
|
+
*/
|
|
182
|
+
private addGrid;
|
|
183
|
+
/** X/Y/Z axes in red/green/blue, the conventional colouring. */
|
|
184
|
+
private addAxes;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=graph3d.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph3d.d.ts","sourceRoot":"","sources":["../../src/graph3d/graph3d.ts"],"names":[],"mappings":"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"}
|