Skip to main content

Color

Struct Color 

Source
pub struct Color {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}
Expand description

32-bit RGBA color.

Fields§

§r: u8

Red component.

§g: u8

Green component.

§b: u8

Blue component.

§a: u8

Alpha component.

Implementations§

Source§

impl Color

Source

pub const fn rgb8(r: u8, g: u8, b: u8) -> Color

Creates a new RGB color with 255 alpha.

Examples found in repository?
examples/explainer.rs (line 6)
6const BG: Color = Color::rgb8(0x0e, 0x0e, 0x12);
7const WHITE: Color = Color::rgb8(0xf0, 0xf0, 0xf0);
8const DIM: Color = Color::rgb8(0x55, 0x55, 0x66);
9const ACCENT: Color = Color::rgb8(0x68, 0xab, 0xdf);
10const RED: Color = Color::rgb8(0xe1, 0x32, 0x38);
11const YELLOW: Color = Color::rgb8(0xe6, 0xa7, 0x00);
12const GREEN: Color = Color::rgb8(0x25, 0xc2, 0x81);
13const TEAL: Color = Color::rgb8(0x20, 0xb2, 0xaa);
14
15const CANVAS_W: u32 = 1280;
16const CANVAS_H: u32 = 720;
17const LEFT: f32 = 40.0;
18
19fn ms(n: u64) -> Duration {
20    Duration::from_millis(n)
21}
22fn secs(n: u64) -> Duration {
23    Duration::from_secs(n)
24}
25
26// ── Text Helpers ───────────────────────────────────────────────────────────
27fn title(text: &str, y: f32) -> TextNode {
28    TextNode::default()
29        .with_anchor(Vec2::new(-1.0, -1.0))
30        .with_position(Vec2::new(LEFT, y))
31        .with_text(text)
32        .with_font_size(36.0)
33        .with_fill(ACCENT)
34        .with_font(FONT)
35        .with_opacity(0.0)
36}
37fn h2(text: &str, y: f32) -> TextNode {
38    TextNode::default()
39        .with_anchor(Vec2::new(-1.0, -1.0))
40        .with_position(Vec2::new(LEFT, y))
41        .with_text(text)
42        .with_font_size(22.0)
43        .with_fill(WHITE)
44        .with_font(FONT)
45        .with_opacity(0.0)
46}
47fn body(text: &str, y: f32) -> TextNode {
48    TextNode::default()
49        .with_anchor(Vec2::new(-1.0, -1.0))
50        .with_position(Vec2::new(LEFT, y))
51        .with_text(text)
52        .with_font_size(17.0)
53        .with_fill(Color::rgb8(0xcc, 0xcc, 0xdd))
54        .with_font(FONT)
55        .with_opacity(0.0)
56}
More examples
Hide additional examples
examples/news_feed.rs (line 7)
7const BG: Color = Color::rgb8(0x0e, 0x0e, 0x12);
8const WHITE: Color = Color::rgb8(0xf0, 0xf0, 0xf0);
9const DIM: Color = Color::rgb8(0x55, 0x55, 0x66);
10const ACCENT: Color = Color::rgb8(0x68, 0xab, 0xdf);
11const YELLOW: Color = Color::rgb8(0xe6, 0xa7, 0x00);
12const GREEN: Color = Color::rgb8(0x25, 0xc2, 0x81);
13const RED: Color = Color::rgb8(0xe1, 0x32, 0x38);
14
15trait HasOpacity {
16    fn opacity_signal(&self) -> Signal<f32>;
17}
18impl HasOpacity for TextNode {
19    fn opacity_signal(&self) -> Signal<f32> {
20        self.opacity.clone()
21    }
22}
23impl HasOpacity for Circle {
24    fn opacity_signal(&self) -> Signal<f32> {
25        self.opacity.clone()
26    }
27}
28impl HasOpacity for Rect {
29    fn opacity_signal(&self) -> Signal<f32> {
30        self.opacity.clone()
31    }
32}
33impl HasOpacity for Line {
34    fn opacity_signal(&self) -> Signal<f32> {
35        self.opacity.clone()
36    }
37}
38
39fn show(n: &impl HasOpacity, d: Duration) -> Box<dyn Animation> {
40    n.opacity_signal()
41        .to(1.0, d)
42        .ease(easings::cubic_out)
43        .into()
44}
45
46fn hide(n: &impl HasOpacity, d: Duration) -> Box<dyn Animation> {
47    n.opacity_signal().to(0.0, d).ease(easings::cubic_in).into()
48}
49
50// Helper for boxes to ensure they start completely hidden and slightly scaled down
51fn create_box(label: &str, center: Vec2, size: Vec2) -> (Rect, TextNode) {
52    let box_center = Vec2::new(center.x, center.y);
53
54    let text_pos = Vec2::new(center.x, center.y);
55
56    let r = Rect::default()
57        .with_position(box_center)
58        .with_size(size)
59        .with_scale(0.95)
60        .with_opacity(0.0)
61        .with_radius(8.0)
62        .with_stroke(ACCENT, 2.0)
63        .with_fill(Color::rgb8(0x26, 0x26, 0x2a));
64
65    let t = TextNode::default()
66        .with_position(text_pos)
67        .with_text(label)
68        .with_font_size(18.0)
69        .with_font("JetBrains Mono")
70        .with_fill(WHITE)
71        .with_scale(0.95)
72        .with_opacity(0.0);
73
74    (r, t)
75}
examples/math_animation.rs (line 17)
4fn main() {
5    // 1. Initialize Project
6    let mut project = Project::default()
7        .with_fps(60)
8        .with_dimensions(500, 500)
9        .with_title("Math Animation")
10        .close_on_finish();
11
12    // 2. Create MathNode (Typst syntax)
13    let tex = MathNode::default()
14        .with_position(Vec2::new(250.0, 250.0))
15        .with_equation("y = a x^2")
16        .with_font_size(48.0)
17        .with_fill(Color::rgb8(0xf2, 0xf2, 0xf2));
18    project.scene.add(Box::new(tex.clone()));
19
20    // 3. Define Animation Sequence
21    project.scene.video_timeline.add(loop_anim(
22        move || {
23            chain![
24                tex.tex("y = a x^2 + b x", Duration::from_secs(1)),
25                tex.tex("e^(i pi) + 1 = 0", Duration::from_secs(1)),
26                tex.tex("y = a x^2", Duration::from_secs(1)),
27            ]
28        },
29        None,
30    ));
31
32    // 4. Run interactive preview
33    project.show().expect("Failed to render");
34}
examples/getting_started.rs (line 16)
4fn main() {
5    // 1. Initialize the Project
6    let mut project = Project::default()
7        .with_fps(60)
8        .with_cache(true)
9        .with_title("Getting Started")
10        .close_on_finish();
11
12    // 2. Define Nodes
13    let circle = Circle::default()
14        .with_position(Vec2::new(400.0, 300.0))
15        .with_radius(50.0)
16        .with_fill(Color::rgb8(0xe1, 0x32, 0x38)); // Red
17
18    let text = TextNode::default()
19        .with_position(Vec2::new(400.0, 450.0))
20        .with_text("Hello Rust")
21        .with_font_size(40.0)
22        .with_fill(Color::rgb8(0xf2, 0xf2, 0xf2)); // White-ish
23
24    // 3. Add Nodes to the Scene
25    project.scene.add(Box::new(circle.clone()));
26    project.scene.add(Box::new(text.clone()));
27
28    // 4. Add Animations to the Timeline
29    project.scene.video_timeline.add(all![
30        circle.radius.to(100.0, Duration::from_secs(1)),
31        text.position
32            .to(Vec2::new(400.0, 500.0), Duration::from_secs(1)),
33    ]);
34
35    // 5. Show
36    project.show().expect("Failed to render");
37}
examples/export.rs (line 17)
4fn main() {
5    // 1. Initialize for Export
6    let mut project = Project::default()
7        .with_fps(30)
8        .with_ffmpeg(true)
9        .with_title("Export")
10        .with_output_path("output")
11        .close_on_finish();
12
13    // 2. Setup Nodes
14    let circle = Circle::default()
15        .with_position(Vec2::new(400.0, 300.0))
16        .with_radius(50.0)
17        .with_fill(Color::rgb8(0x68, 0xab, 0xdf)); // Blue
18
19    let text = TextNode::default()
20        .with_position(Vec2::new(400.0, 50.0))
21        .with_text("Export Demo")
22        .with_font_size(40.0)
23        .with_fill(Color::rgb8(0xf2, 0xf2, 0xf2)); // White
24
25    project.scene.add(Box::new(circle.clone()));
26    project.scene.add(Box::new(text.clone()));
27
28    // 3. Define Animations (Color and Font Size)
29    project.scene.video_timeline.add(all![
30        // Circle color and size
31        circle
32            .fill_color
33            .to(Color::rgb8(0xf2, 0xf2, 0xf2), Duration::from_secs(2))
34            .ease(easings::quad_in_out),
35        circle
36            .radius
37            .to(150.0, Duration::from_secs(2))
38            .ease(easings::elastic_out),
39        // Text font size
40        text.font_size
41            .to(50.0, Duration::from_secs(2))
42            .ease(easings::cubic_out),
43    ]);
44
45    // 4. Export (Renders frames and combines them into out.mkv)
46    println!("Starting export to {}...", project.output_path.display());
47    project.export().expect("Failed to export");
48}
examples/polygon.rs (line 9)
4fn main() {
5    let mut project = Project::default().with_title("Polygon").close_on_finish();
6
7    // Create a regular pentagon
8    let pentagon = Polygon::regular(5, 100.0)
9        .with_fill(Color::rgb8(0xe1, 0x32, 0x38)) // Red
10        .with_position(Vec2::new(200.0, 300.0))
11        .with_scale(0.0);
12
13    // Create a custom triangle
14    let triangle = Polygon::default()
15        .with_position(Vec2::new(500.0, 300.0))
16        .with_points(vec![
17            Vec2::new(0.0, -100.0),
18            Vec2::new(100.0, 100.0),
19            Vec2::new(-100.0, 100.0),
20        ])
21        .with_fill(Color::rgb8(0x68, 0xab, 0xdf)) // Blue
22        .with_stroke(Color::WHITE, 4.0);
23
24    project.scene.add(Box::new(pentagon.clone()));
25    project.scene.add(Box::new(triangle.clone()));
26
27    // Animate rotation and opacity
28    project.scene.video_timeline.add(all![
29        chain![
30            pentagon.scale.to(Vec2::ONE, Duration::from_secs(1)),
31            pentagon
32                .rotation
33                .to(std::f32::consts::PI, Duration::from_secs(2)),
34            pentagon.scale.to(-Vec2::ONE, Duration::from_secs(1)),
35        ],
36        chain![
37            triangle.opacity.to(1.0, Duration::from_secs(1)),
38            triangle
39                .position
40                .to(Vec2::new(500.0, 300.0), Duration::from_secs(1)),
41            triangle
42                .rotation
43                .to(360.0_f32.to_radians(), Duration::from_secs(1))
44        ],
45    ]);
46
47    project.show().expect("Failed to render");
48}
Source

