Skip to main content

advanced_flow/
advanced_flow.rs

1use motion_canvas_rs::prelude::*;
2use std::time::Duration;
3
4fn main() {
5    // 1. Initialize Project with full API coverage
6    let mut project = Project::default()
7        .with_fps(120)
8        .with_gpu(true)
9        .with_cache(true)
10        .with_ffmpeg(true)
11        .with_output_path("output")
12        .with_title("Advanced Flow")
13        .close_on_finish();
14
15    // 2. Setup Nodes
16    let mut path = BezPath::new();
17    path.move_to((100.0, 300.0));
18    path.curve_to((250.0, 100.0), (550.0, 500.0), (700.0, 300.0));
19    let path_node = PathNode::default()
20        .with_path(path)
21        .with_stroke(Color::rgb8(0x44, 0x44, 0x44), 2.0);
22    let follower = Circle::default()
23        .with_position(Vec2::new(100.0, 300.0))
24        .with_radius(20.0)
25        .with_fill(Color::rgb8(0xe1, 0x32, 0x38)); // Red
26
27    // Showcase: Rect and Line
28    let background_rect = Rect::default()
29        .with_position(Vec2::new(400.0, 300.0))
30        .with_size(Vec2::new(760.0, 560.0))
31        .with_fill(Color::rgba8(0x33, 0x33, 0x33, 150))
32        .with_radius(20.0);
33
34    let divider_line = Line::default()
35        .with_start(Vec2::new(0.0, 300.0))
36        .with_end(Vec2::new(0.0, 300.0))
37        .with_stroke(Color::rgb8(0x44, 0x44, 0x44), 1.0);
38    let title_text = TextNode::default()
39        .with_position(Vec2::new(50.0, 50.0))
40        .with_anchor(Vec2::new(-1.0, -1.0))
41        .with_text("Motion Canvas in Rust")
42        .with_font_size(40.0)
43        .with_fill(Color::rgb8(0x68, 0xab, 0xdf)) // Blue
44        .with_font("JetBrains Mono");
45
46    let code_block = CodeNode::default()
47        .with_anchor(Vec2::new(-1.0, -1.0))
48        .with_position(Vec2::new(50.0, 415.0))
49        .with_language("rust")
50        .with_opacity(0.0);
51
52    let math_eq = MathNode::default()
53        .with_position(Vec2::new(150.0, 150.0))
54        .with_equation("f(x) = sin(x)")
55        .with_font_size(30.0)
56        .with_fill(Color::rgb8(0xe6, 0xa7, 0x00)); // Yellow
57
58    let logo = ImageNode::default()
59        .with_position(Vec2::new(650.0, 150.0))
60        .with_path("./examples/images/motion-canvas-logo.png")
61        .with_size(Vec2::new(150.0, 150.0));
62
63    project.scene.video_timeline.add(all![
64        // Show code
65        chain![
66            code_block.opacity.to(1.0, Duration::from_secs(1)),
67            code_block.append("fn main() {\n", Duration::from_secs(1)),
68            code_block.append(
69                "    let mut engine = MotionCanvas::new();\n",
70                Duration::from_secs(1)
71            ),
72            code_block.append("    engine.render();\n", Duration::from_secs(1)),
73            code_block.append("}", Duration::from_secs(1)),
74            // Staggered appearance of nodes
75            sequence![
76                Duration::from_millis(200),
77                divider_line
78                    .end
79                    .to(Vec2::new(800.0, 300.0), Duration::from_secs(1))
80                    .ease(easings::cubic_out),
81                follower
82                    .radius
83                    .to(30.0, Duration::from_millis(500))
84                    .ease(easings::elastic_out),
85            ],
86            // The path follow combined with a "race" logic
87            any![
88                follower
89                    .position
90                    .follow(&path_node, Duration::from_secs(3))
91                    .ease(easings::cubic_in_out),
92                // Race: if this 'wait' finishes first, the follow is done
93                wait(Duration::from_secs(4)),
94            ],
95            // Final flourishes using different easings
96            all![
97                follower
98                    .radius
99                    .to(10.0, Duration::from_secs(1))
100                    .ease(easings::quad_out),
101                divider_line
102                    .start
103                    .to(Vec2::new(400.0, 300.0), Duration::from_secs(1))
104                    .ease(easings::cubic_in),
105            ]
106        ]
107    ]);
108
109    // 4. Build Scene
110    project.scene.add(Box::new(background_rect.clone()));
111    project.scene.add(Box::new(divider_line.clone()));
112    project.scene.add(Box::new(path_node.clone()));
113    project.scene.add(Box::new(follower.clone()));
114    project.scene.add(Box::new(title_text.clone()));
115    project.scene.add(Box::new(code_block.clone()));
116    project.scene.add(Box::new(math_eq.clone()));
117    project.scene.add(Box::new(logo.clone()));
118
119    // 5. Run (Choose show() for interactive or export() for PNGs)
120    project.show().expect("Failed to render");
121    // project.export().expect("Failed to export");
122}