@redwilly/anima 0.1.25 → 0.1.26

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +457 -247
  2. package/dist/index.js +1926 -1430
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -1,50 +1,51 @@
1
1
  import { Glyph as Glyph$1 } from 'fontkit';
2
+ import { Canvas } from '@napi-rs/canvas';
2
3
 
3
4
  /**
4
- * A 2D vector class representing a point or direction in 2D space.
5
+ * Unified vector type for both 2D and 3D usage.
6
+ * - 2D vectors use z = 0
7
+ * - 3D vectors use non-zero z when needed
5
8
  */
6
- declare class Vector2 {
9
+ declare class Vector {
7
10
  readonly x: number;
8
11
  readonly y: number;
9
- constructor(x: number, y: number);
10
- add(other: Vector2): Vector2;
11
- subtract(other: Vector2): Vector2;
12
- multiply(scalar: number): Vector2;
13
- dot(other: Vector2): number;
14
- /** Magnitude (length) of the vector. */
12
+ readonly z: number;
13
+ constructor(x: number, y: number, z?: number);
14
+ add(other: Vector): Vector;
15
+ subtract(other: Vector): Vector;
16
+ multiply(scalar: number): Vector;
17
+ dot(other: Vector): number;
15
18
  length(): number;
16
- /** Returns a normalized unit vector. Returns ZERO for zero-length vectors. */
17
- normalize(): Vector2;
18
- lerp(other: Vector2, t: number): Vector2;
19
- equals(other: Vector2, tolerance?: number): boolean;
20
- static readonly ZERO: Vector2;
21
- static readonly UP: Vector2;
22
- static readonly DOWN: Vector2;
23
- static readonly LEFT: Vector2;
24
- static readonly RIGHT: Vector2;
19
+ normalize(): Vector;
20
+ lerp(other: Vector, t: number): Vector;
21
+ equals(other: Vector, tolerance?: number): boolean;
22
+ toPlanar(): Vector;
23
+ static fromPlanar(v: Vector, z?: number): Vector;
24
+ static readonly ZERO: Vector;
25
+ static readonly UP: Vector;
26
+ static readonly DOWN: Vector;
27
+ static readonly LEFT: Vector;
28
+ static readonly RIGHT: Vector;
25
29
  }
26
30
 
27
31
  /**
28
- * A 3x3 matrix class for 2D affine transformations.
29
- * Stored in row-major order:
30
- * [ 0 1 2 ]
31
- * [ 3 4 5 ]
32
- * [ 6 7 8 ]
32
+ * A 4x4 matrix class for 3D affine transforms and projection.
33
+ * Stored in row-major order.
33
34
  */
34
- declare class Matrix3x3 {
35
+ declare class Matrix4x4 {
35
36
  readonly values: Float32Array;
36
37
  constructor(values: number[] | Float32Array);
37
- multiply(other: Matrix3x3): Matrix3x3;
38
- /** Transforms a Vector2 point (assumes z=1). */
39
- transformPoint(point: Vector2): Vector2;
40
- /** @throws Error if the matrix is not invertible. */
41
- inverse(): Matrix3x3;
42
- static identity(): Matrix3x3;
43
- static translation(tx: number, ty: number): Matrix3x3;
44
- static rotation(angle: number): Matrix3x3;
45
- static scale(sx: number, sy: number): Matrix3x3;
46
- static shear(shx: number, shy: number): Matrix3x3;
47
- static readonly IDENTITY: Matrix3x3;
38
+ multiply(other: Matrix4x4): Matrix4x4;
39
+ transformPoint(point: Vector): Vector;
40
+ transformPoint2D(point: Vector): Vector;
41
+ inverse(): Matrix4x4;
42
+ static identity(): Matrix4x4;
43
+ static translation(tx: number, ty: number, tz?: number): Matrix4x4;
44
+ static rotationX(angle: number): Matrix4x4;
45
+ static rotationY(angle: number): Matrix4x4;
46
+ static rotationZ(angle: number): Matrix4x4;
47
+ static scale(sx: number, sy: number, sz?: number): Matrix4x4;
48
+ static readonly IDENTITY: Matrix4x4;
48
49
  }
49
50
 
50
51
  /**
@@ -79,9 +80,9 @@ declare class Color {
79
80
  type PathCommandType = 'Move' | 'Line' | 'Quadratic' | 'Cubic' | 'Close';
80
81
  interface PathCommand {
81
82
  type: PathCommandType;
82
- end: Vector2;
83
- control1?: Vector2;
84
- control2?: Vector2;
83
+ end: Vector;
84
+ control1?: Vector;
85
+ control2?: Vector;
85
86
  }
86
87
 
87
88
  /**
@@ -100,17 +101,17 @@ declare class BezierPath {
100
101
  /** Builds the cache if not already valid. */
101
102
  private ensureCache;
102
103
  /** Starts a new subpath at the specified point. */
103
- moveTo(point: Vector2): void;
104
- lineTo(point: Vector2): void;
105
- quadraticTo(control: Vector2, end: Vector2): void;
106
- cubicTo(control1: Vector2, control2: Vector2, end: Vector2): void;
104
+ moveTo(point: Vector): void;
105
+ lineTo(point: Vector): void;
106
+ quadraticTo(control: Vector, end: Vector): void;
107
+ cubicTo(control1: Vector, control2: Vector, end: Vector): void;
107
108
  closePath(): void;
108
109
  getCommands(): PathCommand[];
109
110
  getLength(): number;
110
111
  /** Returns the point on the path at the normalized position t (0-1). */
111
- getPointAt(t: number): Vector2;
112
- getTangentAt(t: number): Vector2;
113
- getPoints(count: number): Vector2[];
112
+ getPointAt(t: number): Vector;
113
+ getTangentAt(t: number): Vector;
114
+ getPoints(count: number): Vector[];
114
115
  getPointCount(): number;
115
116
  clone(): BezierPath;
116
117
  /** Returns a new BezierPath where all segments are converted to Cubic curves. */
@@ -121,6 +122,60 @@ declare class BezierPath {
121
122
  private static fromCommands;
122
123
  }
123
124
 
125
+ /**
126
+ * Context provided to updater functions on each frame evaluation.
127
+ */
128
+ interface UpdaterContext {
129
+ /** Absolute scene time in seconds. */
130
+ readonly time: number;
131
+ /** Time delta from previous evaluated frame (seconds). */
132
+ readonly dt: number;
133
+ /** Monotonic frame index produced by the updater engine. */
134
+ readonly frame: number;
135
+ /** The scene currently being evaluated. */
136
+ readonly scene: Scene;
137
+ /**
138
+ * True when evaluation is discontinuous (first frame or backward seek).
139
+ * Updaters using integrators can use this to reset internal accumulators.
140
+ */
141
+ readonly discontinuous: boolean;
142
+ }
143
+ /**
144
+ * A function that mutates a mobject every evaluated frame.
145
+ */
146
+ type UpdaterFunction<T extends Mobject = Mobject> = (mobject: T, context: UpdaterContext) => void;
147
+ /**
148
+ * Public options accepted by Mobject.addUpdater.
149
+ */
150
+ interface UpdaterOptions {
151
+ /**
152
+ * Higher priority runs first. Default: 0.
153
+ * Ties are resolved by insertion order.
154
+ */
155
+ priority?: number;
156
+ /** Whether this updater starts enabled. Default: true. */
157
+ enabled?: boolean;
158
+ /** Optional descriptive label for debugging/introspection. */
159
+ name?: string;
160
+ }
161
+ /**
162
+ * Opaque handle returned from addUpdater for later removal/toggling.
163
+ */
164
+ interface UpdaterHandle {
165
+ readonly id: number;
166
+ }
167
+ /**
168
+ * Internal normalized representation stored by each mobject.
169
+ */
170
+ interface MobjectUpdaterRecord {
171
+ readonly id: number;
172
+ readonly order: number;
173
+ readonly name?: string;
174
+ readonly fn: UpdaterFunction<Mobject>;
175
+ priority: number;
176
+ enabled: boolean;
177
+ }
178
+
124
179
  /**
125
180
  * Type signature for an easing function.
126
181
  * Maps a progress value t ∈ [0, 1] to an eased value.
@@ -561,12 +616,12 @@ declare class FadeOut<T extends Mobject = Mobject> extends ExitAnimation<T> {
561
616
  declare class MoveTo<T extends Mobject = Mobject> extends TransformativeAnimation<T> {
562
617
  private startPosition;
563
618
  private readonly endPosition;
564
- constructor(target: T, destination: Vector2);
565
- constructor(target: T, x: number, y: number);
619
+ constructor(target: T, destination: Vector);
620
+ constructor(target: T, x: number, y: number, z?: number);
566
621
  protected captureStartState(): void;
567
622
  interpolate(progress: number): void;
568
623
  /** Returns the target position of the move animation. */
569
- getDestination(): Vector2;
624
+ getDestination(): Vector;
570
625
  }
571
626
 
572
627
  /**
@@ -631,8 +686,8 @@ declare class AnimationQueue {
631
686
  getTotalDuration(): number;
632
687
  }
633
688
  interface MobjectState {
634
- position: Vector2;
635
- scale: Vector2;
689
+ position: Vector;
690
+ scale: Vector;
636
691
  rotation: number;
637
692
  }
638
693
  /**
@@ -641,26 +696,60 @@ interface MobjectState {
641
696
  * Includes fluent animation API for chainable animations.
642
697
  */
643
698
  declare class Mobject {
644
- protected localMatrix: Matrix3x3;
699
+ protected localMatrix: Matrix4x4;
645
700
  protected opacityValue: number;
646
701
  protected animQueue: AnimationQueue | null;
702
+ protected pointCloud: Vector[];
703
+ protected submobjects: Mobject[];
647
704
  private savedStates;
705
+ private logicalRotation;
706
+ private logicalScale;
707
+ private updaters;
708
+ private nextUpdaterId;
709
+ private nextUpdaterOrder;
710
+ private updatersEnabled;
648
711
  parent: Mobject | null;
649
712
  constructor();
650
713
  protected getQueue(): AnimationQueue;
651
- get matrix(): Matrix3x3;
652
- getWorldMatrix(): Matrix3x3;
653
- get position(): Vector2;
714
+ get matrix(): Matrix4x4;
715
+ getWorldMatrix(): Matrix4x4;
716
+ /**
717
+ * Matrix used by renderer.
718
+ * Geometry-driven mobjects bake their own transform into points,
719
+ * so only ancestor matrix transforms should be applied at draw time.
720
+ */
721
+ getRenderMatrix(): Matrix4x4;
722
+ get position(): Vector;
654
723
  get rotation(): number;
655
- get scale(): Vector2;
724
+ get scale(): Vector;
656
725
  get opacity(): number;
657
- pos(x: number, y: number): this;
726
+ pos(x: number, y: number, z?: number): this;
658
727
  show(): this;
659
728
  hide(): this;
660
729
  setOpacity(value: number): this;
661
730
  setRotation(angle: number): this;
662
731
  setScale(sx: number, sy: number): this;
663
- applyMatrix(m: Matrix3x3): this;
732
+ applyMatrix(m: Matrix4x4): this;
733
+ addSubmobjects(...mobjects: Mobject[]): this;
734
+ removeSubmobject(mobject: Mobject): this;
735
+ clearSubmobjects(): this;
736
+ getSubmobjects(): Mobject[];
737
+ addUpdater(fn: UpdaterFunction<this>, options?: UpdaterOptions): UpdaterHandle;
738
+ removeUpdater(handleOrFn: UpdaterHandle | UpdaterFunction<this>): this;
739
+ clearUpdaters(): this;
740
+ suspendUpdaters(): this;
741
+ resumeUpdaters(): this;
742
+ enableUpdater(handleOrFn: UpdaterHandle | UpdaterFunction<this>): this;
743
+ disableUpdater(handleOrFn: UpdaterHandle | UpdaterFunction<this>): this;
744
+ hasActiveUpdaters(recursive?: boolean): boolean;
745
+ /**
746
+ * Internal API used by UpdaterEngine.
747
+ * Returns a deterministic snapshot for current-frame execution.
748
+ */
749
+ getUpdaterRecordsSnapshot(): MobjectUpdaterRecord[];
750
+ private setUpdaterEnabled;
751
+ protected setPointCloud(points: Array<Vector>): void;
752
+ protected getPointCloud(): Vector[];
664
753
  saveState(): this;
665
754
  getSavedState(): MobjectState | undefined;
666
755
  clearSavedStates(): this;
@@ -678,9 +767,15 @@ declare class Mobject {
678
767
  fadeOut(durationSeconds?: number): this & {
679
768
  toAnimation(): Animation<Mobject>;
680
769
  };
770
+ moveTo(destination: Vector, durationSeconds?: number): this & {
771
+ toAnimation(): Animation<Mobject>;
772
+ };
681
773
  moveTo(x: number, y: number, durationSeconds?: number): this & {
682
774
  toAnimation(): Animation<Mobject>;
683
775
  };
776
+ moveTo(x: number, y: number, z: number, durationSeconds?: number): this & {
777
+ toAnimation(): Animation<Mobject>;
778
+ };
684
779
  rotate(angle: number, durationSeconds?: number): this & {
685
780
  toAnimation(): Animation<Mobject>;
686
781
  };
@@ -711,6 +806,13 @@ declare class Mobject {
711
806
  * Used by the segment cache to detect changes.
712
807
  */
713
808
  computeHash(): number;
809
+ protected applyMatrixToOwnGeometry(m: Matrix4x4): void;
810
+ protected usesGeometryTransforms(): boolean;
811
+ private collectGeometryPoints;
812
+ private getGeometryCenter;
813
+ private syncLocalMatrixFromGeometry;
814
+ private updateLogicalStateFromMatrix;
815
+ private setLocalMatrix;
714
816
  }
715
817
 
716
818
  /**
@@ -788,6 +890,7 @@ declare class VMobject extends Mobject {
788
890
  minY: number;
789
891
  maxY: number;
790
892
  };
893
+ protected applyMatrixToOwnGeometry(m: Matrix4x4): void;
791
894
  /**
792
895
  * Progressively draws the VMobject's paths from start to end.
793
896
  * Preserves fill throughout the animation.
@@ -818,6 +921,7 @@ declare class VMobject extends Mobject {
818
921
  * stroke/fill colors, widths, opacity, and path geometry.
819
922
  */
820
923
  computeHash(): number;
924
+ private syncPointCloudFromPaths;
821
925
  }
822
926
 
823
927
  /**
@@ -1086,7 +1190,7 @@ interface ResolvedCameraConfig {
1086
1190
  * @example
1087
1191
  * // Instant camera manipulation
1088
1192
  * camera.zoomTo(2);
1089
- * camera.panTo(new Vector2(5, 3));
1193
+ * camera.panTo(new Vector(5, 3));
1090
1194
  *
1091
1195
  * @example
1092
1196
  * // Animated camera movement via frame
@@ -1111,14 +1215,14 @@ declare class Camera {
1111
1215
  get frameXRadius(): number;
1112
1216
  get pixelWidth(): number;
1113
1217
  get pixelHeight(): number;
1114
- get position(): Vector2;
1218
+ get position(): Vector;
1115
1219
  get zoom(): number;
1116
1220
  get rotation(): number;
1117
- pan(delta: Vector2): this;
1118
- panTo(position: Vector2): this;
1221
+ pan(delta: Vector): this;
1222
+ panTo(position: Vector): this;
1119
1223
  zoomTo(level: number): this;
1120
1224
  rotateTo(angle: number): this;
1121
- getViewMatrix(): Matrix3x3;
1225
+ getViewMatrix(): Matrix4x4;
1122
1226
  /**
1123
1227
  * Transforms a world-space position to screen-space (pixel) coordinates.
1124
1228
  *
@@ -1132,7 +1236,7 @@ declare class Camera {
1132
1236
  * const screenPos = camera.worldToScreen(circle.position);
1133
1237
  * console.log(`Circle is at pixel (${screenPos.x}, ${screenPos.y})`);
1134
1238
  */
1135
- worldToScreen(pos: Vector2): Vector2;
1239
+ worldToScreen(pos: Vector): Vector;
1136
1240
  /**
1137
1241
  * Transforms a screen-space (pixel) position to world coordinates.
1138
1242
  * This is the inverse of worldToScreen.
@@ -1142,9 +1246,9 @@ declare class Camera {
1142
1246
  *
1143
1247
  * @example
1144
1248
  * // Convert a mouse click position to world coordinates
1145
- * const worldPos = camera.screenToWorld(new Vector2(mouseX, mouseY));
1249
+ * const worldPos = camera.screenToWorld(new Vector(mouseX, mouseY));
1146
1250
  */
1147
- screenToWorld(pos: Vector2): Vector2;
1251
+ screenToWorld(pos: Vector): Vector;
1148
1252
  /**
1149
1253
  * Checks if a world-space position is currently visible within the camera frame.
1150
1254
  *
@@ -1156,7 +1260,7 @@ declare class Camera {
1156
1260
  * console.log('Object is visible');
1157
1261
  * }
1158
1262
  */
1159
- isInView(pos: Vector2): boolean;
1263
+ isInView(pos: Vector): boolean;
1160
1264
  reset(): this;
1161
1265
  /**
1162
1266
  * Hashes camera config and the CameraFrame's full transform state.
@@ -1170,11 +1274,9 @@ type Edge = 'TOP' | 'BOTTOM' | 'LEFT' | 'RIGHT';
1170
1274
 
1171
1275
  /**
1172
1276
  * A collection of VMobjects that can be manipulated as a single unit.
1173
- * Uses Scene Graph hierarchy: transforms on parent are inherited by children
1174
- * via getWorldMatrix() calculation, not by mutating child matrices.
1277
+ * Uses Mobject's submobject hierarchy and recursive geometry transforms.
1175
1278
  */
1176
1279
  declare class VGroup extends VMobject {
1177
- protected children: VMobject[];
1178
1280
  constructor(...mobjects: VMobject[]);
1179
1281
  get length(): number;
1180
1282
  add(...mobjects: VMobject[]): this;
@@ -1182,7 +1284,6 @@ declare class VGroup extends VMobject {
1182
1284
  clear(): this;
1183
1285
  getChildren(): VMobject[];
1184
1286
  get(index: number): VMobject | undefined;
1185
- pos(x: number, y: number): this;
1186
1287
  show(): this;
1187
1288
  hide(): this;
1188
1289
  /**
@@ -1215,11 +1316,178 @@ declare class VGroup extends VMobject {
1215
1316
  toCorner(corner: CornerPosition, buff?: number): this;
1216
1317
  arrange(direction?: Direction, buff?: number, shouldCenter?: boolean): this;
1217
1318
  alignTo(target: VMobject, edge: Edge): this;
1319
+ computeHash(): number;
1320
+ }
1321
+
1322
+ declare class Arc extends VMobject {
1323
+ readonly radius: number;
1324
+ readonly startAngle: number;
1325
+ readonly endAngle: number;
1326
+ constructor(radius?: number, startAngle?: number, endAngle?: number);
1327
+ private generatePath;
1328
+ }
1329
+
1330
+ declare class Circle extends Arc {
1331
+ constructor(radius?: number);
1332
+ }
1333
+
1334
+ declare class Line extends VMobject {
1335
+ readonly start: Vector;
1336
+ readonly end: Vector;
1337
+ constructor(x1?: number, y1?: number, x2?: number, y2?: number);
1338
+ private generatePath;
1339
+ }
1340
+
1341
+ declare class Polygon extends VMobject {
1342
+ readonly vertices: Vector[];
1343
+ constructor(...points: Array<[number, number]>);
1344
+ private generatePath;
1345
+ }
1346
+
1347
+ declare class Rectangle extends Polygon {
1348
+ readonly width: number;
1349
+ readonly height: number;
1350
+ constructor(width?: number, height?: number);
1351
+ }
1352
+
1353
+ declare class Arrow extends Line {
1354
+ readonly tipLength: number;
1355
+ readonly tipAngle: number;
1356
+ constructor(x1?: number, y1?: number, x2?: number, y2?: number, tipLength?: number, tipAngle?: number);
1357
+ private addTip;
1358
+ }
1359
+
1360
+ /**
1361
+ * A VMobject representing a single glyph character.
1362
+ * Converts fontkit glyph path to BezierPath for rendering.
1363
+ */
1364
+ declare class Glyph extends VMobject {
1365
+ readonly character: string;
1366
+ readonly glyphId: number;
1367
+ constructor(fontkitGlyph: Glyph$1, character: string, scale: number, offsetX: number, offsetY: number);
1368
+ }
1369
+
1370
+ /**
1371
+ * A VGroup of vectorized glyphs created from a text string using fontkit.
1372
+ * Each character becomes a Glyph VMobject that can be individually animated.
1373
+ *
1374
+ * Uses VMobject's fill/stroke as the source of truth (same as geometry).
1375
+ * Default: white fill, white stroke width 2.
1376
+ */
1377
+ declare class Text extends VGroup {
1378
+ readonly text: string;
1379
+ private fontSize;
1380
+ private fontPath;
1381
+ constructor(text: string, fontPath?: string, options?: {
1382
+ fontSize?: number;
1383
+ });
1384
+ private buildGlyphs;
1385
+ /** Propagates this Text's fill/stroke to all Glyph children. */
1386
+ private propagate;
1387
+ stroke(color: Color, width?: number): this;
1388
+ fill(color: Color, opacity?: number): this;
1389
+ getFontSize(): number;
1390
+ getGlyph(index: number): Glyph | undefined;
1391
+ }
1392
+
1393
+ /** Unique identifier for graph nodes. */
1394
+ type GraphNodeId = string;
1395
+ /** Configuration for creating a graph node. */
1396
+ interface NodeConfig {
1397
+ position?: {
1398
+ x: number;
1399
+ y: number;
1400
+ };
1401
+ radius?: number;
1402
+ strokeColor?: Color;
1403
+ strokeWidth?: number;
1404
+ fillColor?: Color;
1405
+ fillOpacity?: number;
1406
+ }
1407
+ /** Configuration for creating a graph edge. */
1408
+ interface EdgeConfig {
1409
+ strokeColor?: Color;
1410
+ strokeWidth?: number;
1411
+ curved?: boolean;
1412
+ }
1413
+ /** Supported layout algorithms. */
1414
+ type LayoutType = 'force-directed' | 'tree' | 'circular';
1415
+ /** Configuration for graph layout algorithms. */
1416
+ interface LayoutConfig {
1417
+ radius?: number;
1418
+ levelHeight?: number;
1419
+ siblingSpacing?: number;
1420
+ iterations?: number;
1421
+ springLength?: number;
1422
+ repulsion?: number;
1423
+ attraction?: number;
1424
+ damping?: number;
1425
+ minDistance?: number;
1426
+ }
1427
+
1428
+ /**
1429
+ * A graph node represented as a circular VMobject.
1430
+ * Supports customizable radius, stroke, and fill styling.
1431
+ */
1432
+ declare class GraphNode extends VMobject {
1433
+ readonly id: GraphNodeId;
1434
+ private nodeRadius;
1435
+ constructor(id: GraphNodeId, config?: NodeConfig);
1436
+ get radius(): number;
1218
1437
  /**
1219
- * Recursively hashes this VGroup and all children.
1220
- * Any child state change invalidates segments containing this group.
1438
+ * Generates a circular BezierPath approximation using cubic Bezier curves.
1439
+ * Uses the standard 4-point circle approximation with control point factor ~0.5523.
1221
1440
  */
1222
- computeHash(): number;
1441
+ private generateCirclePath;
1442
+ getCenter(): Vector;
1443
+ }
1444
+
1445
+ /**
1446
+ * A graph edge represented as a BezierPath connecting two nodes.
1447
+ * Supports straight or curved edges with customizable styling.
1448
+ */
1449
+ declare class GraphEdge extends VMobject {
1450
+ readonly source: GraphNodeId;
1451
+ readonly target: GraphNodeId;
1452
+ private sourceNode;
1453
+ private targetNode;
1454
+ private curved;
1455
+ constructor(sourceNode: GraphNode, targetNode: GraphNode, config?: EdgeConfig);
1456
+ /**
1457
+ * Recalculates the edge path based on current node positions.
1458
+ * Call this when nodes move to update the edge connection.
1459
+ */
1460
+ updatePath(): void;
1461
+ getPath(): BezierPath | undefined;
1462
+ /**
1463
+ * Updates node references (used when nodes are replaced).
1464
+ */
1465
+ setNodes(sourceNode: GraphNode, targetNode: GraphNode): void;
1466
+ }
1467
+
1468
+ /**
1469
+ * A graph structure containing nodes and edges.
1470
+ * Manages nodes as VMobjects and edges as BezierPath curves.
1471
+ * Supports multiple layout algorithms for automatic positioning.
1472
+ */
1473
+ declare class Graph extends VGroup {
1474
+ private nodes;
1475
+ private edges;
1476
+ constructor();
1477
+ /** Adds a node to the graph. */
1478
+ addNode(id: GraphNodeId, config?: NodeConfig): GraphNode;
1479
+ /** Removes a node and all connected edges from the graph. */
1480
+ removeNode(id: GraphNodeId): this;
1481
+ getNode(id: GraphNodeId): GraphNode | undefined;
1482
+ getNodes(): GraphNode[];
1483
+ addEdge(sourceId: GraphNodeId, targetId: GraphNodeId, config?: EdgeConfig): GraphEdge | undefined;
1484
+ removeEdge(sourceId: GraphNodeId, targetId: GraphNodeId): this;
1485
+ private removeEdgeInternal;
1486
+ getEdgePath(sourceId: GraphNodeId, targetId: GraphNodeId): ReturnType<GraphEdge['getPath']>;
1487
+ getEdges(): GraphEdge[];
1488
+ /** Applies a layout algorithm to reposition all nodes. */
1489
+ layout(type: LayoutType, config?: LayoutConfig): this;
1490
+ updateEdges(): this;
1223
1491
  }
1224
1492
 
1225
1493
  /**
@@ -1367,6 +1635,7 @@ declare class KeyframeAnimation<T extends Mobject = Mobject> extends Animation<T
1367
1635
  interpolate(progress: number): void;
1368
1636
  }
1369
1637
 
1638
+ type FollowOffsetInput = Vector | readonly [number, number] | readonly [number, number, number];
1370
1639
  /**
1371
1640
  * Configuration options for the Follow animation.
1372
1641
  */
@@ -1374,9 +1643,16 @@ interface FollowConfig {
1374
1643
  /**
1375
1644
  * Offset from the target's position. The camera will track
1376
1645
  * (target.position + offset) instead of the exact target position.
1377
- * @default Vector2.ZERO
1646
+ * Accepts:
1647
+ * - `Vector`
1648
+ * - `[x, y]`
1649
+ * - `[x, y, z]`
1650
+ *
1651
+ * Note: camera follow movement is planar, so only x/y affect the CameraFrame position.
1652
+ * If provided, z is accepted for API consistency but ignored by this animation.
1653
+ * @default Vector.ZERO
1378
1654
  */
1379
- offset?: Vector2;
1655
+ offset?: FollowOffsetInput;
1380
1656
  /**
1381
1657
  * Damping factor for smooth following (0 to 1).
1382
1658
  * - 0 = instant snap to target (no smoothing)
@@ -1402,7 +1678,14 @@ interface FollowConfig {
1402
1678
  * @example
1403
1679
  * // Follow with offset (camera leads the target)
1404
1680
  * this.play(new Follow(this.frame, car, {
1405
- * offset: new Vector2(2, 0), // Camera 2 units ahead
1681
+ * offset: [2, 0], // Camera 2 units ahead
1682
+ * damping: 0.5
1683
+ * }).duration(10));
1684
+ *
1685
+ * @example
1686
+ * // 3D tuple offset is accepted for consistency, but z is ignored by camera follow
1687
+ * this.play(new Follow(this.frame, car, {
1688
+ * offset: [2, 0, 1],
1406
1689
  * damping: 0.5
1407
1690
  * }).duration(10));
1408
1691
  */
@@ -1430,6 +1713,7 @@ declare class Follow extends Animation<CameraFrame> {
1430
1713
  * @param progress - Animation progress (0 to 1)
1431
1714
  */
1432
1715
  interpolate(progress: number): void;
1716
+ private static normalizeOffset;
1433
1717
  }
1434
1718
 
1435
1719
  /**
@@ -1620,6 +1904,11 @@ interface SceneConfig {
1620
1904
  readonly frameRate?: number;
1621
1905
  }
1622
1906
 
1907
+ /** Protocol for objects that contribute to segment hashing. */
1908
+ interface Hashable {
1909
+ computeHash(): number;
1910
+ }
1911
+
1623
1912
  /**
1624
1913
  * A Segment represents one independent rendering unit,
1625
1914
  * corresponding to a single play() or wait() call.
@@ -1640,6 +1929,30 @@ interface Segment {
1640
1929
  readonly hash: number;
1641
1930
  }
1642
1931
 
1932
+ /**
1933
+ * Manages a disk-based cache of rendered segment partial files.
1934
+ *
1935
+ * Each segment is stored as a video file keyed by its CRC32 hash.
1936
+ * On re-render, segments whose hashes match an existing file are skipped.
1937
+ */
1938
+ declare class SegmentCache {
1939
+ private readonly cacheDir;
1940
+ constructor(cacheDir: string);
1941
+ /** Ensure the cache directory exists. */
1942
+ init(): Promise<void>;
1943
+ /** Check if a rendered segment file exists for the given hash. */
1944
+ has(hash: number): boolean;
1945
+ /** Get the absolute file path for a segment hash. */
1946
+ getPath(hash: number): string;
1947
+ /** Get the cache directory path. */
1948
+ getDir(): string;
1949
+ /**
1950
+ * Remove cached files that are not in the active set.
1951
+ * Call after a full render to clean up stale segments.
1952
+ */
1953
+ prune(activeHashes: Set<number>): Promise<void>;
1954
+ }
1955
+
1643
1956
  /**
1644
1957
  * Scene is the core container that manages Mobjects and coordinates animations.
1645
1958
  * It provides both a simple API for playing animations and access to the
@@ -1650,6 +1963,7 @@ declare class Scene {
1650
1963
  private readonly mobjects;
1651
1964
  private readonly timeline;
1652
1965
  private readonly _camera;
1966
+ private readonly updaterEngine;
1653
1967
  private readonly segmentList;
1654
1968
  private playheadTime;
1655
1969
  constructor(config?: SceneConfig);
@@ -1718,6 +2032,18 @@ declare class Scene {
1718
2032
  * Get the total duration of all scheduled animations.
1719
2033
  */
1720
2034
  getTotalDuration(): number;
2035
+ /**
2036
+ * Evaluates scene state at an absolute time.
2037
+ * Execution order is deterministic:
2038
+ * 1) timeline animations
2039
+ * 2) mobject updaters
2040
+ */
2041
+ evaluateFrame(time: number): void;
2042
+ /**
2043
+ * Returns true if any scene mobject (or camera frame) has active updaters.
2044
+ * Used by renderer to disable unsafe segment caching.
2045
+ */
2046
+ hasActiveUpdaters(): boolean;
1721
2047
  /**
1722
2048
  * Get the underlying Timeline for advanced control.
1723
2049
  * Use this for direct manipulation of animation timing.
@@ -1755,177 +2081,6 @@ declare class Scene {
1755
2081
  private computeSegmentHash;
1756
2082
  }
1757
2083
 
1758
- declare class Arc extends VMobject {
1759
- readonly radius: number;
1760
- readonly startAngle: number;
1761
- readonly endAngle: number;
1762
- constructor(radius?: number, startAngle?: number, endAngle?: number);
1763
- private generatePath;
1764
- }
1765
-
1766
- declare class Line extends VMobject {
1767
- readonly start: Vector2;
1768
- readonly end: Vector2;
1769
- constructor(x1?: number, y1?: number, x2?: number, y2?: number);
1770
- private generatePath;
1771
- }
1772
-
1773
- declare class Arrow extends Line {
1774
- readonly tipLength: number;
1775
- readonly tipAngle: number;
1776
- constructor(x1?: number, y1?: number, x2?: number, y2?: number, tipLength?: number, tipAngle?: number);
1777
- private addTip;
1778
- }
1779
-
1780
- declare class Circle extends Arc {
1781
- constructor(radius?: number);
1782
- }
1783
-
1784
- declare class Polygon extends VMobject {
1785
- readonly vertices: Vector2[];
1786
- constructor(...points: Array<[number, number]>);
1787
- private generatePath;
1788
- }
1789
-
1790
- declare class Rectangle extends Polygon {
1791
- readonly width: number;
1792
- readonly height: number;
1793
- constructor(width?: number, height?: number);
1794
- }
1795
-
1796
- /**
1797
- * A VMobject representing a single glyph character.
1798
- * Converts fontkit glyph path to BezierPath for rendering.
1799
- */
1800
- declare class Glyph extends VMobject {
1801
- readonly character: string;
1802
- readonly glyphId: number;
1803
- constructor(fontkitGlyph: Glyph$1, character: string, scale: number, offsetX: number, offsetY: number);
1804
- }
1805
-
1806
- /**
1807
- * A VGroup of vectorized glyphs created from a text string using fontkit.
1808
- * Each character becomes a Glyph VMobject that can be individually animated.
1809
- *
1810
- * Uses VMobject's fill/stroke as the source of truth (same as geometry).
1811
- * Default: white fill, white stroke width 2.
1812
- */
1813
- declare class Text extends VGroup {
1814
- readonly text: string;
1815
- private fontSize;
1816
- private fontPath;
1817
- constructor(text: string, fontPath?: string, options?: {
1818
- fontSize?: number;
1819
- });
1820
- private buildGlyphs;
1821
- /** Propagates this Text's fill/stroke to all Glyph children. */
1822
- private propagate;
1823
- stroke(color: Color, width?: number): this;
1824
- fill(color: Color, opacity?: number): this;
1825
- getFontSize(): number;
1826
- getGlyph(index: number): Glyph | undefined;
1827
- }
1828
-
1829
- /** Unique identifier for graph nodes. */
1830
- type GraphNodeId = string;
1831
- /** Configuration for creating a graph node. */
1832
- interface NodeConfig {
1833
- position?: {
1834
- x: number;
1835
- y: number;
1836
- };
1837
- radius?: number;
1838
- strokeColor?: Color;
1839
- strokeWidth?: number;
1840
- fillColor?: Color;
1841
- fillOpacity?: number;
1842
- }
1843
- /** Configuration for creating a graph edge. */
1844
- interface EdgeConfig {
1845
- strokeColor?: Color;
1846
- strokeWidth?: number;
1847
- curved?: boolean;
1848
- }
1849
- /** Supported layout algorithms. */
1850
- type LayoutType = 'force-directed' | 'tree' | 'circular';
1851
- /** Configuration for graph layout algorithms. */
1852
- interface LayoutConfig {
1853
- radius?: number;
1854
- levelHeight?: number;
1855
- siblingSpacing?: number;
1856
- iterations?: number;
1857
- springLength?: number;
1858
- repulsion?: number;
1859
- attraction?: number;
1860
- damping?: number;
1861
- minDistance?: number;
1862
- }
1863
-
1864
- /**
1865
- * A graph node represented as a circular VMobject.
1866
- * Supports customizable radius, stroke, and fill styling.
1867
- */
1868
- declare class GraphNode extends VMobject {
1869
- readonly id: GraphNodeId;
1870
- private nodeRadius;
1871
- constructor(id: GraphNodeId, config?: NodeConfig);
1872
- get radius(): number;
1873
- /**
1874
- * Generates a circular BezierPath approximation using cubic Bezier curves.
1875
- * Uses the standard 4-point circle approximation with control point factor ~0.5523.
1876
- */
1877
- private generateCirclePath;
1878
- getCenter(): Vector2;
1879
- }
1880
-
1881
- /**
1882
- * A graph edge represented as a BezierPath connecting two nodes.
1883
- * Supports straight or curved edges with customizable styling.
1884
- */
1885
- declare class GraphEdge extends VMobject {
1886
- readonly source: GraphNodeId;
1887
- readonly target: GraphNodeId;
1888
- private sourceNode;
1889
- private targetNode;
1890
- private curved;
1891
- constructor(sourceNode: GraphNode, targetNode: GraphNode, config?: EdgeConfig);
1892
- /**
1893
- * Recalculates the edge path based on current node positions.
1894
- * Call this when nodes move to update the edge connection.
1895
- */
1896
- updatePath(): void;
1897
- getPath(): BezierPath | undefined;
1898
- /**
1899
- * Updates node references (used when nodes are replaced).
1900
- */
1901
- setNodes(sourceNode: GraphNode, targetNode: GraphNode): void;
1902
- }
1903
-
1904
- /**
1905
- * A graph structure containing nodes and edges.
1906
- * Manages nodes as VMobjects and edges as BezierPath curves.
1907
- * Supports multiple layout algorithms for automatic positioning.
1908
- */
1909
- declare class Graph extends VGroup {
1910
- private nodes;
1911
- private edges;
1912
- constructor();
1913
- /** Adds a node to the graph. */
1914
- addNode(id: GraphNodeId, config?: NodeConfig): GraphNode;
1915
- /** Removes a node and all connected edges from the graph. */
1916
- removeNode(id: GraphNodeId): this;
1917
- getNode(id: GraphNodeId): GraphNode | undefined;
1918
- getNodes(): GraphNode[];
1919
- addEdge(sourceId: GraphNodeId, targetId: GraphNodeId, config?: EdgeConfig): GraphEdge | undefined;
1920
- removeEdge(sourceId: GraphNodeId, targetId: GraphNodeId): this;
1921
- private removeEdgeInternal;
1922
- getEdgePath(sourceId: GraphNodeId, targetId: GraphNodeId): ReturnType<GraphEdge['getPath']>;
1923
- getEdges(): GraphEdge[];
1924
- /** Applies a layout algorithm to reposition all nodes. */
1925
- layout(type: LayoutType, config?: LayoutConfig): this;
1926
- updateEdges(): this;
1927
- }
1928
-
1929
2084
  /**
1930
2085
  * Supported render output formats.
1931
2086
  * - sprite: PNG sequence (frame_0000.png, frame_0001.png, ...)
@@ -2061,4 +2216,59 @@ declare class Renderer {
2061
2216
  private renderSegmentToFile;
2062
2217
  }
2063
2218
 
2064
- export { Animation, type AnimationConfig, Arc, Arrow, Camera, type CameraConfig, CameraFrame, Circle, Color, Draw, type EasingFunction, type EdgeConfig, FadeIn, FadeOut, Follow, Glyph, Graph, GraphEdge, GraphNode, type GraphNodeId, type Keyframe, KeyframeAnimation, KeyframeTrack, type LayoutConfig, type LayoutType, Line, Mobject, MorphTo, MoveTo, type NodeConfig, Parallel, Polygon, type ProgressCallback, Rectangle, type RenderConfig, type RenderFormat, type RenderProgress, type RenderQuality, Renderer, Resolution, type ResolvedCameraConfig, Rotate, Scale, Scene, type SceneConfig, type ScheduledAnimation, Sequence, Shake, Text, Timeline, type TimelineConfig, Unwrite, VGroup, VMobject, Vector2, Write, clearRegistry, smooth as defaultEasing, doubleSmooth, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, exponentialDecay, getEasing, hasEasing, linear, lingering, notQuiteThere, registerEasing, runningStart, rushFrom, rushInto, slowInto, smooth, thereAndBack, thereAndBackWithPause, unregisterEasing, wiggle };
2219
+ /**
2220
+ * Renders individual frames from a Scene.
2221
+ * Responsible for drawing mobjects to a canvas at a specific point in time.
2222
+ */
2223
+ declare class FrameRenderer {
2224
+ private readonly scene;
2225
+ private readonly width;
2226
+ private readonly height;
2227
+ constructor(scene: Scene, width: number, height: number);
2228
+ /**
2229
+ * Calculates the matrix that transforms Manim world coordinates to screen pixels.
2230
+ *
2231
+ * Manim coordinate system:
2232
+ * - Origin at center of screen
2233
+ * - Y-axis points up
2234
+ * - frameHeight = 8.0 units
2235
+ *
2236
+ * Screen coordinate system:
2237
+ * - Origin at top-left
2238
+ * - Y-axis points down
2239
+ * - Width x Height pixels
2240
+ */
2241
+ private calculateWorldToScreenMatrix;
2242
+ /**
2243
+ * Renders a single frame at the specified time.
2244
+ */
2245
+ renderFrame(time: number): Canvas;
2246
+ /**
2247
+ * Gets the canvas dimensions.
2248
+ */
2249
+ getDimensions(): {
2250
+ width: number;
2251
+ height: number;
2252
+ };
2253
+ }
2254
+
2255
+ /**
2256
+ * Tracks rendering progress and reports updates via callback.
2257
+ */
2258
+ declare class ProgressReporter {
2259
+ private readonly totalFrames;
2260
+ private readonly onProgress?;
2261
+ private readonly startTime;
2262
+ private currentFrame;
2263
+ constructor(totalFrames: number, onProgress?: ProgressCallback);
2264
+ /**
2265
+ * Report progress for the current frame.
2266
+ */
2267
+ reportFrame(frameIndex: number): void;
2268
+ /**
2269
+ * Report rendering complete.
2270
+ */
2271
+ complete(): void;
2272
+ }
2273
+
2274
+ export { Animation, type AnimationConfig, Arc, Arrow, Camera, type CameraConfig, CameraFrame, Circle, Color, Draw, type EasingFunction, type EdgeConfig, FadeIn, FadeOut, Follow, FrameRenderer, Glyph, Graph, GraphEdge, GraphNode, type GraphNodeId, type Hashable, type Keyframe, KeyframeAnimation, KeyframeTrack, type LayoutConfig, type LayoutType, Line, Mobject, MorphTo, MoveTo, type NodeConfig, Parallel, Polygon, type ProgressCallback, ProgressReporter, Rectangle, type RenderConfig, type RenderFormat, type RenderProgress, type RenderQuality, Renderer, Resolution, type ResolvedCameraConfig, Rotate, Scale, Scene, type SceneConfig, type ScheduledAnimation, type Segment, SegmentCache, Sequence, Shake, Text, Timeline, type TimelineConfig, Unwrite, type UpdaterContext, type UpdaterFunction, type UpdaterHandle, type UpdaterOptions, VGroup, VMobject, Vector, Write, clearRegistry, smooth as defaultEasing, doubleSmooth, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, exponentialDecay, getEasing, hasEasing, linear, lingering, notQuiteThere, registerEasing, runningStart, rushFrom, rushInto, slowInto, smooth, thereAndBack, thereAndBackWithPause, unregisterEasing, wiggle };