pub const fn rgba8(r: u8, g: u8, b: u8, a: u8) -> Color

Creates a new RGBA color.

Examples found in repository?
examples/explainer.rs (line 90)
86fn hline(y: f32) -> Line {
87    Line::default()
88        .with_start(Vec2::new(LEFT, y))
89        .with_end(Vec2::new(LEFT, y))
90        .with_stroke(Color::rgba8(255, 255, 255, 25), 1.0)
91}
92// Shorthand for show/hide
93fn show(n: &impl HasOpacity, d: Duration) -> Box<dyn Animation> {
94    n.opacity_signal()
95        .to(1.0, d)
96        .ease(easings::cubic_out)
97        .into()
98}
99fn hide(n: &impl HasOpacity, d: Duration) -> Box<dyn Animation> {
100    n.opacity_signal().to(0.0, d).ease(easings::cubic_in).into()
101}
102
103// Trait to unify opacity access across different node types
104trait HasOpacity {
105    fn opacity_signal(&self) -> Signal<f32>;
106}
107impl HasOpacity for TextNode {
108    fn opacity_signal(&self) -> Signal<f32> {
109        self.opacity.clone()
110    }
111}
112impl HasOpacity for Circle {
113    fn opacity_signal(&self) -> Signal<f32> {
114        self.opacity.clone()
115    }
116}
117impl HasOpacity for Rect {
118    fn opacity_signal(&self) -> Signal<f32> {
119        self.opacity.clone()
120    }
121}
122impl HasOpacity for Line {
123    fn opacity_signal(&self) -> Signal<f32> {
124        self.opacity.clone()
125    }
126}
127impl HasOpacity for Polygon {
128    fn opacity_signal(&self) -> Signal<f32> {
129        self.opacity.clone()
130    }
131}
132impl HasOpacity for CodeNode {
133    fn opacity_signal(&self) -> Signal<f32> {
134        self.opacity.clone()
135    }
136}
137impl HasOpacity for GroupNode {
138    fn opacity_signal(&self) -> Signal<f32> {
139        self.opacity.clone()
140    }
141}
142impl HasOpacity for ImageNode {
143    fn opacity_signal(&self) -> Signal<f32> {
144        self.opacity.clone()
145    }
146}
147
148fn main() {
149    let mut project = Project::default()
150        .with_dimensions(CANVAS_W, CANVAS_H)
151        .with_fps(60)
152        .with_title("Explainer")
153        .with_background(BG)
154        .close_on_finish();
155
156    // =====================================================================
157    //  S1: TITLE CARD
158    // =====================================================================
159    let s1_line = hline(100.0);
160    let s1_title = TextNode::default()
161        .with_anchor(Vec2::new(-1.0, -1.0))
162        .with_position(Vec2::new(LEFT, 120.0))
163        .with_text("motion-canvas-rs")
164        .with_font_size(52.0)
165        .with_fill(ACCENT)
166        .with_font(FONT)
167        .with_opacity(0.0);
168    let s1_sub = h2("A GPU-Accelerated Vector Animation Engine", 185.0);
169    let s1_built = body(
170        "Built on Vello + Typst  —  Inspired by Motion Canvas",
171        220.0,
172    );
173    let s1_desc = body(
174        "This animation will teach you how the library works,",
175        280.0,
176    );
177    let s1_desc2 = body(
178        "from struct definitions to the GPU rendering pipeline.",
179        305.0,
180    );
181
182    let s1_logo = ImageNode::default()
183        .with_position(Vec2::new(950.0, 420.0))
184        .with_path("examples/images/motion-canvas-rs.svg")
185        .with_scale(0.3)
186        .with_opacity(0.0);
187
188    for n in [&s1_title, &s1_sub, &s1_built, &s1_desc, &s1_desc2] {
189        project.scene.add(Box::new(n.clone()));
190    }
191    project.scene.add(Box::new(s1_line.clone()));
192    project.scene.add(Box::new(s1_logo.clone()));
193
194    // =====================================================================
195    //  S2: THE 5 STEPS
196    // =====================================================================
197    let s2_h = title("Every program follows 5 steps", 50.0);
198    let steps = [
199        "1. Create a Project       — your canvas settings",
200        "2. Create Nodes           — shapes, text, images",
201        "3. Add Nodes to Scene     — what gets drawn",
202        "4. Animate the Timeline   — how things move",
203        "5. Show or Export         — live window or video",
204    ];
205    let s2_texts: Vec<TextNode> = steps
206        .iter()
207        .enumerate()
208        .map(|(i, s)| body(s, 120.0 + i as f32 * 35.0))
209        .collect();
210
211    project.scene.add(Box::new(s2_h.clone()));
212    for t in &s2_texts {
213        project.scene.add(Box::new(t.clone()));
214    }
215
216    // =====================================================================
217    //  S3: WHAT IS A STRUCT?  +  The Project struct
218    // =====================================================================
219    let s3_h = title("What is a 'struct'?", 50.0);
220    let s3_explain = h2(
221        "A struct is a container that groups related data together.",
222        95.0,
223    );
224    let s3_analogy = body(
225        "Think of it like a class in Python/JS, but it only holds data.",
226        130.0,
227    );
228
229    let s3_code = code_block(
230        "pub struct Project {
231    pub width: u32,          // Canvas width in pixels
232    pub height: u32,         // Canvas height in pixels
233    pub fps: u32,            // Frames per second
234    pub title: String,       // Window title
235    pub scene: BaseScene,    // Holds nodes + timelines
236    pub background_color: Color,
237    pub close_on_finish: bool,
238}",
239        175.0,
240    );
241
242    let s3_note = note(
243        "^ This is the actual Project struct from the library.",
244        420.0,
245    );
246    let s3_note2 = body(
247        "'pub' means public — anyone can read/write these fields.",
248        455.0,
249    );
250    let s3_note3 = body(
251        "u32 = unsigned 32-bit integer,  String = text,  bool = true/false",
252        485.0,
253    );
254
255    for n in [
256        &s3_h,
257        &s3_explain,
258        &s3_analogy,
259        &s3_note,
260        &s3_note2,
261        &s3_note3,
262    ] {
263        project.scene.add(Box::new(n.clone()));
264    }
265    project.scene.add(Box::new(s3_code.clone()));
266
267    // =====================================================================
268    //  S4: WHAT IS impl?  +  Builder pattern
269    // =====================================================================
270    let s4_h = title("What is 'impl'?", 50.0);
271    let s4_explain = h2("impl adds methods (functions) to a struct.", 95.0);
272    let s4_analogy = body(
273        "Like adding methods to a class. Separated from the data.",
274        130.0,
275    );
276
277    let s4_code = code_block(
278        "impl Project {
279    pub fn with_fps(mut self, fps: u32) -> Self {
280        self.fps = fps;   // set the value
281        self              // return yourself (builder pattern)
282    }
283    pub fn with_title(mut self, title: &str) -> Self {
284        self.title = title.to_string();
285        self
286    }
287}",
288        175.0,
289    );
290
291    let s4_usage = body("Usage — chain calls to configure:", 430.0);
292    let s4_usage_code = code_block(
293        "let project = Project::default()
294    .with_fps(60)
295    .with_title(\"My Animation\")
296    .with_dimensions(800, 600)
297    .close_on_finish();",
298        460.0,
299    );
300
301    let s4_note = note(
302        "Each .with_*() returns 'self', so you can chain them.",
303        590.0,
304    );
305
306    for n in [&s4_h, &s4_explain, &s4_analogy, &s4_usage, &s4_note] {
307        project.scene.add(Box::new(n.clone()));
308    }
309    project.scene.add(Box::new(s4_code.clone()));
310    project.scene.add(Box::new(s4_usage_code.clone()));
311
312    // =====================================================================
313    //  S5: WHAT IS A TRAIT?  +  The Node trait
314    // =====================================================================
315    let s5_h = title("What is a 'trait'?", 50.0);
316    let s5_explain = h2(
317        "A trait is a contract — like an interface in Java/TypeScript.",
318        95.0,
319    );
320    let s5_analogy = body(
321        "Any type that implements a trait promises to provide those methods.",
322        130.0,
323    );
324
325    let s5_code = code_block(
326        "pub trait Node: Send + Sync + 'static {
327    fn render(&self, scene: &mut Scene,
328              parent_transform: Affine,
329              parent_opacity: f32);
330    fn update(&mut self, dt: Duration);
331    fn state_hash(&self) -> u64;
332    fn clone_node(&self) -> Box<dyn Node>;
333}",
334        175.0,
335    );
336
337    let s5_r = note(
338        "render()     — draw yourself using current signal values",
339        410.0,
340    );
341    let s5_u = note(
342        "update(dt)   — called every frame (for per-frame logic)",
343        435.0,
344    );
345    let s5_s = note(
346        "state_hash() — returns a number that changes when you change",
347        460.0,
348    );
349    let s5_c = note("clone_node() — make a deep copy of yourself", 485.0);
350    let s5_every = body(
351        "Circle, Rect, Line, TextNode, Polygon all implement Node.",
352        530.0,
353    );
354
355    for n in [
356        &s5_h,
357        &s5_explain,
358        &s5_analogy,
359        &s5_r,
360        &s5_u,
361        &s5_s,
362        &s5_c,
363        &s5_every,
364    ] {
365        project.scene.add(Box::new(n.clone()));
366    }
367    project.scene.add(Box::new(s5_code.clone()));
368
369    // =====================================================================
370    //  S6: NODE GALLERY  (visual demo)
371    // =====================================================================
372    let s6_h = title("The Built-in Nodes", 50.0);
373    let s6_sub = body(
374        "Each node uses the builder pattern and stores properties as Signals.",
375        90.0,
376    );
377
378    let demo_c = Circle::default()
379        .with_position(Vec2::new(120.0, 230.0))
380        .with_radius(40.0)
381        .with_fill(RED)
382        .with_opacity(0.0);
383    let demo_r = Rect::default()
384        .with_position(Vec2::new(293.0, 230.0))
385        .with_size(Vec2::new(80.0, 80.0))
386        .with_fill(ACCENT)
387        .with_radius(8.0)
388        .with_opacity(0.0);
389    let demo_l = Line::default()
390        .with_start(Vec2::new(420.0, 200.0))
391        .with_end(Vec2::new(510.0, 270.0))
392        .with_stroke(WHITE, 3.0)
393        .with_opacity(0.0);
394    let demo_p = Polygon::regular(5, 40.0)
395        .with_position(Vec2::new(606.0, 230.0))
396        .with_fill(YELLOW)
397        .with_opacity(0.0);
398    let demo_t = TextNode::default()
399        .with_position(Vec2::new(765.0, 230.0))
400        .with_text("Abc")
401        .with_font_size(36.0)
402        .with_fill(GREEN)
403        .with_font(FONT)
404        .with_opacity(0.0);
405
406    let lc = dim("Circle", 95.0, 285.0);
407    let lr = dim("Rect", 280.0, 285.0);
408    let ll = dim("Line", 445.0, 285.0);
409    let lp = dim("Polygon", 580.0, 285.0);
410    let lt = dim("TextNode", 735.0, 285.0);
411
412    let s6_box_h = h2("Why Box<dyn Node>?", 340.0);
413    let s6_box1 = body("The scene stores different node types in one list:", 375.0);
414    let s6_box_code = code_block(
415        "pub struct BaseScene {
416    pub nodes: Vec<Box<dyn Node>>,  // a list of \"any Node\"
417}
418// 'Box' = heap-allocated,  'dyn Node' = any type implementing Node
419// Like List<INode> in Java or Array<Node> in TypeScript
420project.scene.add(Box::new(circle));  // wrap + add",
421        405.0,
422    );
423
424    for n in [&s6_h, &s6_sub, &lc, &lr, &ll, &lp, &lt, &s6_box_h, &s6_box1] {
425        project.scene.add(Box::new(n.clone()));
426    }
427    project.scene.add(Box::new(demo_c.clone()));
428    project.scene.add(Box::new(demo_r.clone()));
429    project.scene.add(Box::new(demo_l.clone()));
430    project.scene.add(Box::new(demo_p.clone()));
431    project.scene.add(Box::new(demo_t.clone()));
432    project.scene.add(Box::new(s6_box_code.clone()));
433
434    // =====================================================================
435    //  S7: SIGNALS — The Reactive Core
436    // =====================================================================
437    let s7_h = title("Signals — The Reactive Core", 50.0);
438    let s7_sub = h2("Every animatable property is a Signal<T>.", 95.0);
439
440    let s7_code = code_block(
441        "pub struct Signal<T> {
442    pub data: Arc<Mutex<SignalData<T>>>,
443}
444pub struct SignalData<T> {
445    pub value: T,  // the actual value (f32, Vec2, Color...)
446}",
447        140.0,
448    );
449
450    let s7_arc = note("Arc = shared pointer. Multiple owners, same data.", 310.0);
451    let s7_mutex = note(
452        "Mutex = lock. Only one thread reads/writes at a time.",
453        335.0,
454    );
455    let s7_why = body(
456        "Why? A node and its animation both need the same property:",
457        380.0,
458    );
459
460    let s7_diagram_code = code_block(
461        "let circle = Circle::default().with_radius(50.0);
462// circle.radius is a Signal<f32>
463
464circle.radius.to(100.0, Duration::from_secs(1));
465// Creates a SignalTween with a CLONE of circle.radius
466// Both point to the SAME underlying value (via Arc)
467
468// The animation WRITES new values each frame
469// The node READS them when rendering",
470        420.0,
471    );
472
473    // Live demo circle
474    let sig_demo = Circle::default()
475        .with_position(Vec2::new(1000.0, 400.0))
476        .with_radius(50.0)
477        .with_fill(RED)
478        .with_stroke(Color::rgba8(255, 255, 255, 50), 2.0)
479        .with_opacity(0.0);
480    let sig_lbl = dim("Live Signal demo", 900.0, 150.0);
481
482    for n in [&s7_h, &s7_sub, &s7_arc, &s7_mutex, &s7_why, &sig_lbl] {
483        project.scene.add(Box::new(n.clone()));
484    }
485    project.scene.add(Box::new(s7_code.clone()));
486    project.scene.add(Box::new(s7_diagram_code.clone()));
487    project.scene.add(Box::new(sig_demo.clone()));
488
489    // =====================================================================
490    //  S8: SIGNAL TWEEN — How animations work per-frame
491    // =====================================================================
492    let s8_h = title("SignalTween — The Animation Engine", 50.0);
493    let s8_sub = body(
494        ".to() creates a SignalTween that interpolates over time:",
495        90.0,
496    );
497
498    let s8_code = code_block(
499        "pub struct SignalTween<T> {
500    data: Arc<Mutex<SignalData<T>>>,  // shared ref to signal
501    start_value: Option<T>,           // captured on FIRST update (lazy!)
502    target_value: Option<T>,          // where we're going
503    duration: Duration,               // how long
504    elapsed: Duration,                // how much time passed
505    easing: fn(f32) -> f32,           // curve function
506}",
507        125.0,
508    );
509
510    let s8_how = h2("Each frame update:", 340.0);
511    let s8_steps = [
512        "1. elapsed += dt",
513        "2. t_linear = elapsed / duration          (0.0 to 1.0)",
514        "3. t_eased  = easing(t_linear)            (curved)",
515        "4. value    = lerp(start, target, t)      (interpolate)",
516        "5. Write value into Signal                (node sees it)",
517        "6. If elapsed >= duration: finished!      (return leftover dt)",
518    ];
519    let s8_step_texts: Vec<TextNode> = s8_steps
520        .iter()
521        .enumerate()
522        .map(|(i, s)| body(s, 370.0 + i as f32 * 28.0))
523        .collect();
524
525    let s8_lazy = note(
526        "start_value is captured lazily — so chained tweens read the",
527        570.0,
528    );
529    let s8_lazy2 = note(
530        "correct value at their actual start time, not creation time.",
531        590.0,
532    );
533
534    // Progress bar
535    let prog_bg = Rect::default()
536        .with_position(Vec2::new(895.0, 150.0))
537        .with_size(Vec2::new(400.0, 16.0))
538        .with_fill(Color::rgba8(255, 255, 255, 15))
539        .with_radius(8.0)
540        .with_opacity(0.0);
541    let prog_fill = Rect::default()
542        .with_position(Vec2::new(695.0, 154.0))
543        .with_anchor(Vec2::new(-1.0, 0.5))
544        .with_size(Vec2::new(0.0, 16.0))
545        .with_fill(ACCENT)
546        .with_radius(8.0)
547        .with_opacity(0.0);
548    let plbl0 = dim("t=0", 700.0, 172.0);
549    let plbl1 = dim("t=1", 1070.0, 172.0);
550    let tween_ball = Circle::default()
551        .with_position(Vec2::new(900.0, 430.0))
552        .with_radius(30.0)
553        .with_fill(RED)
554        .with_opacity(0.0);
555    let tween_lbl = dim("radius animating: 30 -> 80", 760.0, 220.0);
556
557    for n in [
558        &s8_h, &s8_sub, &s8_how, &s8_lazy, &s8_lazy2, &plbl0, &plbl1, &tween_lbl,
559    ] {
560        project.scene.add(Box::new(n.clone()));
561    }
562    project.scene.add(Box::new(s8_code.clone()));
563    for t in &s8_step_texts {
564        project.scene.add(Box::new(t.clone()));
565    }
566    project.scene.add(Box::new(prog_bg.clone()));
567    project.scene.add(Box::new(prog_fill.clone()));
568    project.scene.add(Box::new(tween_ball.clone()));
569
570    // =====================================================================
571    //  S9: TWEENABLE + EASINGS
572    // =====================================================================
573    let s9_h = title("Tweenable — What Can Be Animated", 50.0);
574    let s9_code = code_block(
575        "pub trait Tweenable: Clone + Send + Sync {
576    fn interpolate(a: &Self, b: &Self, t: f32) -> Self;
577    fn state_hash(&self) -> u64;
578}
579// Implemented for: f32, Vec2, Color, String, Affine, Vec<Vec2>
580//   f32:    lerp(a, b, t) = a + (b-a)*t
581//   Vec2:   lerp x and y independently
582//   Color:  lerp R,G,B,A channels independently
583//   String: snap — returns 'a' until t>=1, then 'b'",
584        95.0,
585    );
586
587    let s9_easing_h = h2("Easing functions curve the linear t:", 310.0);
588    let s9_easing_desc = body("Same distance, same duration — different feel.", 340.0);
589
590    let enames = [
591        "linear",
592        "cubic_in_out",
593        "elastic_out",
594        "bounce_out",
595        "back_out",
596    ];
597    let ecolors = [WHITE, ACCENT, RED, YELLOW, GREEN];
598    let mut eballs: Vec<Circle> = Vec::new();
599    let mut elabels: Vec<TextNode> = Vec::new();
600    for (i, name) in enames.iter().enumerate() {
601        let y = 390.0 + i as f32 * 55.0;
602        let b = Circle::default()
603            .with_position(Vec2::new(250.0, y))
604            .with_radius(12.0)
605            .with_fill(ecolors[i])
606            .with_opacity(0.0);
607        let l = dim(name, LEFT, y - 5.0);
608        project.scene.add(Box::new(b.clone()));
609        project.scene.add(Box::new(l.clone()));
610        eballs.push(b);
611        elabels.push(l);
612    }
613    project.scene.add(Box::new(s9_h.clone()));
614    project.scene.add(Box::new(s9_code.clone()));
615    project.scene.add(Box::new(s9_easing_h.clone()));
616    project.scene.add(Box::new(s9_easing_desc.clone()));
617
618    // =====================================================================
619    //  S10: FLOW CONTROLS
620    // =====================================================================
621    let s10_h = title("Flow Controls — Composing Animations", 50.0);
622    let s10_sub = body(
623        "Individual tweens are simple. Power comes from composing them.",
624        90.0,
625    );
626
627    // chain
628    let s10_chain_h = h2("chain![ ] — one after another", 140.0);
629    let chain_d: Vec<Circle> = (0..3)
630        .map(|i| {
631            Circle::default()
632                .with_position(Vec2::new(LEFT + 30.0 + i as f32 * 60.0, 200.0))
633                .with_radius(18.0)
634                .with_fill([RED, ACCENT, YELLOW][i])
635                .with_opacity(0.0)
636        })
637        .collect();
638
639    // all
640    let s10_all_h = h2("all![ ] — all at the same time", 270.0);
641    let all_d: Vec<Circle> = (0..3)
642        .map(|i| {
643            Circle::default()
644                .with_position(Vec2::new(LEFT + 30.0 + i as f32 * 60.0, 330.0))
645                .with_radius(18.0)
646                .with_fill([RED, ACCENT, YELLOW][i])
647                .with_opacity(0.0)
648        })
649        .collect();
650
651    // sequence
652    let s10_seq_h = h2("sequence![ ] — staggered starts", 400.0);
653    let seq_d: Vec<Circle> = (0..3)
654        .map(|i| {
655            Circle::default()
656                .with_position(Vec2::new(LEFT + 30.0 + i as f32 * 60.0, 460.0))
657                .with_radius(18.0)
658                .with_fill([RED, ACCENT, YELLOW][i])
659                .with_opacity(0.0)
660        })
661        .collect();
662
663    let s10_code = code_block(
664        "chain![ a, b, c ]           // a then b then c
665all![ a, b, c ]             // a + b + c together
666sequence![ 200ms, a, b, c ] // staggered
667delay![ 500ms, a ]          // wait then play
668wait(1s)                    // pause
669any![ a, b ]                // race: first wins
670loop_anim![ a, 3 ]          // repeat 3 times",
671        510.0,
672    );
673
674    project.scene.add(Box::new(s10_h.clone()));
675    project.scene.add(Box::new(s10_sub.clone()));
676    project.scene.add(Box::new(s10_chain_h.clone()));
677    project.scene.add(Box::new(s10_all_h.clone()));
678    project.scene.add(Box::new(s10_seq_h.clone()));
679    project.scene.add(Box::new(s10_code.clone()));
680    for d in &chain_d {
681        project.scene.add(Box::new(d.clone()));
682    }
683    for d in &all_d {
684        project.scene.add(Box::new(d.clone()));
685    }
686    for d in &seq_d {
687        project.scene.add(Box::new(d.clone()));
688    }
689
690    // =====================================================================
691    //  S11: TIMELINE + RENDERING
692    // =====================================================================
693    let s11_h = title("The Timeline — Animation Queue", 50.0);
694    let s11_code = code_block(
695        "pub struct Timeline {
696    pub animations: Vec<Box<dyn Animation>>,
697}
698impl Timeline {
699    fn update(&mut self, mut dt: Duration) {
700        while !self.animations.is_empty() {
701            let (finished, leftover) = self.animations[0].update(dt);
702            if finished {
703                self.animations.remove(0); // pop front
704                dt = leftover;             // pass leftover to next!
705            } else { break; }
706        }
707    }
708}",
709        95.0,
710    );
711
712    let s11_leftover = note(
713        "leftover propagation: if A finishes mid-frame, the remaining",
714        390.0,
715    );
716    let s11_leftover2 = note(
717        "dt is immediately given to B. No 'lost frames' at transitions.",
718        415.0,
719    );
720
721    let s11_render_h = h2("Rendering Pipeline (per frame):", 470.0);
722    let s11_steps = [
723        "1. Timeline.update(dt)  =>  SignalTween writes to Signals",
724        "2. Node.render()        =>  reads signals, draws shapes",
725        "3. Vello GPU            =>  compiles scene => wgpu => pixels",
726        "4. state_hash()         =>  seahash for hashing scene state, skip if unchanged",
727    ];
728    let s11_render_texts: Vec<TextNode> = s11_steps
729        .iter()
730        .enumerate()
731        .map(|(i, s)| body(s, 505.0 + i as f32 * 28.0))
732        .collect();
733
734    project.scene.add(Box::new(s11_h.clone()));
735    project.scene.add(Box::new(s11_code.clone()));
736    for n in [&s11_leftover, &s11_leftover2, &s11_render_h] {
737        project.scene.add(Box::new(n.clone()));
738    }
739    for t in &s11_render_texts {
740        project.scene.add(Box::new(t.clone()));
741    }
742
743    // =====================================================================
744    //  S12: EVENT LOOP — Why an infinite loop?
745    // =====================================================================
746    let s12_h = title("Why an Infinite Loop? — The Event Loop", 50.0);
747    let s12_sub = body(
748        "GPU rendering requires a persistent event loop (winit + wgpu).",
749        90.0,
750    );
751    let s12_code = code_block(
752        "event_loop.run(|event, elwt| {
753    match event {
754        Resumed => {           // GPU surface ready
755            renderer.resume(&window);
756        }
757        AboutToWait => {       // run every frame
758            scene.update(dt);  // advance animations
759            let hash = scene.state_hash();
760            if hash != last_hash {    // dirty?
761                window.request_redraw();
762            }
763        }
764        RedrawRequested => {   // GPU draw call
765            renderer.render(&scene, w, h);
766        }
767    }
768});",
769        130.0,
770    );
771    let s12_why = note(
772        "The window stays open because the GPU surface is tied to",
773        490.0,
774    );
775    let s12_why2 = note(
776        "the OS event loop. Without it, the surface is immediately dropped.",
777        510.0,
778    );
779    let s12_hash = body(
780        "state_hash() skips re-rendering unchanged frames (dirty-checking).",
781        550.0,
782    );
783
784    for n in [&s12_h, &s12_sub, &s12_why, &s12_why2, &s12_hash] {
785        project.scene.add(Box::new(n.clone()));
786    }
787    project.scene.add(Box::new(s12_code.clone()));
788
789    // =====================================================================
790    //  S13: HEADLESS EXPORT — GPU without a window
791    // =====================================================================
792    let s13_h = title("Headless Export: GPU -> PNG -> FFmpeg", 50.0);
793    let s13_sub = body(
794        "Same GPU rendering, but without a window — output to files.",
795        90.0,
796    );
797    let s13_code = code_block(
798        "pub struct Exporter {
799    texture: wgpu::Texture,       // GPU-side image
800    output_buffer: wgpu::Buffer,  // CPU-readable copy
801    renderer: Renderer,           // Vello
802}
803fn export_frame(&mut self, scene) -> Vec<u8> {
804    scene.render(&mut self.scene);           // 1. build shapes
805    renderer.render_to_texture(..);          // 2. GPU draws
806    encoder.copy_texture_to_buffer(..);      // 3. GPU -> CPU
807    output_buffer.map_async(Read, ..);       // 4. read pixels
808    return pixels;                           // 5. raw RGBA
809}",
810        130.0,
811    );
812    let s13_cache = note(
813        "Cache: state_hash per frame. If unchanged, skip GPU entirely.",
814        420.0,
815    );
816    let s13_ffmpeg = note(
817        "FFmpeg: raw pixels piped to stdin -> libx264 -> .mkv video.",
818        445.0,
819    );
820    let s13_parallel = body(
821        "PNG saving runs on a background thread. Export is pipelined.",
822        485.0,
823    );
824
825    for n in [&s13_h, &s13_sub, &s13_cache, &s13_ffmpeg, &s13_parallel] {
826        project.scene.add(Box::new(n.clone()));
827    }
828    project.scene.add(Box::new(s13_code.clone()));
829
830    // =====================================================================
831    //  S14: ENGINE UTILITIES
832    // =====================================================================
833    let s14_h = title("Under the Hood: Utility Modules", 50.0);
834    let s14_sub = body(
835        "Helper systems that power the engine behind the scenes.",
836        90.0,
837    );
838    let s14_code = code_block(
839        "// src/engine/util/
840font_manager.rs    // Lazy-loads system fonts via Typst
841                   // Global HashMap cache with lazy_static
842
843image_manager.rs   // Loads PNG + SVG (via resvg)
844                   // Caches decoded images as Arc<Image>
845
846code_tokenizer.rs  // Syntax highlighting via Syntect
847                   // Parses code -> colored spans for CodeNode
848
849hash.rs            // SeaHash: fast, deterministic fingerprints
850                   // Position-aware combination
851                   // Powers Rayon parallel state hashing
852
853export.rs          // FFmpeg pipe: rawvideo -> libx264
854                   // Audio merging with filter_complex
855                   // Title sanitization for filenames",
856        130.0,
857    );
858    let s14_lazy = note(
859        "lazy_static + Mutex = global singleton, created once, cached forever.",
860        495.0,
861    );
862    let s14_arc = body(
863        "Arc<Image> lets multiple nodes share one decoded image without copies.",
864        530.0,
865    );
866    let s14_hash = note(
867        "Rayon + SeaHash = Deterministic fingerprints across runs & threads.",
868        565.0,
869    );
870
871    for n in [&s14_h, &s14_sub, &s14_lazy, &s14_arc, &s14_hash] {
872        project.scene.add(Box::new(n.clone()));
873    }
874    project.scene.add(Box::new(s14_code.clone()));
875
876    // =====================================================================
877    //  S15: FINALE
878    // =====================================================================
879    let fin = TextNode::default()
880        .with_anchor(Vec2::new(-1.0, -1.0))
881        .with_position(Vec2::new(LEFT, 200.0))
882        .with_text("That's how it works!")
883        .with_font_size(48.0)
884        .with_fill(ACCENT)
885        .with_font(FONT)
886        .with_opacity(0.0);
887    let fin_steps = [
888        "1.  struct          — data container",
889        "2.  impl            — methods / builder pattern",
890        "3.  trait Node      — interface contract",
891        "4.  Box<dyn Node>   — type-erased heap allocation",
892        "5.  Signal<T>       — Arc<Mutex> shared reactive state",
893        "6.  SignalTween     — per-frame lerp interpolation",
894        "7.  Timeline        — sequential queue + leftover dt",
895        "8.  Event Loop      — winit + wgpu infinite loop",
896        "9.  Exporter        — headless GPU -> PNG/FFmpeg",
897        "10. Utilities       — font/image cache, syntax highlight",
898    ];
899    let fin_texts: Vec<TextNode> = fin_steps
900        .iter()
901        .enumerate()
902        .map(|(i, s)| body(s, 270.0 + i as f32 * 28.0))
903        .collect();
904    let fin_hint = dim("cargo run --example getting_started", LEFT, 570.0);
905
906    project.scene.add(Box::new(fin.clone()));
907    for t in &fin_texts {
908        project.scene.add(Box::new(t.clone()));
909    }
910    project.scene.add(Box::new(fin_hint.clone()));
911
912    // =====================================================================
913    //  ANIMATION TIMELINE
914    // =====================================================================
915    // Helper: hide_all takes a vec of opacity signals and fades them out
916    let hide_dur = ms(200);
917
918    project.scene.video_timeline.add(chain![
919        // ── S1: TITLE ──
920        s1_line
921            .end
922            .to(Vec2::new(500.0, 100.0), ms(500))
923            .ease(easings::cubic_out),
924        sequence![
925            ms(120),
926            show(&s1_title, ms(500)),
927            show(&s1_sub, ms(500)),
928            show(&s1_built, ms(500)),
929            show(&s1_logo, ms(600)),
930            show(&s1_desc, ms(500)),
931            show(&s1_desc2, ms(500)),
932        ],
933        wait(secs(5)),
934        all![
935            hide(&s1_title, hide_dur),
936            hide(&s1_sub, hide_dur),
937            hide(&s1_built, hide_dur),
938            hide(&s1_desc, hide_dur),
939            hide(&s1_desc2, hide_dur),
940            hide(&s1_logo, hide_dur),
941            s1_line.end.to(Vec2::new(LEFT, 100.0), hide_dur)
942        ],
943        wait(ms(150)),
944        // ── S2: FIVE STEPS ──
945        show(&s2_h, ms(500)),
946        wait(ms(400)),
947        sequence![
948            ms(250),
949            show(&s2_texts[0], ms(400)),
950            show(&s2_texts[1], ms(400)),
951            show(&s2_texts[2], ms(400)),
952            show(&s2_texts[3], ms(400)),
953            show(&s2_texts[4], ms(400)),
954        ],
955        wait(secs(8)),
956        all![
957            hide(&s2_h, hide_dur),
958            hide(&s2_texts[0], hide_dur),
959            hide(&s2_texts[1], hide_dur),
960            hide(&s2_texts[2], hide_dur),
961            hide(&s2_texts[3], hide_dur),
962            hide(&s2_texts[4], hide_dur)
963        ],
964        wait(ms(150)),
965        // ── S3: STRUCT ──
966        sequence![
967            ms(120),
968            show(&s3_h, ms(500)),
969            show(&s3_explain, ms(400)),
970            show(&s3_analogy, ms(400))
971        ],
972        wait(ms(500)),
973        show(&s3_code, ms(500)),
974        wait(secs(6)),
975        sequence![
976            ms(300),
977            show(&s3_note, ms(400)),
978            show(&s3_note2, ms(400)),
979            show(&s3_note3, ms(400))
980        ],
981        wait(secs(6)),
982        all![
983            hide(&s3_h, hide_dur),
984            hide(&s3_explain, hide_dur),
985            hide(&s3_analogy, hide_dur),
986            hide(&s3_code, hide_dur),
987            hide(&s3_note, hide_dur),
988            hide(&s3_note2, hide_dur),
989            hide(&s3_note3, hide_dur)
990        ],
991        wait(ms(150)),
992        // ── S4: IMPL / BUILDER ──
993        sequence![
994            ms(120),
995            show(&s4_h, ms(500)),
996            show(&s4_explain, ms(400)),
997            show(&s4_analogy, ms(400))
998        ],
999        wait(ms(500)),
1000        show(&s4_code, ms(500)),
1001        wait(secs(7)),
1002        show(&s4_usage, ms(400)),
1003        show(&s4_usage_code, ms(500)),
1004        wait(secs(2)),
1005        show(&s4_note, ms(400)),
1006        wait(secs(5)),
1007        all![
1008            hide(&s4_h, hide_dur),
1009            hide(&s4_explain, hide_dur),
1010            hide(&s4_analogy, hide_dur),
1011            hide(&s4_code, hide_dur),
1012            hide(&s4_usage, hide_dur),
1013            hide(&s4_usage_code, hide_dur),
1014            hide(&s4_note, hide_dur)
1015        ],
1016        wait(ms(150)),
1017        // ── S5: TRAIT / NODE ──
1018        sequence![
1019            ms(120),
1020            show(&s5_h, ms(500)),
1021            show(&s5_explain, ms(400)),
1022            show(&s5_analogy, ms(400))
1023        ],
1024        wait(ms(500)),
1025        show(&s5_code, ms(500)),
1026        wait(secs(6)),
1027        sequence![
1028            ms(300),
1029            show(&s5_r, ms(400)),
1030            show(&s5_u, ms(400)),
1031            show(&s5_s, ms(400)),
1032            show(&s5_c, ms(400))
1033        ],
1034        wait(secs(2)),
1035        show(&s5_every, ms(400)),
1036        wait(secs(4)),
1037        all![
1038            hide(&s5_h, hide_dur),
1039            hide(&s5_explain, hide_dur),
1040            hide(&s5_analogy, hide_dur),
1041            hide(&s5_code, hide_dur),
1042            hide(&s5_r, hide_dur),
1043            hide(&s5_u, hide_dur),
1044            hide(&s5_s, hide_dur),
1045            hide(&s5_c, hide_dur),
1046            hide(&s5_every, hide_dur)
1047        ],
1048        wait(ms(150)),
1049        // ── S6: NODE GALLERY ──
1050        sequence![ms(120), show(&s6_h, ms(500)), show(&s6_sub, ms(400))],
1051        wait(ms(400)),
1052        sequence![
1053            ms(200),
1054            all![show(&demo_c, ms(400)), show(&lc, ms(400))],
1055            all![show(&demo_r, ms(400)), show(&lr, ms(400))],
1056            all![show(&demo_l, ms(400)), show(&ll, ms(400))],
1057            all![show(&demo_p, ms(400)), show(&lp, ms(400))],
1058            all![show(&demo_t, ms(400)), show(&lt, ms(400))],
1059        ],
1060        wait(secs(2)),
1061        sequence![
1062            ms(200),
1063            show(&s6_box_h, ms(400)),
1064            show(&s6_box1, ms(400)),
1065            show(&s6_box_code, ms(500))
1066        ],
1067        wait(secs(7)),
1068        all![
1069            hide(&s6_h, hide_dur),
1070            hide(&s6_sub, hide_dur),
1071            hide(&demo_c, hide_dur),
1072            hide(&demo_r, hide_dur),
1073            hide(&demo_l, hide_dur),
1074            hide(&demo_p, hide_dur),
1075            hide(&demo_t, hide_dur),
1076            hide(&lc, hide_dur),
1077            hide(&lr, hide_dur),
1078            hide(&ll, hide_dur),
1079            hide(&lp, hide_dur),
1080            hide(&lt, hide_dur),
1081            hide(&s6_box_h, hide_dur),
1082            hide(&s6_box1, hide_dur),
1083            hide(&s6_box_code, hide_dur)
1084        ],
1085        wait(ms(150)),
1086        // ── S7: SIGNALS ──
1087        sequence![ms(120), show(&s7_h, ms(500)), show(&s7_sub, ms(400))],
1088        wait(ms(400)),
1089        show(&s7_code, ms(500)),
1090        wait(secs(5)),
1091        sequence![ms(300), show(&s7_arc, ms(400)), show(&s7_mutex, ms(400))],
1092        wait(secs(4)),
1093        show(&s7_why, ms(400)),
1094        show(&s7_diagram_code, ms(500)),
1095        wait(secs(6)),
1096        // Live demo
1097        all![show(&sig_demo, ms(300)), show(&sig_lbl, ms(300))],
1098        chain![
1099            sig_demo.radius.to(80.0, ms(700)).ease(easings::elastic_out),
1100            sig_demo.fill_color.to(TEAL, ms(500)),
1101            sig_demo
1102                .position
1103                .to(Vec2::new(950.0, 350.0), ms(500))
1104                .ease(easings::cubic_out),
1105            wait(ms(300)),
1106            all![
1107                sig_demo.radius.to(50.0, ms(400)),
1108                sig_demo.fill_color.to(RED, ms(400)),
1109                sig_demo.position.to(Vec2::new(900.0, 300.0), ms(400))
1110            ],
1111        ],
1112        wait(secs(3)),
1113        all![
1114            hide(&s7_h, hide_dur),
1115            hide(&s7_sub, hide_dur),
1116            hide(&s7_code, hide_dur),
1117            hide(&s7_arc, hide_dur),
1118            hide(&s7_mutex, hide_dur),
1119            hide(&s7_why, hide_dur),
1120            hide(&s7_diagram_code, hide_dur),
1121            hide(&sig_demo, hide_dur),
1122            hide(&sig_lbl, hide_dur)
1123        ],
1124        wait(ms(150)),
1125        // ── S8: SIGNAL TWEEN ──
1126        sequence![ms(120), show(&s8_h, ms(500)), show(&s8_sub, ms(400))],
1127        wait(ms(400)),
1128        show(&s8_code, ms(500)),
1129        wait(secs(6)),
1130        show(&s8_how, ms(300)),
1131        sequence![
1132            ms(100),
1133            show(&s8_step_texts[0], ms(250)),
1134            show(&s8_step_texts[1], ms(250)),
1135            show(&s8_step_texts[2], ms(250)),
1136            show(&s8_step_texts[3], ms(250)),
1137            show(&s8_step_texts[4], ms(250)),
1138            show(&s8_step_texts[5], ms(250)),
1139        ],
1140        wait(ms(500)),
1141        sequence![ms(100), show(&s8_lazy, ms(300)), show(&s8_lazy2, ms(300))],
1142        wait(ms(500)),
1143        // Progress bar demo
1144        all![
1145            show(&prog_bg, ms(200)),
1146            show(&prog_fill, ms(200)),
1147            show(&plbl0, ms(200)),
1148            show(&plbl1, ms(200)),
1149            show(&tween_ball, ms(200)),
1150            show(&tween_lbl, ms(200))
1151        ],
1152        all![
1153            prog_fill
1154                .size
1155                .to(Vec2::new(400.0, 16.0), secs(2))
1156                .ease(easings::cubic_in_out),
1157            tween_ball
1158                .radius
1159                .to(80.0, secs(2))
1160                .ease(easings::cubic_in_out),
1161        ],
1162        wait(secs(3)),
1163        all![
1164            hide(&s8_h, hide_dur),
1165            hide(&s8_sub, hide_dur),
1166            hide(&s8_code, hide_dur),
1167            hide(&s8_how, hide_dur),
1168            hide(&s8_lazy, hide_dur),
1169            hide(&s8_lazy2, hide_dur),
1170            hide(&prog_bg, hide_dur),
1171            hide(&prog_fill, hide_dur),
1172            hide(&plbl0, hide_dur),
1173            hide(&plbl1, hide_dur),
1174            hide(&tween_ball, hide_dur),
1175            hide(&tween_lbl, hide_dur),
1176            hide(&s8_step_texts[0], hide_dur),
1177            hide(&s8_step_texts[1], hide_dur),
1178            hide(&s8_step_texts[2], hide_dur),
1179            hide(&s8_step_texts[3], hide_dur),
1180            hide(&s8_step_texts[4], hide_dur),
1181            hide(&s8_step_texts[5], hide_dur)
1182        ],
1183        wait(ms(150)),
1184        // ── S9: TWEENABLE + EASINGS ──
1185        show(&s9_h, ms(500)),
1186        show(&s9_code, ms(500)),
1187        wait(secs(4)),
1188        sequence![
1189            ms(60),
1190            show(&s9_easing_h, ms(300)),
1191            show(&s9_easing_desc, ms(300))
1192        ],
1193        sequence![
1194            ms(50),
1195            all![show(&eballs[0], ms(200)), show(&elabels[0], ms(200))],
1196            all![show(&eballs[1], ms(200)), show(&elabels[1], ms(200))],
1197            all![show(&eballs[2], ms(200)), show(&elabels[2], ms(200))],
1198            all![show(&eballs[3], ms(200)), show(&elabels[3], ms(200))],
1199            all![show(&eballs[4], ms(200)), show(&elabels[4], ms(200))],
1200        ],
1201        wait(ms(300)),
1202        // Race!
1203        all![
1204            eballs[0]
1205                .position
1206                .to(Vec2::new(1050.0, 390.0), secs(2))
1207                .ease(easings::linear),
1208            eballs[1]
1209                .position
1210                .to(Vec2::new(1050.0, 445.0), secs(2))
1211                .ease(easings::cubic_in_out),
1212            eballs[2]
1213                .position
1214                .to(Vec2::new(1050.0, 500.0), secs(2))
1215                .ease(easings::elastic_out),
1216            eballs[3]
1217                .position
1218                .to(Vec2::new(1050.0, 555.0), secs(2))
1219                .ease(easings::bounce_out),
1220            eballs[4]
1221                .position
1222                .to(Vec2::new(1050.0, 610.0), secs(2))
1223                .ease(easings::back_out),
1224        ],
1225        wait(ms(500)),
1226        all![
1227            eballs[0]
1228                .position
1229                .to(Vec2::new(250.0, 390.0), secs(2))
1230                .ease(easings::linear),
1231            eballs[1]
1232                .position
1233                .to(Vec2::new(250.0, 445.0), secs(2))
1234                .ease(easings::cubic_in_out),
1235            eballs[2]
1236                .position
1237                .to(Vec2::new(250.0, 500.0), secs(2))
1238                .ease(easings::elastic_out),
1239            eballs[3]
1240                .position
1241                .to(Vec2::new(250.0, 555.0), secs(2))
1242                .ease(easings::bounce_out),
1243            eballs[4]
1244                .position
1245                .to(Vec2::new(250.0, 610.0), secs(2))
1246                .ease(easings::back_out),
1247        ],
1248        wait(ms(500)),
1249        all![
1250            hide(&s9_h, hide_dur),
1251            hide(&s9_code, hide_dur),
1252            hide(&s9_easing_h, hide_dur),
1253            hide(&s9_easing_desc, hide_dur),
1254            hide(&eballs[0], hide_dur),
1255            hide(&eballs[1], hide_dur),
1256            hide(&eballs[2], hide_dur),
1257            hide(&eballs[3], hide_dur),
1258            hide(&eballs[4], hide_dur),
1259            hide(&elabels[0], hide_dur),
1260            hide(&elabels[1], hide_dur),
1261            hide(&elabels[2], hide_dur),
1262            hide(&elabels[3], hide_dur),
1263            hide(&elabels[4], hide_dur)
1264        ],
1265        wait(ms(150)),
1266        // ── S10: FLOW CONTROLS ──
1267        sequence![ms(120), show(&s10_h, ms(500)), show(&s10_sub, ms(400))],
1268        wait(ms(400)),
1269        // chain demo
1270        show(&s10_chain_h, ms(400)),
1271        all![
1272            show(&chain_d[0], ms(300)),
1273            show(&chain_d[1], ms(300)),
1274            show(&chain_d[2], ms(300))
1275        ],
1276        wait(ms(300)),
1277        chain![
1278            chain_d[0]
1279                .position
1280                .to(Vec2::new(700.0, 200.0), ms(500))
1281                .ease(easings::cubic_out),
1282            chain_d[1]
1283                .position
1284                .to(Vec2::new(800.0, 200.0), ms(500))
1285                .ease(easings::cubic_out),
1286            chain_d[2]
1287                .position
1288                .to(Vec2::new(900.0, 200.0), ms(500))
1289                .ease(easings::cubic_out),
1290        ],
1291        wait(secs(1)),
1292        // all demo
1293        show(&s10_all_h, ms(400)),
1294        all![
1295            show(&all_d[0], ms(300)),
1296            show(&all_d[1], ms(300)),
1297            show(&all_d[2], ms(300))
1298        ],
1299        wait(ms(300)),
1300        all![
1301            all_d[0]
1302                .position
1303                .to(Vec2::new(700.0, 330.0), ms(500))
1304                .ease(easings::cubic_out),
1305            all_d[1]
1306                .position
1307                .to(Vec2::new(800.0, 330.0), ms(500))
1308                .ease(easings::cubic_out),
1309            all_d[2]
1310                .position
1311                .to(Vec2::new(900.0, 330.0), ms(500))
1312                .ease(easings::cubic_out),
1313        ],
1314        wait(secs(1)),
1315        // sequence demo
1316        show(&s10_seq_h, ms(400)),
1317        all![
1318            show(&seq_d[0], ms(300)),
1319            show(&seq_d[1], ms(300)),
1320            show(&seq_d[2], ms(300))
1321        ],
1322        wait(ms(300)),
1323        sequence![
1324            ms(250),
1325            seq_d[0]
1326                .position
1327                .to(Vec2::new(700.0, 460.0), ms(500))
1328                .ease(easings::cubic_out),
1329            seq_d[1]
1330                .position
1331                .to(Vec2::new(800.0, 460.0), ms(500))
1332                .ease(easings::cubic_out),
1333            seq_d[2]
1334                .position
1335                .to(Vec2::new(900.0, 460.0), ms(500))
1336                .ease(easings::cubic_out),
1337        ],
1338        wait(secs(1)),
1339        show(&s10_code, ms(500)),
1340        wait(secs(8)),
1341        all![
1342            hide(&s10_h, hide_dur),
1343            hide(&s10_sub, hide_dur),
1344            hide(&s10_chain_h, hide_dur),
1345            hide(&s10_all_h, hide_dur),
1346            hide(&s10_seq_h, hide_dur),
1347            hide(&s10_code, hide_dur),
1348            hide(&chain_d[0], hide_dur),
1349            hide(&chain_d[1], hide_dur),
1350            hide(&chain_d[2], hide_dur),
1351            hide(&all_d[0], hide_dur),
1352            hide(&all_d[1], hide_dur),
1353            hide(&all_d[2], hide_dur),
1354            hide(&seq_d[0], hide_dur),
1355            hide(&seq_d[1], hide_dur),
1356            hide(&seq_d[2], hide_dur)
1357        ],
1358        wait(ms(150)),
1359        // ── S11: TIMELINE + RENDERING ──
1360        show(&s11_h, ms(500)),
1361        wait(ms(400)),
1362        show(&s11_code, ms(500)),
1363        wait(secs(7)),
1364        sequence![
1365            ms(200),
1366            show(&s11_leftover, ms(400)),
1367            show(&s11_leftover2, ms(400))
1368        ],
1369        wait(secs(4)),
1370        show(&s11_render_h, ms(400)),
1371        sequence![
1372            ms(200),
1373            show(&s11_render_texts[0], ms(350)),
1374            show(&s11_render_texts[1], ms(350)),
1375            show(&s11_render_texts[2], ms(350)),
1376            show(&s11_render_texts[3], ms(350)),
1377        ],
1378        wait(secs(7)),
1379        all![
1380            hide(&s11_h, hide_dur),
1381            hide(&s11_code, hide_dur),
1382            hide(&s11_leftover, hide_dur),
1383            hide(&s11_leftover2, hide_dur),
1384            hide(&s11_render_h, hide_dur),
1385            hide(&s11_render_texts[0], hide_dur),
1386            hide(&s11_render_texts[1], hide_dur),
1387            hide(&s11_render_texts[2], hide_dur),
1388            hide(&s11_render_texts[3], hide_dur)
1389        ],
1390        wait(ms(300)),
1391        // ── S12: EVENT LOOP ──
1392        sequence![ms(120), show(&s12_h, ms(500)), show(&s12_sub, ms(400))],
1393        wait(ms(500)),
1394        show(&s12_code, ms(500)),
1395        wait(secs(8)),
1396        sequence![
1397            ms(200),
1398            show(&s12_why, ms(400)),
1399            show(&s12_why2, ms(400)),
1400            show(&s12_hash, ms(400))
1401        ],
1402        wait(secs(5)),
1403        all![
1404            hide(&s12_h, hide_dur),
1405            hide(&s12_sub, hide_dur),
1406            hide(&s12_code, hide_dur),
1407            hide(&s12_why, hide_dur),
1408            hide(&s12_why2, hide_dur),
1409            hide(&s12_hash, hide_dur)
1410        ],
1411        wait(ms(150)),
1412        // ── S13: HEADLESS EXPORT ──
1413        sequence![ms(120), show(&s13_h, ms(500)), show(&s13_sub, ms(400))],
1414        wait(ms(500)),
1415        show(&s13_code, ms(500)),
1416        wait(secs(8)),
1417        sequence![
1418            ms(200),
1419            show(&s13_cache, ms(400)),
1420            show(&s13_ffmpeg, ms(400)),
1421            show(&s13_parallel, ms(400))
1422        ],
1423        wait(secs(5)),
1424        all![
1425            hide(&s13_h, hide_dur),
1426            hide(&s13_sub, hide_dur),
1427            hide(&s13_code, hide_dur),
1428            hide(&s13_cache, hide_dur),
1429            hide(&s13_ffmpeg, hide_dur),
1430            hide(&s13_parallel, hide_dur)
1431        ],
1432        wait(ms(150)),
1433        // ── S14: UTILITIES ──
1434        sequence![ms(120), show(&s14_h, ms(500)), show(&s14_sub, ms(400))],
1435        wait(ms(500)),
1436        show(&s14_code, ms(500)),
1437        wait(secs(8)),
1438        sequence![ms(200), show(&s14_lazy, ms(400)), show(&s14_arc, ms(400))],
1439        wait(secs(5)),
1440        all![
1441            hide(&s14_h, hide_dur),
1442            hide(&s14_sub, hide_dur),
1443            hide(&s14_code, hide_dur),
1444            hide(&s14_lazy, hide_dur),
1445            hide(&s14_arc, hide_dur)
1446        ],
1447        wait(ms(300)),
1448        // ── S15: FINALE ──
1449        show(&fin, ms(700)),
1450        wait(ms(500)),
1451        sequence![
1452            ms(150),
1453            show(&fin_texts[0], ms(350)),
1454            show(&fin_texts[1], ms(350)),
1455            show(&fin_texts[2], ms(350)),
1456            show(&fin_texts[3], ms(350)),
1457            show(&fin_texts[4], ms(350)),
1458            show(&fin_texts[5], ms(350)),
1459            show(&fin_texts[6], ms(350)),
1460            show(&fin_texts[7], ms(350)),
1461            show(&fin_texts[8], ms(350)),
1462            show(&fin_texts[9], ms(350)),
1463        ],
1464        wait(secs(2)),
1465        show(&fin_hint, ms(400)),
1466        wait(secs(6)),
1467    ]);
1468
1469    #[cfg(feature = "audio")]
1470    project
1471        .scene
1472        .audio_timeline
1473        .add(play!(AudioNode::new("background.mp3").with_volume(0.3)));
1474
1475    project.show().expect("Failed to render");
1476}
More examples
Hide additional examples
examples/group_animation.rs (line 13)
4fn main() {
5    let mut project = Project::default()
6        .with_title("Group Animation")
7        .close_on_finish();
8
9    // Create some child nodes
10    let rect = Rect::default()
11        .with_position(Vec2::new(0.0, 0.0))
12        .with_size(Vec2::new(100.0, 100.0))
13        .with_fill(Color::rgba8(100, 100, 255, 255))
14        .with_radius(10.0);
15
16    let circle1 = Circle::default()
17        .with_position(Vec2::new(-40.0, -40.0))
18        .with_radius(20.0)
19        .with_fill(Color::rgba8(255, 100, 100, 255));
20
21    let circle2 = Circle::default()
22        .with_position(Vec2::new(40.0, 40.0))
23        .with_radius(20.0)
24        .with_fill(Color::rgba8(100, 255, 100, 255));
25
26    // Create a GroupNode holding them
27    let group = GroupNode::default()
28        .with_nodes(vec![
29            Box::new(rect.clone()),
30            Box::new(circle1.clone()),
31            Box::new(circle2.clone()),
32        ])
33        .with_position(Vec2::new(400.0, 300.0));
34
35    // We must add the group to the scene's nodes to render it
36    project.scene.add(Box::new(group.clone()));
37
38    // Define animations and add them to the timeline
39    project.scene.video_timeline.add(chain![
40        // 1. Move the whole group
41        group
42            .position
43            .to(Vec2::new(200.0, 150.0), Duration::from_secs(2)),
44        // 2. Rotate the group
45        group
46            .rotation
47            .to(std::f32::consts::PI, Duration::from_secs(2)),
48        // 3. Complex transform (move + scale)
49        all![
50            group
51                .position
52                .to(Vec2::new(400.0, 450.0), Duration::from_secs(2)),
53            group.scale.to(Vec2::splat(2.0), Duration::from_secs(2)),
54            group.opacity.to(0.3, Duration::from_secs(2)),
55        ],
56        // 4. Reset (at the center)
57        all![
58            group
59                .position
60                .to(Vec2::new(400.0, 300.0), Duration::from_secs(1)),
61            group.scale.to(Vec2::ONE, Duration::from_secs(1)),
62            group.rotation.to(0.0, Duration::from_secs(1)),
63            group.opacity.to(1.0, Duration::from_secs(1)),
64        ],
65    ]);
66
67    project.show().expect("Failed to render");
68}
examples/signals.rs (line 19)
4fn main() {
5    let mut project = Project::default()
6        .with_title("Signals")
7        .with_dimensions(800, 600)
8        .close_on_finish();
9
10    // 1. Create independent signals for our "Coordinate System"
11    // These are NOT tied to any node yet.
12    let x_var = Signal::new(0.0f32);
13    let y_var = Signal::new(0.0f32);
14
15    // 2. Create the Axis lines (Fixed)
16    let x_axis = Line::default()
17        .with_start(Vec2::new(-200.0, 0.0))
18        .with_end(Vec2::new(200.0, 0.0))
19        .with_stroke(Color::rgba8(255, 255, 255, 100), 2.0);
20
21    let y_axis = Line::default()
22        .with_start(Vec2::new(0.0, -200.0))
23        .with_end(Vec2::new(0.0, 200.0))
24        .with_stroke(Color::rgba8(255, 255, 255, 100), 2.0);
25
26    // Group the axes at the center
27    let axes = GroupNode::default()
28        .with_nodes(vec![Box::new(x_axis), Box::new(y_axis)])
29        .with_position(Vec2::new(400.0, 300.0));
30
31    // 3. Create a representation of the point (P)
32    let point = Circle::default()
33        .with_radius(8.0)
34        .with_fill(Color::rgb8(0xe1, 0x32, 0x38)); // Red
35
36    // 4. Create text labels that show the values
37    let x_label = TextNode::default()
38        .with_text("X: 0")
39        .with_font_size(24.0)
40        .with_fill(Color::WHITE);
41
42    let y_label = TextNode::default()
43        .with_text("Y: 0")
44        .with_font_size(24.0)
45        .with_fill(Color::WHITE);
46
47    // 5. Use .bind() to derive node properties from our variables
48    // This makes node properties react to x_var and y_var.
49
50    // Circle position follows both
51    let y_clone = y_var.clone();
52    let circle_pos_link = point.position.bind(x_var.clone(), move |x| {
53        Vec2::new(x + 400.0, y_clone.get() + 300.0)
54    });
55
56    // X Label follows X but stays at bottom
57    let x_label_pos_link = x_label
58        .position
59        .bind(x_var.clone(), |x| Vec2::new(x + 400.0, 550.0));
60
61    // Y Label stays at left but follows Y
62    let y_label_pos_link = y_label
63        .position
64        .bind(y_var.clone(), |y| Vec2::new(75.0, y + 300.0));
65
66    // Dynamic text update for labels
67    let x_text_link = x_label.text.bind(x_var.clone(), |x| format!("X: {:.1}", x));
68    let y_text_link = y_label.text.bind(y_var.clone(), |y| format!("Y: {:.1}", y));
69
70    // Add everything to the scene
71    project.scene.add(Box::new(axes));
72    project.scene.add(Box::new(point));
73    project.scene.add(Box::new(x_label));
74    project.scene.add(Box::new(y_label));
75
76    // Add the links as "invisible" nodes that just perform the sync
77    project.scene.add(Box::new(circle_pos_link));
78    project.scene.add(Box::new(x_label_pos_link));
79    project.scene.add(Box::new(y_label_pos_link));
80    project.scene.add(Box::new(x_text_link));
81    project.scene.add(Box::new(y_text_link));
82
83    // 6. Animate our independent variables!
84    project.scene.video_timeline.add(chain![
85        // Move X
86        x_var
87            .to(200.0, Duration::from_secs(1))
88            .ease(easings::cubic_out),
89        // Wait
90        wait(Duration::from_millis(500)),
91        // Move Y
92        y_var
93            .to(-150.0, Duration::from_secs(1))
94            .ease(easings::back_out),
95        // Move both together
96        all![
97            x_var
98                .to(-250.0, Duration::from_secs(2))
99                .ease(easings::expo_in_out),
100            y_var
101                .to(100.0, Duration::from_secs(2))
102                .ease(easings::sine_in_out),
103        ],
104        // Reset
105        all![
106            x_var.to(0.0, Duration::from_secs(1)),
107            y_var.to(0.0, Duration::from_secs(1)),
108        ],
109        // Final wait to see the result
110        wait(Duration::from_secs(1)),
111    ]);
112
113    project.show().expect("Failed to render");
114}
examples/advanced_flow.rs (line 31)
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}
Source

