@glissade/scene 0.29.0-pre.0 → 0.30.0-pre.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/dist/describe.js +7 -1
- package/dist/examples.js +13 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +2 -2
- package/dist/{echo.js → motionBlur.js} +74 -1
- package/package.json +2 -2
package/dist/describe.js
CHANGED
|
@@ -22,7 +22,7 @@ import { easings, listValueTypes } from "@glissade/core";
|
|
|
22
22
|
* never pulled onto the base embed path — a scene that never calls `describe()`
|
|
23
23
|
* pays zero bytes for it.
|
|
24
24
|
*/
|
|
25
|
-
const RAW_VERSION = "0.
|
|
25
|
+
const RAW_VERSION = "0.30.0-pre.0";
|
|
26
26
|
const PACKAGE_VERSION = RAW_VERSION.includes("GLISSADE_".concat("VERSION")) ? "0.0.0-dev" : RAW_VERSION;
|
|
27
27
|
/** Arity of a value type's numeric repr: vec2/vec2-arc → 2, number → 1; others (color/paint/path/string/boolean) carry no scalar arity. */
|
|
28
28
|
function arityOf(type) {
|
|
@@ -345,6 +345,12 @@ const HELPERS = [
|
|
|
345
345
|
import: "@glissade/scene",
|
|
346
346
|
usage: "echo(child: Node, opts?: { id?, count?: number, spacing?: number, decay?: number }): Echo"
|
|
347
347
|
},
|
|
348
|
+
{
|
|
349
|
+
name: "motionBlur",
|
|
350
|
+
summary: "Real sampled motion blur: wrap a child so it renders at N sub-frame times across a shutter interval (centered on the frame) and AVERAGES them — tracks every animated prop, not a faked directional blur. A pure multi-time re-eval (playhead re-addressed per sample, running-mean opacity, restored), byte-exact on Skia; browser↔Skia is perceptual-tier for blur.",
|
|
351
|
+
import: "@glissade/scene",
|
|
352
|
+
usage: "motionBlur(child: Node, opts?: { id?, shutter?: number, samples?: number }): MotionBlur"
|
|
353
|
+
},
|
|
348
354
|
{
|
|
349
355
|
name: "clip",
|
|
350
356
|
summary: "A reusable, target-agnostic motion captured once as a relative-time key schedule, then applied to a node at a wall-clock start time. Build-time sugar: clip.apply() compiles to ordinary Track[].",
|
package/dist/examples.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Grid } from "./grid.js";
|
|
|
5
5
|
import { Stack } from "./layoutCtors.js";
|
|
6
6
|
import { splitText } from "./type.js";
|
|
7
7
|
import { i as orientToPath, r as lookAt, s as motionPath } from "./orient.js";
|
|
8
|
-
import {
|
|
8
|
+
import { i as echo, n as motionBlur } from "./motionBlur.js";
|
|
9
9
|
import { pathFromSvg } from "./path.js";
|
|
10
10
|
import { key, retime, timeline, track } from "@glissade/core";
|
|
11
11
|
//#region src/examples.ts
|
|
@@ -257,6 +257,18 @@ const EXAMPLES = [
|
|
|
257
257
|
spacing: .05,
|
|
258
258
|
decay: .7
|
|
259
259
|
})
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
key: "motionBlur",
|
|
263
|
+
code: "import { Circle, motionBlur } from '@glissade/scene';\n// real sampled motion blur: renders the child at N sub-frame times across `shutter` (seconds) and averages them.\n// Wrap the MOVING content; its background stays crisp. Byte-exact on Skia, perceptual browser↔Skia.\nconst dot = new Circle({ id: 'dot', radius: 16, fill: '#ffcf3f' });\nconst blurred = motionBlur(dot, { shutter: 0.06, samples: 16 });",
|
|
264
|
+
run: () => void motionBlur(new Circle({
|
|
265
|
+
id: "dot",
|
|
266
|
+
radius: 16,
|
|
267
|
+
fill: "#ffcf3f"
|
|
268
|
+
}), {
|
|
269
|
+
shutter: .06,
|
|
270
|
+
samples: 16
|
|
271
|
+
})
|
|
260
272
|
}
|
|
261
273
|
];
|
|
262
274
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -445,6 +445,25 @@ declare class Echo extends Group {
|
|
|
445
445
|
* A convenience wrapper: pass the trailing content as children of the returned Echo. */
|
|
446
446
|
declare function echo(child: Node, props?: Omit<EchoProps, 'children'>): Echo;
|
|
447
447
|
//#endregion
|
|
448
|
+
//#region src/motionBlur.d.ts
|
|
449
|
+
interface MotionBlurProps extends NodeProps {
|
|
450
|
+
children?: Node[];
|
|
451
|
+
/** the shutter interval in SECONDS, centered on the frame time (0 = no blur); default 0.04. */
|
|
452
|
+
shutter?: number;
|
|
453
|
+
/** number of sub-frame samples averaged across the shutter (≥ 1); default 8. */
|
|
454
|
+
samples?: number;
|
|
455
|
+
}
|
|
456
|
+
declare class MotionBlur extends Group {
|
|
457
|
+
get describeType(): string;
|
|
458
|
+
readonly shutter: number;
|
|
459
|
+
readonly samples: number;
|
|
460
|
+
constructor(props?: MotionBlurProps);
|
|
461
|
+
protected draw(out: DisplayListBuilder, ctx: EvalContext): void;
|
|
462
|
+
}
|
|
463
|
+
/** `children: [motionBlur(fastDot, { shutter: 0.05 })]` — fastDot smears with real
|
|
464
|
+
* sub-frame motion blur. Wrap the moving content; its background stays crisp. */
|
|
465
|
+
declare function motionBlur(child: Node, props?: Omit<MotionBlurProps, 'children'>): MotionBlur;
|
|
466
|
+
//#endregion
|
|
448
467
|
//#region src/raster2d.d.ts
|
|
449
468
|
/** A backend gradient handle (DOM CanvasGradient and @napi-rs CanvasGradient both satisfy it). */
|
|
450
469
|
interface CanvasGradientLike {
|
|
@@ -691,4 +710,4 @@ declare function meshRasterSize(bw: number, bh: number): {
|
|
|
691
710
|
h: number;
|
|
692
711
|
};
|
|
693
712
|
//#endregion
|
|
694
|
-
export { ALL_FILTER_KINDS, type AnchorSpec, type BackendCaps, type BindablePropTarget, type BlendMode, type Bounds, type CanvasLike, Circle, ColdAssetError, type Ctx2DLike, Custom, DeterminismViolationError, type DisplayList, type DisplayListBuilder, type DrawCommand, type DrawOnEachOptions, type DrawOnOptions, DuplicateNodeIdError, type EachBox, type EachContext, type EachDistribute, EachError, type EachLayout, type EachMotion, type EachOpts, type EachResult, Echo, type EchoProps, type EditMark, type EvalContext, type FilterKind, type FilterSpec, FilterValidationError, type FontByteLoader, type FontSpec, type GraphemeBox, Group, type GuardMode, type HachureSpec, Highlight, type HighlightProps, type HitArea, IDENTITY, ImageNode as Image, ImageNode, type ImageDataLike, type ImageHandle, type ImageProps, type LayerCacheEntry, type LayerStore, type LayoutBox, type LayoutChildSpec, type LayoutContainerSpec, type LayoutEngine, LayoutEngineMissingError, type LineBox, MEASURE_QUANTUM_PX, MESH_DOWNSCALE, MESH_SHEPARD_POWER, MESH_SIGMA, type Mat2x3, type MeshInterpolation, type MeshPaint, type MeshPoint, NODE_TAXONOMY, Node, NodeConstructionError, type NodeProps, type NodeTypeName, type Paint, Path, type PathLike, type PathProps, type PathSeg, type Place, type Polyline, type PropInit, Raster2D, type Raster2DHost, Rect, type Rect$1 as RectShape, type RenderBackend, ReservedNodeIdError, type ResolvedSketch, type Resource, type ResourceId, type RevealMark, type Scene, type SceneInit, type SceneModule, type ShaderCaps, ShaderEffect, type ShaderEffectProps, type ShaderRef, type ShapeProps, type SketchStyle, SketchValidationError, type StepMark, type StrokeStyle, Text, TextCursor, type TextCursorProps, type TextMeasurer, type TextMetricsLite, type TextProps, type TypeEdit, type TypewriterResult, type ValidateSceneFontsOptions, Video, type VideoFrameSource, type VideoProps, type WordBox, type WrappedTextMetrics, __resetEstimateWarnings, applyToPoint, arcLength, assertFiniteFontSize, bindScene, breakLines, coercePathData, collapseReplacer, collectLocalizedTextUsages, collectTextUsages, createDisplayListBuilder, createScene, drawOn, drawOnEach, each, echo, estimatingMeasurer, evaluate, filtersToCanvasFilter, flatten, fontString, fromTRS, getLayoutEngine, glow, hachureLines, highlight, invert, isEstimatingMeasurer, matEquals, measureWrappedText, meshRasterSize, multiply, pathFromSegs, quantize, rasterizeMesh, requireLayoutEngine, resolveAnchor, resolveSketch, revealSchedule, roughen, roundedRectSegs, segmentGraphemes, segmentWords, setDefaultMeasurer, setLayoutEngine, sketchStrokes, textCursor, typewriter, validateFilters, validateHachure, validateSceneFonts, validateSketch, withDeterminismGuards };
|
|
713
|
+
export { ALL_FILTER_KINDS, type AnchorSpec, type BackendCaps, type BindablePropTarget, type BlendMode, type Bounds, type CanvasLike, Circle, ColdAssetError, type Ctx2DLike, Custom, DeterminismViolationError, type DisplayList, type DisplayListBuilder, type DrawCommand, type DrawOnEachOptions, type DrawOnOptions, DuplicateNodeIdError, type EachBox, type EachContext, type EachDistribute, EachError, type EachLayout, type EachMotion, type EachOpts, type EachResult, Echo, type EchoProps, type EditMark, type EvalContext, type FilterKind, type FilterSpec, FilterValidationError, type FontByteLoader, type FontSpec, type GraphemeBox, Group, type GuardMode, type HachureSpec, Highlight, type HighlightProps, type HitArea, IDENTITY, ImageNode as Image, ImageNode, type ImageDataLike, type ImageHandle, type ImageProps, type LayerCacheEntry, type LayerStore, type LayoutBox, type LayoutChildSpec, type LayoutContainerSpec, type LayoutEngine, LayoutEngineMissingError, type LineBox, MEASURE_QUANTUM_PX, MESH_DOWNSCALE, MESH_SHEPARD_POWER, MESH_SIGMA, type Mat2x3, type MeshInterpolation, type MeshPaint, type MeshPoint, MotionBlur, type MotionBlurProps, NODE_TAXONOMY, Node, NodeConstructionError, type NodeProps, type NodeTypeName, type Paint, Path, type PathLike, type PathProps, type PathSeg, type Place, type Polyline, type PropInit, Raster2D, type Raster2DHost, Rect, type Rect$1 as RectShape, type RenderBackend, ReservedNodeIdError, type ResolvedSketch, type Resource, type ResourceId, type RevealMark, type Scene, type SceneInit, type SceneModule, type ShaderCaps, ShaderEffect, type ShaderEffectProps, type ShaderRef, type ShapeProps, type SketchStyle, SketchValidationError, type StepMark, type StrokeStyle, Text, TextCursor, type TextCursorProps, type TextMeasurer, type TextMetricsLite, type TextProps, type TypeEdit, type TypewriterResult, type ValidateSceneFontsOptions, Video, type VideoFrameSource, type VideoProps, type WordBox, type WrappedTextMetrics, __resetEstimateWarnings, applyToPoint, arcLength, assertFiniteFontSize, bindScene, breakLines, coercePathData, collapseReplacer, collectLocalizedTextUsages, collectTextUsages, createDisplayListBuilder, createScene, drawOn, drawOnEach, each, echo, estimatingMeasurer, evaluate, filtersToCanvasFilter, flatten, fontString, fromTRS, getLayoutEngine, glow, hachureLines, highlight, invert, isEstimatingMeasurer, matEquals, measureWrappedText, meshRasterSize, motionBlur, multiply, pathFromSegs, quantize, rasterizeMesh, requireLayoutEngine, resolveAnchor, resolveSketch, revealSchedule, roughen, roundedRectSegs, segmentGraphemes, segmentWords, setDefaultMeasurer, setLayoutEngine, sketchStrokes, textCursor, typewriter, validateFilters, validateHachure, validateSceneFonts, validateSketch, withDeterminismGuards };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $ as multiply, A as setDefaultMeasurer, B as validateHachure, C as estimatingMeasurer, D as quantize, E as measureWrappedText, F as hachureLines, G as glow, H as FilterValidationError, I as hashStr, J as IDENTITY, K as validateFilters, L as resolveSketch, M as SketchValidationError, N as arcLength, O as segmentGraphemes, P as flatten, Q as matEquals, R as roughen, S as breakLines, T as isEstimatingMeasurer, U as createDisplayListBuilder, V as validateSketch, W as filtersToCanvasFilter, X as fromTRS, Y as applyToPoint, Z as invert, a as Path, b as __resetEstimateWarnings, c as Video, d as revealSchedule, f as roundedRectSegs, h as resolveAnchor, i as ImageNode, k as segmentWords, l as coercePathData, m as NodeConstructionError, n as Custom, o as Rect, p as Node, q as collapseReplacer, r as Group, s as Text, t as Circle, u as pathFromSegs, x as assertFiniteFontSize, y as MEASURE_QUANTUM_PX, z as sketchStrokes } from "./nodes.js";
|
|
2
2
|
import { a as evaluate, i as createScene, n as ReservedNodeIdError, r as bindScene, t as DuplicateNodeIdError } from "./scene.js";
|
|
3
3
|
import { i as setLayoutEngine, n as getLayoutEngine, r as requireLayoutEngine, t as LayoutEngineMissingError } from "./layoutEngine.js";
|
|
4
|
-
import {
|
|
4
|
+
import { i as echo, n as motionBlur, r as Echo, t as MotionBlur } from "./motionBlur.js";
|
|
5
5
|
import { buildFontRegistry, emitDevWarning, key, lerpColor, oklabToRgba, parseCmap, parseColor, random, rgbaToOklab, signal, stagger, track, validateFonts } from "@glissade/core";
|
|
6
6
|
//#region src/taxonomy.ts
|
|
7
7
|
/**
|
|
@@ -1396,4 +1396,4 @@ var Raster2D = class {
|
|
|
1396
1396
|
}
|
|
1397
1397
|
};
|
|
1398
1398
|
//#endregion
|
|
1399
|
-
export { ALL_FILTER_KINDS, Circle, ColdAssetError, Custom, DeterminismViolationError, DuplicateNodeIdError, EachError, Echo, FilterValidationError, Group, Highlight, IDENTITY, ImageNode as Image, ImageNode, LayoutEngineMissingError, MEASURE_QUANTUM_PX, MESH_DOWNSCALE, MESH_SHEPARD_POWER, MESH_SIGMA, NODE_TAXONOMY, Node, NodeConstructionError, Path, Raster2D, Rect, ReservedNodeIdError, ShaderEffect, SketchValidationError, Text, TextCursor, Video, __resetEstimateWarnings, applyToPoint, arcLength, assertFiniteFontSize, bindScene, breakLines, coercePathData, collapseReplacer, collectLocalizedTextUsages, collectTextUsages, createDisplayListBuilder, createScene, drawOn, drawOnEach, each, echo, estimatingMeasurer, evaluate, filtersToCanvasFilter, flatten, fontString, fromTRS, getLayoutEngine, glow, hachureLines, highlight, invert, isEstimatingMeasurer, matEquals, measureWrappedText, meshRasterSize, multiply, pathFromSegs, quantize, rasterizeMesh, requireLayoutEngine, resolveAnchor, resolveSketch, revealSchedule, roughen, roundedRectSegs, segmentGraphemes, segmentWords, setDefaultMeasurer, setLayoutEngine, sketchStrokes, textCursor, typewriter, validateFilters, validateHachure, validateSceneFonts, validateSketch, withDeterminismGuards };
|
|
1399
|
+
export { ALL_FILTER_KINDS, Circle, ColdAssetError, Custom, DeterminismViolationError, DuplicateNodeIdError, EachError, Echo, FilterValidationError, Group, Highlight, IDENTITY, ImageNode as Image, ImageNode, LayoutEngineMissingError, MEASURE_QUANTUM_PX, MESH_DOWNSCALE, MESH_SHEPARD_POWER, MESH_SIGMA, MotionBlur, NODE_TAXONOMY, Node, NodeConstructionError, Path, Raster2D, Rect, ReservedNodeIdError, ShaderEffect, SketchValidationError, Text, TextCursor, Video, __resetEstimateWarnings, applyToPoint, arcLength, assertFiniteFontSize, bindScene, breakLines, coercePathData, collapseReplacer, collectLocalizedTextUsages, collectTextUsages, createDisplayListBuilder, createScene, drawOn, drawOnEach, each, echo, estimatingMeasurer, evaluate, filtersToCanvasFilter, flatten, fontString, fromTRS, getLayoutEngine, glow, hachureLines, highlight, invert, isEstimatingMeasurer, matEquals, measureWrappedText, meshRasterSize, motionBlur, multiply, pathFromSegs, quantize, rasterizeMesh, requireLayoutEngine, resolveAnchor, resolveSketch, revealSchedule, roughen, roundedRectSegs, segmentGraphemes, segmentWords, setDefaultMeasurer, setLayoutEngine, sketchStrokes, textCursor, typewriter, validateFilters, validateHachure, validateSceneFonts, validateSketch, withDeterminismGuards };
|
|
@@ -75,4 +75,77 @@ function echo(child, props = {}) {
|
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
//#endregion
|
|
78
|
-
|
|
78
|
+
//#region src/motionBlur.ts
|
|
79
|
+
/**
|
|
80
|
+
* MotionBlur (0.30): real sampled motion blur — the flagship motion-craft feature.
|
|
81
|
+
* It renders its subtree at N sub-frame times across a shutter interval centered on
|
|
82
|
+
* the current frame and AVERAGES them, so a fast-moving element smears exactly the
|
|
83
|
+
* way an analog shutter captures it — and it tracks EVERY animated prop (position,
|
|
84
|
+
* rotation, scale, path progress, colour), not a faked directional blur.
|
|
85
|
+
*
|
|
86
|
+
* Like `Echo`, it re-addresses the scene playhead within one frame (wrapped in
|
|
87
|
+
* `batch()`, restored after) to sample sub-frame times. The averaging is a running
|
|
88
|
+
* mean done with plain compositing, NO backend change: paint the k-th sample (of N)
|
|
89
|
+
* at opacity 1/(k+1). Over source-over that is the exact equal-weight mean —
|
|
90
|
+
* L₀=∅; Lₖ₊₁ = Lₖ·(k/(k+1)) + sₖ·(1/(k+1)) = mean(s₀…sₖ)
|
|
91
|
+
* — so all N samples contribute equally (unlike a decaying trail). Each sub-frame t
|
|
92
|
+
* is a pure function of the current time, so evaluate() stays deterministic and the
|
|
93
|
+
* result is byte-stable on Skia (the golden twin); browser↔Skia is perceptual-tier
|
|
94
|
+
* for blur, marked in describe().
|
|
95
|
+
*
|
|
96
|
+
* Ships on the base scene index alongside Echo/ShaderEffect (off the closed 9-node
|
|
97
|
+
* taxonomy). No blur ⇒ pass `samples: 1` or `shutter: 0` and it's a plain group.
|
|
98
|
+
*/
|
|
99
|
+
var MotionBlur = class extends Group {
|
|
100
|
+
get describeType() {
|
|
101
|
+
return "MotionBlur";
|
|
102
|
+
}
|
|
103
|
+
shutter;
|
|
104
|
+
samples;
|
|
105
|
+
constructor(props = {}) {
|
|
106
|
+
super(props);
|
|
107
|
+
this.shutter = props.shutter ?? .04;
|
|
108
|
+
this.samples = Math.max(1, Math.floor(props.samples ?? 8));
|
|
109
|
+
}
|
|
110
|
+
draw(out, ctx) {
|
|
111
|
+
const playhead = ctx.playhead;
|
|
112
|
+
if (this.samples <= 1 || this.shutter === 0 || playhead === void 0) {
|
|
113
|
+
super.draw(out, ctx);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const now = ctx.time;
|
|
117
|
+
const n = this.samples;
|
|
118
|
+
batch(() => {
|
|
119
|
+
try {
|
|
120
|
+
for (let i = 0; i < n; i++) {
|
|
121
|
+
const t = now + (i / (n - 1) - .5) * this.shutter;
|
|
122
|
+
const opacity = 1 / (i + 1);
|
|
123
|
+
playhead.forceSet(t);
|
|
124
|
+
out.push({
|
|
125
|
+
op: "pushGroup",
|
|
126
|
+
opacity,
|
|
127
|
+
blend: "source-over",
|
|
128
|
+
filters: []
|
|
129
|
+
});
|
|
130
|
+
super.draw(out, {
|
|
131
|
+
...ctx,
|
|
132
|
+
time: t
|
|
133
|
+
});
|
|
134
|
+
out.push({ op: "popGroup" });
|
|
135
|
+
}
|
|
136
|
+
} finally {
|
|
137
|
+
playhead.forceSet(now);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
/** `children: [motionBlur(fastDot, { shutter: 0.05 })]` — fastDot smears with real
|
|
143
|
+
* sub-frame motion blur. Wrap the moving content; its background stays crisp. */
|
|
144
|
+
function motionBlur(child, props = {}) {
|
|
145
|
+
return new MotionBlur({
|
|
146
|
+
...props,
|
|
147
|
+
children: [child]
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
export { echo as i, motionBlur as n, Echo as r, MotionBlur as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glissade/scene",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0-pre.0",
|
|
4
4
|
"description": "glissade scene graph: nodes, transforms, DisplayList emission. Renderer-agnostic; zero DOM/Node dependencies.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"engines": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
],
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"yoga-layout": "^3.2.1",
|
|
68
|
-
"@glissade/core": "0.
|
|
68
|
+
"@glissade/core": "0.30.0-pre.0"
|
|
69
69
|
},
|
|
70
70
|
"repository": {
|
|
71
71
|
"type": "git",
|