pub fn rgb(r: f64, g: f64, b: f64) -> Color

Create a color from three floating point values, each in the range 0.0 to 1.0.

The interpretation is the same as rgb8, and no greater precision is (currently) assumed.

Source

pub fn rgba(r: f64, g: f64, b: f64, a: f64) -> Color

Create a color from four floating point values, each in the range 0.0 to 1.0.

The interpretation is the same as rgba32, and no greater precision is (currently) assumed.

Source

pub fn hlc(h: f64, l: f64, c: f64) -> Color

Create a color from a CIEL*a*b* polar (also known as CIE HCL) specification.

The h parameter is an angle in degrees, with 0 roughly magenta, 90 roughly yellow, 180 roughly cyan, and 270 roughly blue. The l parameter is perceptual luminance, with 0 black and 100 white. The c parameter is a chrominance concentration, with 0 grayscale and a nominal maximum of 127 (in the future, higher values might be useful, for high gamut contexts).

Currently this is just converted into sRGB, but in the future as we support high-gamut colorspaces, it can be used to specify more colors or existing colors with a higher accuracy.

Currently out-of-gamut values are clipped to the nearest sRGB color, which is perhaps not ideal (the clipping might change the hue). See https://github.com/d3/d3-color/issues/33 for discussion.

Source

pub fn hlca(h: f64, l: f64, c: f64, a: f64) -> Color

Create a color from a CIEL*a*b* polar specification and alpha.

The a value represents alpha in the range 0.0 to 1.0.

Source

pub fn parse(s: &str) -> Option<Color>

Parses a color from a string.

Currently accepts CSS style hexadecimal colors of the forms #RGB, #RGBA, #RRGGBB, #RRGGBBAA or the name of an SVG color such as “aliceblue”.

Source

pub fn with_alpha_factor(self, alpha: f32) -> Color

Returns the color with the alpha component multiplied by the specified factor.

Source

pub fn to_premul_u32(self) -> u32

Returns the color as a packed premultiplied value.

Source§

impl Color

Named SVG colors.

Source

pub const ALICE_BLUE: Color

Alice blue (240, 248, 255, 255)

Source

pub const ANTIQUE_WHITE: Color

Antique white (250, 235, 215, 255)

Source

pub const AQUA: Color

Aqua (0, 255, 255, 255)

Source

pub const AQUAMARINE: Color

Aquamarine (127, 255, 212, 255)

Source

pub const AZURE: Color

Azure (240, 255, 255, 255)

Source

pub const BEIGE: Color

Beige (245, 245, 220, 255)

Source

pub const BISQUE: Color

Bisque (255, 228, 196, 255)

Source

pub const BLACK: Color

Black (0, 0, 0, 255)

Source

pub const BLANCHED_ALMOND: Color

Blanched almond (255, 235, 205, 255)

Source

pub const BLUE: Color

Blue (0, 0, 255, 255)

Source

pub const BLUE_VIOLET: Color

Blue violet (138, 43, 226, 255)

Source

pub const BROWN: Color

Brown (165, 42, 42, 255)

Source

pub const BURLYWOOD: Color

Burlywood (222, 184, 135, 255)

Source

pub const CADET_BLUE: Color

Cadet blue (95, 158, 160, 255)

Source

pub const CHARTREUSE: Color

Chartreuse (127, 255, 0, 255)

Source

pub const CHOCOLATE: Color

Chocolate (210, 105, 30, 255)

Source

pub const CORAL: Color

Coral (255, 127, 80, 255)

Source

pub const CORNFLOWER_BLUE: Color

Cornflower blue (100, 149, 237, 255)

Source

pub const CORNSILK: Color

Cornsilk (255, 248, 220, 255)

Source

pub const CRIMSON: Color

Crimson (220, 20, 60, 255)

Source

pub const CYAN: Color

Cyan (0, 255, 255, 255)

Source

pub const DARK_BLUE: Color

Dark blue (0, 0, 139, 255)

Source

pub const DARK_CYAN: Color

Dark cyan (0, 139, 139, 255)

Source

pub const DARK_GOLDENROD: Color

Dark goldenrod (184, 134, 11, 255)

Source

pub const DARK_GRAY: Color

Dark gray (169, 169, 169, 255)

Source

pub const DARK_GREEN: Color

Dark green (0, 100, 0, 255)

Source

pub const DARK_KHAKI: Color

Dark khaki (189, 183, 107, 255)

Source

pub const DARK_MAGENTA: Color

Dark magenta (139, 0, 139, 255)

Source

pub const DARK_OLIVE_GREEN: Color

Dark olive green (85, 107, 47, 255)

Source

pub const DARK_ORANGE: Color

Dark orange (255, 140, 0, 255)

Source

pub const DARK_ORCHID: Color

Dark orchid (153, 50, 204, 255)

Source

pub const DARK_RED: Color

Dark red (139, 0, 0, 255)

Source

pub const DARK_SALMON: Color

Dark salmon (233, 150, 122, 255)

Source

pub const DARK_SEA_GREEN: Color

Dark sea green (143, 188, 143, 255)

Source

pub const DARK_SLATE_BLUE: Color

Dark slate blue (72, 61, 139, 255)

Source

pub const DARK_SLATE_GRAY: Color

Dark slate gray (47, 79, 79, 255)

Source

pub const DARK_TURQUOISE: Color

Dark turquoise (0, 206, 209, 255)

Source

pub const DARK_VIOLET: Color

Dark violet (148, 0, 211, 255)

Source

pub const DEEP_PINK: Color

Deep pink (255, 20, 147, 255)

Source

pub const DEEP_SKY_BLUE: Color

Deep sky blue (0, 191, 255, 255)

Source

pub const DIM_GRAY: Color

Dim gray (105, 105, 105, 255)

Source

pub const DODGER_BLUE: Color

Dodger blue (30, 144, 255, 255)

Source

pub const FIREBRICK: Color

Firebrick (178, 34, 34, 255)

Source

pub const FLORAL_WHITE: Color

Floral white (255, 250, 240, 255)

Source

pub const FOREST_GREEN: Color

Forest green (34, 139, 34, 255)

Source

pub const FUCHSIA: Color

Fuchsia (255, 0, 255, 255)

Source

pub const GAINSBORO: Color

Gainsboro (220, 220, 220, 255)

Source

pub const GHOST_WHITE: Color

Ghost white (248, 248, 255, 255)

Source

pub const GOLD: Color

Gold (255, 215, 0, 255)

Source

pub const GOLDENROD: Color

Goldenrod (218, 165, 32, 255)

Source

pub const GRAY: Color

Gray (128, 128, 128, 255)

Source

pub const GREEN: Color

Green (0, 128, 0, 255)

Source

pub const GREEN_YELLOW: Color

Green yellow (173, 255, 47, 255)

Source

pub const HONEYDEW: Color

Honeydew (240, 255, 240, 255)

Source

pub const HOT_PINK: Color

Hot pink (255, 105, 180, 255)

Source

pub const INDIAN_RED: Color

Indian red (205, 92, 92, 255)

Source

pub const INDIGO: Color

Indigo (75, 0, 130, 255)

Source

pub const IVORY: Color

Ivory (255, 255, 240, 255)

Source

pub const KHAKI: Color

Khaki (240, 230, 140, 255)

Source

pub const LAVENDER: Color

Lavender (230, 230, 250, 255)

Source

pub const LAVENDER_BLUSH: Color

Lavender blush (255, 240, 245, 255)

Source

pub const LAWN_GREEN: Color

Lawn green (124, 252, 0, 255)

Source

pub const LEMON_CHIFFON: Color

Lemon chiffon (255, 250, 205, 255)

Source

pub const LIGHT_BLUE: Color

Light blue (173, 216, 230, 255)

Source

pub const LIGHT_CORAL: Color

Light coral (240, 128, 128, 255)

Source

pub const LIGHT_CYAN: Color

Light cyan (224, 255, 255, 255)

Source

pub const LIGHT_GOLDENROD_YELLOW: Color

Light goldenrod yellow (250, 250, 210, 255)

Source

pub const LIGHT_GRAY: Color

Light gray (211, 211, 211, 255)

Source

pub const LIGHT_GREEN: Color

Light green (144, 238, 144, 255)

Source

pub const LIGHT_PINK: Color

Light pink (255, 182, 193, 255)

Source

pub const LIGHT_SALMON: Color

Light salmon (255, 160, 122, 255)

Source

pub const LIGHT_SEA_GREEN: Color

Light sea green (32, 178, 170, 255)

Source

pub const LIGHT_SKY_BLUE: Color

Light sky blue (135, 206, 250, 255)

Source

pub const LIGHT_SLATE_GRAY: Color

Light slate gray (119, 136, 153, 255)

Source

pub const LIGHT_STEEL_BLUE: Color

Light steel blue (176, 196, 222, 255)

Source

pub const LIGHT_YELLOW: Color

Light yellow (255, 255, 224, 255)

Source

pub const LIME: Color

Lime (0, 255, 0, 255)

Source

pub const LIME_GREEN: Color

Lime green (50, 205, 50, 255)

Source

pub const LINEN: Color

Linen (250, 240, 230, 255)

Source

pub const MAGENTA: Color

Magenta (255, 0, 255, 255)

Source

pub const MAROON: Color

Maroon (128, 0, 0, 255)

Source

pub const MEDIUM_AQUAMARINE: Color

Medium aquamarine (102, 205, 170, 255)

Source

pub const MEDIUM_BLUE: Color

Medium blue (0, 0, 205, 255)

Source

pub const MEDIUM_ORCHID: Color

Medium orchid (186, 85, 211, 255)

Source

pub const MEDIUM_PURPLE: Color

Medium purple (147, 112, 219, 255)

Source

pub const MEDIUM_SEA_GREEN: Color

Medium sea green (60, 179, 113, 255)

Source

pub const MEDIUM_SLATE_BLUE: Color

Medium slate blue (123, 104, 238, 255)

Source

pub const MEDIUM_SPRING_GREEN: Color

Medium spring green (0, 250, 154, 255)

Source

pub const MEDIUM_TURQUOISE: Color

Medium turquoise (72, 209, 204, 255)

Source

pub const MEDIUM_VIOLET_RED: Color

Medium violet red (199, 21, 133, 255)

Source

pub const MIDNIGHT_BLUE: Color

Midnight blue (25, 25, 112, 255)

Source

pub const MINT_CREAM: Color

Mint cream (245, 255, 250, 255)

Source

pub const MISTY_ROSE: Color

Misty rose (255, 228, 225, 255)

Source

pub const MOCCASIN: Color

Moccasin (255, 228, 181, 255)

Source

pub const NAVAJO_WHITE: Color

Navajo white (255, 222, 173, 255)

Source

pub const NAVY: Color

Navy (0, 0, 128, 255)

Source

pub const OLD_LACE: Color

Old lace (253, 245, 230, 255)

Source

pub const OLIVE: Color

Olive (128, 128, 0, 255)

Source

pub const OLIVE_DRAB: Color

Olive drab (107, 142, 35, 255)

Source

pub const ORANGE: Color

Orange (255, 165, 0, 255)

Source

pub const ORANGE_RED: Color

Orange red (255, 69, 0, 255)

Source

pub const ORCHID: Color

Orchid (218, 112, 214, 255)

Source

pub const PALE_GOLDENROD: Color

Pale goldenrod (238, 232, 170, 255)

Source

pub const PALE_GREEN: Color

Pale green (152, 251, 152, 255)

Source

pub const PALE_TURQUOISE: Color

Pale turquoise (175, 238, 238, 255)

Source

pub const PALE_VIOLET_RED: Color

Pale violet red (219, 112, 147, 255)

Source

pub const PAPAYA_WHIP: Color

Papaya whip (255, 239, 213, 255)

Source

pub const PEACH_PUFF: Color

Peach puff (255, 218, 185, 255)

Source

pub const PERU: Color

Peru (205, 133, 63, 255)

Source

pub const PINK: Color

Pink (255, 192, 203, 255)

Source

pub const PLUM: Color

Plum (221, 160, 221, 255)

Source

pub const POWDER_BLUE: Color

Powder blue (176, 224, 230, 255)

Source

pub const PURPLE: Color

Purple (128, 0, 128, 255)

Source

pub const REBECCA_PURPLE: Color

Rebecca purple (102, 51, 153, 255)

Source

pub const RED: Color

Red (255, 0, 0, 255)

Source

pub const ROSY_BROWN: Color

Rosy brown (188, 143, 143, 255)

Source

pub const ROYAL_BLUE: Color

Royal blue (65, 105, 225, 255)

Source

pub const SADDLE_BROWN: Color

Saddle brown (139, 69, 19, 255)

Source

pub const SALMON: Color

Salmon (250, 128, 114, 255)

Source

pub const SANDY_BROWN: Color

Sandy brown (244, 164, 96, 255)

Source

pub const SEA_GREEN: Color

Sea green (46, 139, 87, 255)

Source

pub const SEASHELL: Color

Seashell (255, 245, 238, 255)

Source

pub const SIENNA: Color

Sienna (160, 82, 45, 255)

Source

pub const SILVER: Color

Silver (192, 192, 192, 255)

Source

pub const SKY_BLUE: Color

Sky blue (135, 206, 235, 255)

Source

pub const SLATE_BLUE: Color

Slate blue (106, 90, 205, 255)

Source

pub const SLATE_GRAY: Color

Slate gray (112, 128, 144, 255)

Source

pub const SNOW: Color

Snow (255, 250, 250, 255)

Source

pub const SPRING_GREEN: Color

Spring green (0, 255, 127, 255)

Source

pub const STEEL_BLUE: Color

Steel blue (70, 130, 180, 255)

Source

pub const TAN: Color

Tan (210, 180, 140, 255)

Source

pub const TEAL: Color

Teal (0, 128, 128, 255)

Source

pub const THISTLE: Color

Thistle (216, 191, 216, 255)

Source

pub const TOMATO: Color

Tomato (255, 99, 71, 255)

Source

pub const TRANSPARENT: Color

Transparent (0, 0, 0, 0)

Source

pub const TURQUOISE: Color

Turquoise (64, 224, 208, 255)

Source

pub const VIOLET: Color

Violet (238, 130, 238, 255)

Source

pub const WHEAT: Color

Wheat (245, 222, 179, 255)

Source

pub const WHITE: Color

White (255, 255, 255, 255)

Source

pub const WHITE_SMOKE: Color

White smoke (245, 245, 245, 255)

Source

pub const YELLOW: Color

Yellow (255, 255, 0, 255)

Source

pub const YELLOW_GREEN: Color

Yellow green (154, 205, 50, 255)

Trait Implementations§

Source§

impl Clone for Color

Source§

fn clone(&self) -> Color

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Color

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for Color

Source§

fn default() -> Color

Returns the “default value” for a type. Read more
Source§

impl From<[u8; 3]> for Color

Source§

fn from(rgb: [u8; 3]) -> Color

Converts to this type from the input type.
Source§

impl From<[u8; 4]> for Color

Source§

fn from(rgba: [u8; 4]) -> Color

Converts to this type from the input type.
Source§

impl Hash for Color

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for Color

Source§

fn cmp(&self, other: &Color) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for Color

Source§

fn eq(&self, other: &Color) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialOrd for Color

Source§

fn partial_cmp(&self, other: &Color) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Tweenable for Color

Source§

fn interpolate(a: &Self, b: &Self, t: f32) -> Self

Source§

fn state_hash(&self) -> u64

Source§

impl Copy for Color

Source§

impl Eq for Color

Source§

impl StructuralPartialEq for Color

Auto Trait Implementations§

§

impl Freeze for Color

§

impl RefUnwindSafe for Color

§

impl Send for Color

§

impl Sync for Color

§

impl Unpin for Color

§

impl UnsafeUnpin for Color

§

impl UnwindSafe for Color

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Comparable<K> for Q
where Q: Ord + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn compare(&self, key: &K) -> Ordering

Compare self to key and return their ordering.
Source§

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> Filterable for T

Source§

fn filterable( self, filter_name: &'static str, ) -> RequestFilterDataProvider<T, fn(DataRequest<'_>) -> bool>

Creates a filterable data provider with the given name for debugging. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

Source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
Source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
Source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> StrictAs for T

Source§

fn strict_as<Dst>(self) -> Dst
where T: StrictCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> StrictCastFrom<Src> for Dst
where Src: StrictCast<Dst>,

Source§

fn strict_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> MaybeSendSync for T
where T: Send + Sync,

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,