Skip to main content

EffectConfig

Struct EffectConfig 

Source
pub struct EffectConfig {
    pub duration: usize,
    pub hold_final_frames: usize,
    pub seed: u64,
    pub gradient: Gradient,
    pub gradient_direction: GradientDirection,
    pub easing: Easing,
    pub existing_color_handling: ExistingColorHandling,
    pub no_color: bool,
    pub background: Option<Color>,
    pub canvas_width: Option<usize>,
    pub canvas_height: Option<usize>,
    pub tab_width: usize,
}
Expand description

Shared configuration used by the embeddable Rust renderers.

Fields§

§duration: usize§hold_final_frames: usize§seed: u64§gradient: Gradient§gradient_direction: GradientDirection§easing: Easing§existing_color_handling: ExistingColorHandling§no_color: bool§background: Option<Color>§canvas_width: Option<usize>§canvas_height: Option<usize>§tab_width: usize

Implementations§

Source§

impl EffectConfig

Source

pub fn with_duration(self, duration: usize) -> Self

Examples found in repository?
examples/demo.rs (line 13)
9fn main() {
10    let args = Args::parse();
11    let kind = EffectKind::from_str(&args.effect).unwrap_or(EffectKind::Wipe);
12    let mut config = EffectConfig::default()
13        .with_duration(args.duration)
14        .with_seed(args.seed);
15
16    if let (Some(width), Some(height)) = (args.width, args.height) {
17        config = config.with_canvas_size(width.max(1), height.max(1));
18    }
19
20    let effect = Effect::with_config(kind, args.text, config);
21
22    let mut stdout = io::stdout();
23    for frame in effect.iter() {
24        write!(stdout, "\x1b[2J\x1b[H{}", frame.to_ansi_string()).unwrap();
25        stdout.flush().unwrap();
26        thread::sleep(Duration::from_millis((1000 / args.fps.max(1)) as u64));
27    }
28    writeln!(stdout).unwrap();
29}
More examples
Hide additional examples
examples/showcase.rs (line 377)
359fn build_panes(
360    text: &str,
361    layout: &Layout,
362    base_duration: usize,
363    theme: Theme,
364) -> Vec<PaneRuntime> {
365    EffectKind::all()
366        .iter()
367        .enumerate()
368        .map(|(index, kind)| {
369            let shape = pane_shape(*kind, index, layout);
370            let (pane_width, pane_height) = pane_size(layout, shape);
371            let inner_width = pane_width.saturating_sub(2).max(8);
372            let inner_height = pane_height.saturating_sub(2).max(3);
373            let snippet = snippet(text, index, inner_width, inner_height);
374            let accent = theme.accent(*kind, index);
375            let duration = base_duration + (index % 9) * 5;
376            let config = EffectConfig::default()
377                .with_duration(duration)
378                .with_seed(1009 + index as u64 * 97)
379                .with_canvas_size(inner_width, inner_height)
380                .with_gradient(
381                    effect_gradient(*kind, index, theme),
382                    gradient_direction(index),
383                );
384            let frames = Effect::with_config(*kind, snippet, config).frames();
385            PaneRuntime {
386                index,
387                kind: *kind,
388                frames,
389                offset: index * 13,
390                speed_numerator: 1 + (index % 4),
391                accent,
392                shape,
393            }
394        })
395        .collect()
396}
examples/loader_lab.rs (line 781)
727fn build_panes(effect_width: usize, effect_height: usize, focus_ticks: usize) -> Vec<Pane> {
728    let ops = [
729        ("DOWNLOAD", "tendon-atlas", "MB"),
730        ("UPLOAD", "field-manifest", "MB"),
731        ("SYNC", "sensor-mesh", "pkt"),
732        ("VERIFY", "leverage-map", "chk"),
733        ("STREAM", "gait-vectors", "vec"),
734        ("FORGE", "actuator-curve", "N"),
735        ("DECRYPT", "intent-bus", "blk"),
736        ("MIRROR", "joint-state", "msg"),
737        ("PACK", "motion-plan", "ops"),
738        ("RELAY", "balance-loop", "hz"),
739        ("CALIBRATE", "cable-stack", "mm"),
740        ("ARCHIVE", "field-log", "MB"),
741    ];
742    let effects = [
743        EffectKind::Matrix,
744        EffectKind::Burn,
745        EffectKind::Decrypt,
746        EffectKind::Thunderstorm,
747        EffectKind::LaserEtch,
748        EffectKind::Blackhole,
749        EffectKind::Rings,
750        EffectKind::Swarm,
751        EffectKind::Fireworks,
752        EffectKind::Slice,
753        EffectKind::Waves,
754        EffectKind::Wipe,
755    ];
756    let palette = [
757        Color::rgb(74, 255, 170),
758        Color::rgb(255, 118, 54),
759        Color::rgb(92, 204, 255),
760        Color::rgb(255, 216, 92),
761        Color::rgb(172, 130, 255),
762        Color::rgb(255, 112, 218),
763        Color::rgb(112, 236, 255),
764        Color::rgb(255, 178, 72),
765    ];
766    let speeds = [1, 2, 3, 4, 5, 7, 9, 11];
767
768    LoaderKind::all()
769        .iter()
770        .enumerate()
771        .map(|(index, kind)| {
772            let (op, noun, unit) = ops[index % ops.len()];
773            let effect_kind = effects[(index * 5 + 3) % effects.len()];
774            let accent = palette[index % palette.len()];
775            let label = format!("{} {}", op.to_ascii_lowercase(), noun);
776            let effect_text = format!("{} {}\n{}", op, kind.name(), noun).to_ascii_uppercase();
777            let effect = Effect::with_config(
778                effect_kind,
779                effect_text,
780                EffectConfig::default()
781                    .with_duration(focus_ticks)
782                    .with_seed(991 + index as u64 * 37)
783                    .with_canvas_size(effect_width, effect_height.max(1))
784                    .with_gradient(
785                        Gradient::new(
786                            vec![accent, accent.brighten(0.32), Color::rgb(230, 244, 250)],
787                            20,
788                        ),
789                        GradientDirection::Diagonal,
790                    ),
791            );
792            Pane {
793                index,
794                kind: *kind,
795                op,
796                noun,
797                label,
798                unit,
799                total: 128 + ((index as u64 * 97) % 2048),
800                speed: speeds[index % speeds.len()],
801                offset: index * 17,
802                accent,
803                effect_kind,
804                effect_frames: effect.frames(),
805            }
806        })
807        .collect()
808}
examples/story.rs (line 567)
477fn build_scenes(source: &str, layout: &Layout, scene_ticks: usize) -> Vec<Scene> {
478    let paragraphs = paragraphs(source);
479    let effect_w = layout.stage.w.saturating_sub(8).max(40);
480    let effect_h = layout.stage.h.saturating_sub(16).max(5).min(12);
481    let specs = [
482        (
483            "BOOT SEQUENCE",
484            "matrix rain resolves the mission",
485            EffectKind::Matrix,
486            Color::rgb(74, 255, 170),
487            0usize,
488        ),
489        (
490            "FORGE",
491            "burning the actuator constraints",
492            EffectKind::Burn,
493            Color::rgb(255, 118, 54),
494            3,
495        ),
496        (
497            "STORM SENSORS",
498            "signal and response in the weather",
499            EffectKind::Thunderstorm,
500            Color::rgb(96, 204, 255),
501            2,
502        ),
503        (
504            "LASER ETCH",
505            "leverage maps cut into the frame",
506            EffectKind::LaserEtch,
507            Color::rgb(255, 220, 92),
508            7,
509        ),
510        (
511            "GRAVITY WELL",
512            "weight and balance collapse into order",
513            EffectKind::Blackhole,
514            Color::rgb(164, 126, 255),
515            5,
516        ),
517        (
518            "ORBITAL BALANCE",
519            "rings of motion settle around intent",
520            EffectKind::Rings,
521            Color::rgb(110, 255, 224),
522            6,
523        ),
524        (
525            "SWARM CALIBRATION",
526            "many small forces become one gait",
527            EffectKind::Swarm,
528            Color::rgb(255, 112, 218),
529            4,
530        ),
531        (
532            "FIELD DEMO",
533            "fireworks over the completed machine",
534            EffectKind::Fireworks,
535            Color::rgb(255, 180, 72),
536            1,
537        ),
538    ];
539    specs
540        .iter()
541        .enumerate()
542        .map(
543            |(index, (title, subtitle, kind, accent, paragraph_index))| {
544                let paragraph = paragraphs
545                    .get(*paragraph_index)
546                    .or_else(|| paragraphs.get(index % paragraphs.len().max(1)))
547                    .cloned()
548                    .unwrap_or_else(|| source.to_string());
549                let extra = match kind {
550                    EffectKind::Matrix => "Data falls until it becomes purpose.",
551                    EffectKind::Burn => "The forge removes everything that does not serve motion.",
552                    EffectKind::Thunderstorm => "Noise becomes weather; weather becomes signal.",
553                    EffectKind::LaserEtch => "Leverage is written as geometry and timing.",
554                    EffectKind::Blackhole => {
555                        "Weight collapses into balance before it expands into gait."
556                    }
557                    EffectKind::Rings => "Joints orbit a center of intention.",
558                    EffectKind::Swarm => "Many corrections gather into one quiet step.",
559                    _ => "The machine disappears into the grace of the whole.",
560                };
561                let text = wrap_text(&format!("{}\n\n{}", paragraph, extra), effect_w);
562                let gradient = Gradient::new(
563                    vec![*accent, accent.brighten(0.36), Color::rgb(235, 244, 250)],
564                    32,
565                );
566                let config = EffectConfig::default()
567                    .with_duration(scene_ticks.max(8))
568                    .with_seed(700 + index as u64 * 97)
569                    .with_canvas_size(effect_w, effect_h)
570                    .with_gradient(gradient, GradientDirection::Diagonal);
571                let frames = Effect::with_config(*kind, text.clone(), config).frames();
572                Scene {
573                    title,
574                    subtitle,
575                    effect: *kind,
576                    accent: *accent,
577                    frames,
578                    quote: paragraph,
579                }
580            },
581        )
582        .collect()
583}
Source

pub fn with_seed(self, seed: u64) -> Self

Examples found in repository?
examples/demo.rs (line 14)
9fn main() {
10    let args = Args::parse();
11    let kind = EffectKind::from_str(&args.effect).unwrap_or(EffectKind::Wipe);
12    let mut config = EffectConfig::default()
13        .with_duration(args.duration)
14        .with_seed(args.seed);
15
16    if let (Some(width), Some(height)) = (args.width, args.height) {
17        config = config.with_canvas_size(width.max(1), height.max(1));
18    }
19
20    let effect = Effect::with_config(kind, args.text, config);
21
22    let mut stdout = io::stdout();
23    for frame in effect.iter() {
24        write!(stdout, "\x1b[2J\x1b[H{}", frame.to_ansi_string()).unwrap();
25        stdout.flush().unwrap();
26        thread::sleep(Duration::from_millis((1000 / args.fps.max(1)) as u64));
27    }
28    writeln!(stdout).unwrap();
29}
More examples
Hide additional examples
examples/showcase.rs (line 378)
359fn build_panes(
360    text: &str,
361    layout: &Layout,
362    base_duration: usize,
363    theme: Theme,
364) -> Vec<PaneRuntime> {
365    EffectKind::all()
366        .iter()
367        .enumerate()
368        .map(|(index, kind)| {
369            let shape = pane_shape(*kind, index, layout);
370            let (pane_width, pane_height) = pane_size(layout, shape);
371            let inner_width = pane_width.saturating_sub(2).max(8);
372            let inner_height = pane_height.saturating_sub(2).max(3);
373            let snippet = snippet(text, index, inner_width, inner_height);
374            let accent = theme.accent(*kind, index);
375            let duration = base_duration + (index % 9) * 5;
376            let config = EffectConfig::default()
377                .with_duration(duration)
378                .with_seed(1009 + index as u64 * 97)
379                .with_canvas_size(inner_width, inner_height)
380                .with_gradient(
381                    effect_gradient(*kind, index, theme),
382                    gradient_direction(index),
383                );
384            let frames = Effect::with_config(*kind, snippet, config).frames();
385            PaneRuntime {
386                index,
387                kind: *kind,
388                frames,
389                offset: index * 13,
390                speed_numerator: 1 + (index % 4),
391                accent,
392                shape,
393            }
394        })
395        .collect()
396}
examples/loader_lab.rs (line 782)
727fn build_panes(effect_width: usize, effect_height: usize, focus_ticks: usize) -> Vec<Pane> {
728    let ops = [
729        ("DOWNLOAD", "tendon-atlas", "MB"),
730        ("UPLOAD", "field-manifest", "MB"),
731        ("SYNC", "sensor-mesh", "pkt"),
732        ("VERIFY", "leverage-map", "chk"),
733        ("STREAM", "gait-vectors", "vec"),
734        ("FORGE", "actuator-curve", "N"),
735        ("DECRYPT", "intent-bus", "blk"),
736        ("MIRROR", "joint-state", "msg"),
737        ("PACK", "motion-plan", "ops"),
738        ("RELAY", "balance-loop", "hz"),
739        ("CALIBRATE", "cable-stack", "mm"),
740        ("ARCHIVE", "field-log", "MB"),
741    ];
742    let effects = [
743        EffectKind::Matrix,
744        EffectKind::Burn,
745        EffectKind::Decrypt,
746        EffectKind::Thunderstorm,
747        EffectKind::LaserEtch,
748        EffectKind::Blackhole,
749        EffectKind::Rings,
750        EffectKind::Swarm,
751        EffectKind::Fireworks,
752        EffectKind::Slice,
753        EffectKind::Waves,
754        EffectKind::Wipe,
755    ];
756    let palette = [
757        Color::rgb(74, 255, 170),
758        Color::rgb(255, 118, 54),
759        Color::rgb(92, 204, 255),
760        Color::rgb(255, 216, 92),
761        Color::rgb(172, 130, 255),
762        Color::rgb(255, 112, 218),
763        Color::rgb(112, 236, 255),
764        Color::rgb(255, 178, 72),
765    ];
766    let speeds = [1, 2, 3, 4, 5, 7, 9, 11];
767
768    LoaderKind::all()
769        .iter()
770        .enumerate()
771        .map(|(index, kind)| {
772            let (op, noun, unit) = ops[index % ops.len()];
773            let effect_kind = effects[(index * 5 + 3) % effects.len()];
774            let accent = palette[index % palette.len()];
775            let label = format!("{} {}", op.to_ascii_lowercase(), noun);
776            let effect_text = format!("{} {}\n{}", op, kind.name(), noun).to_ascii_uppercase();
777            let effect = Effect::with_config(
778                effect_kind,
779                effect_text,
780                EffectConfig::default()
781                    .with_duration(focus_ticks)
782                    .with_seed(991 + index as u64 * 37)
783                    .with_canvas_size(effect_width, effect_height.max(1))
784                    .with_gradient(
785                        Gradient::new(
786                            vec![accent, accent.brighten(0.32), Color::rgb(230, 244, 250)],
787                            20,
788                        ),
789                        GradientDirection::Diagonal,
790                    ),
791            );
792            Pane {
793                index,
794                kind: *kind,
795                op,
796                noun,
797                label,
798                unit,
799                total: 128 + ((index as u64 * 97) % 2048),
800                speed: speeds[index % speeds.len()],
801                offset: index * 17,
802                accent,
803                effect_kind,
804                effect_frames: effect.frames(),
805            }
806        })
807        .collect()
808}
examples/story.rs (line 568)
477fn build_scenes(source: &str, layout: &Layout, scene_ticks: usize) -> Vec<Scene> {
478    let paragraphs = paragraphs(source);
479    let effect_w = layout.stage.w.saturating_sub(8).max(40);
480    let effect_h = layout.stage.h.saturating_sub(16).max(5).min(12);
481    let specs = [
482        (
483            "BOOT SEQUENCE",
484            "matrix rain resolves the mission",
485            EffectKind::Matrix,
486            Color::rgb(74, 255, 170),
487            0usize,
488        ),
489        (
490            "FORGE",
491            "burning the actuator constraints",
492            EffectKind::Burn,
493            Color::rgb(255, 118, 54),
494            3,
495        ),
496        (
497            "STORM SENSORS",
498            "signal and response in the weather",
499            EffectKind::Thunderstorm,
500            Color::rgb(96, 204, 255),
501            2,
502        ),
503        (
504            "LASER ETCH",
505            "leverage maps cut into the frame",
506            EffectKind::LaserEtch,
507            Color::rgb(255, 220, 92),
508            7,
509        ),
510        (
511            "GRAVITY WELL",
512            "weight and balance collapse into order",
513            EffectKind::Blackhole,
514            Color::rgb(164, 126, 255),
515            5,
516        ),
517        (
518            "ORBITAL BALANCE",
519            "rings of motion settle around intent",
520            EffectKind::Rings,
521            Color::rgb(110, 255, 224),
522            6,
523        ),
524        (
525            "SWARM CALIBRATION",
526            "many small forces become one gait",
527            EffectKind::Swarm,
528            Color::rgb(255, 112, 218),
529            4,
530        ),
531        (
532            "FIELD DEMO",
533            "fireworks over the completed machine",
534            EffectKind::Fireworks,
535            Color::rgb(255, 180, 72),
536            1,
537        ),
538    ];
539    specs
540        .iter()
541        .enumerate()
542        .map(
543            |(index, (title, subtitle, kind, accent, paragraph_index))| {
544                let paragraph = paragraphs
545                    .get(*paragraph_index)
546                    .or_else(|| paragraphs.get(index % paragraphs.len().max(1)))
547                    .cloned()
548                    .unwrap_or_else(|| source.to_string());
549                let extra = match kind {
550                    EffectKind::Matrix => "Data falls until it becomes purpose.",
551                    EffectKind::Burn => "The forge removes everything that does not serve motion.",
552                    EffectKind::Thunderstorm => "Noise becomes weather; weather becomes signal.",
553                    EffectKind::LaserEtch => "Leverage is written as geometry and timing.",
554                    EffectKind::Blackhole => {
555                        "Weight collapses into balance before it expands into gait."
556                    }
557                    EffectKind::Rings => "Joints orbit a center of intention.",
558                    EffectKind::Swarm => "Many corrections gather into one quiet step.",
559                    _ => "The machine disappears into the grace of the whole.",
560                };
561                let text = wrap_text(&format!("{}\n\n{}", paragraph, extra), effect_w);
562                let gradient = Gradient::new(
563                    vec![*accent, accent.brighten(0.36), Color::rgb(235, 244, 250)],
564                    32,
565                );
566                let config = EffectConfig::default()
567                    .with_duration(scene_ticks.max(8))
568                    .with_seed(700 + index as u64 * 97)
569                    .with_canvas_size(effect_w, effect_h)
570                    .with_gradient(gradient, GradientDirection::Diagonal);
571                let frames = Effect::with_config(*kind, text.clone(), config).frames();
572                Scene {
573                    title,
574                    subtitle,
575                    effect: *kind,
576                    accent: *accent,
577                    frames,
578                    quote: paragraph,
579                }
580            },
581        )
582        .collect()
583}
Source

pub fn with_gradient( self, gradient: Gradient, direction: GradientDirection, ) -> Self

Examples found in repository?
examples/showcase.rs (lines 380-383)
359fn build_panes(
360    text: &str,
361    layout: &Layout,
362    base_duration: usize,
363    theme: Theme,
364) -> Vec<PaneRuntime> {
365    EffectKind::all()
366        .iter()
367        .enumerate()
368        .map(|(index, kind)| {
369            let shape = pane_shape(*kind, index, layout);
370            let (pane_width, pane_height) = pane_size(layout, shape);
371            let inner_width = pane_width.saturating_sub(2).max(8);
372            let inner_height = pane_height.saturating_sub(2).max(3);
373            let snippet = snippet(text, index, inner_width, inner_height);
374            let accent = theme.accent(*kind, index);
375            let duration = base_duration + (index % 9) * 5;
376            let config = EffectConfig::default()
377                .with_duration(duration)
378                .with_seed(1009 + index as u64 * 97)
379                .with_canvas_size(inner_width, inner_height)
380                .with_gradient(
381                    effect_gradient(*kind, index, theme),
382                    gradient_direction(index),
383                );
384            let frames = Effect::with_config(*kind, snippet, config).frames();
385            PaneRuntime {
386                index,
387                kind: *kind,
388                frames,
389                offset: index * 13,
390                speed_numerator: 1 + (index % 4),
391                accent,
392                shape,
393            }
394        })
395        .collect()
396}
More examples
Hide additional examples
examples/loader_lab.rs (lines 784-790)
727fn build_panes(effect_width: usize, effect_height: usize, focus_ticks: usize) -> Vec<Pane> {
728    let ops = [
729        ("DOWNLOAD", "tendon-atlas", "MB"),
730        ("UPLOAD", "field-manifest", "MB"),
731        ("SYNC", "sensor-mesh", "pkt"),
732        ("VERIFY", "leverage-map", "chk"),
733        ("STREAM", "gait-vectors", "vec"),
734        ("FORGE", "actuator-curve", "N"),
735        ("DECRYPT", "intent-bus", "blk"),
736        ("MIRROR", "joint-state", "msg"),
737        ("PACK", "motion-plan", "ops"),
738        ("RELAY", "balance-loop", "hz"),
739        ("CALIBRATE", "cable-stack", "mm"),
740        ("ARCHIVE", "field-log", "MB"),
741    ];
742    let effects = [
743        EffectKind::Matrix,
744        EffectKind::Burn,
745        EffectKind::Decrypt,
746        EffectKind::Thunderstorm,
747        EffectKind::LaserEtch,
748        EffectKind::Blackhole,
749        EffectKind::Rings,
750        EffectKind::Swarm,
751        EffectKind::Fireworks,
752        EffectKind::Slice,
753        EffectKind::Waves,
754        EffectKind::Wipe,
755    ];
756    let palette = [
757        Color::rgb(74, 255, 170),
758        Color::rgb(255, 118, 54),
759        Color::rgb(92, 204, 255),
760        Color::rgb(255, 216, 92),
761        Color::rgb(172, 130, 255),
762        Color::rgb(255, 112, 218),
763        Color::rgb(112, 236, 255),
764        Color::rgb(255, 178, 72),
765    ];
766    let speeds = [1, 2, 3, 4, 5, 7, 9, 11];
767
768    LoaderKind::all()
769        .iter()
770        .enumerate()
771        .map(|(index, kind)| {
772            let (op, noun, unit) = ops[index % ops.len()];
773            let effect_kind = effects[(index * 5 + 3) % effects.len()];
774            let accent = palette[index % palette.len()];
775            let label = format!("{} {}", op.to_ascii_lowercase(), noun);
776            let effect_text = format!("{} {}\n{}", op, kind.name(), noun).to_ascii_uppercase();
777            let effect = Effect::with_config(
778                effect_kind,
779                effect_text,
780                EffectConfig::default()
781                    .with_duration(focus_ticks)
782                    .with_seed(991 + index as u64 * 37)
783                    .with_canvas_size(effect_width, effect_height.max(1))
784                    .with_gradient(
785                        Gradient::new(
786                            vec![accent, accent.brighten(0.32), Color::rgb(230, 244, 250)],
787                            20,
788                        ),
789                        GradientDirection::Diagonal,
790                    ),
791            );
792            Pane {
793                index,
794                kind: *kind,
795                op,
796                noun,
797                label,
798                unit,
799                total: 128 + ((index as u64 * 97) % 2048),
800                speed: speeds[index % speeds.len()],
801                offset: index * 17,
802                accent,
803                effect_kind,
804                effect_frames: effect.frames(),
805            }
806        })
807        .collect()
808}
examples/story.rs (line 570)
477fn build_scenes(source: &str, layout: &Layout, scene_ticks: usize) -> Vec<Scene> {
478    let paragraphs = paragraphs(source);
479    let effect_w = layout.stage.w.saturating_sub(8).max(40);
480    let effect_h = layout.stage.h.saturating_sub(16).max(5).min(12);
481    let specs = [
482        (
483            "BOOT SEQUENCE",
484            "matrix rain resolves the mission",
485            EffectKind::Matrix,
486            Color::rgb(74, 255, 170),
487            0usize,
488        ),
489        (
490            "FORGE",
491            "burning the actuator constraints",
492            EffectKind::Burn,
493            Color::rgb(255, 118, 54),
494            3,
495        ),
496        (
497            "STORM SENSORS",
498            "signal and response in the weather",
499            EffectKind::Thunderstorm,
500            Color::rgb(96, 204, 255),
501            2,
502        ),
503        (
504            "LASER ETCH",
505            "leverage maps cut into the frame",
506            EffectKind::LaserEtch,
507            Color::rgb(255, 220, 92),
508            7,
509        ),
510        (
511            "GRAVITY WELL",
512            "weight and balance collapse into order",
513            EffectKind::Blackhole,
514            Color::rgb(164, 126, 255),
515            5,
516        ),
517        (
518            "ORBITAL BALANCE",
519            "rings of motion settle around intent",
520            EffectKind::Rings,
521            Color::rgb(110, 255, 224),
522            6,
523        ),
524        (
525            "SWARM CALIBRATION",
526            "many small forces become one gait",
527            EffectKind::Swarm,
528            Color::rgb(255, 112, 218),
529            4,
530        ),
531        (
532            "FIELD DEMO",
533            "fireworks over the completed machine",
534            EffectKind::Fireworks,
535            Color::rgb(255, 180, 72),
536            1,
537        ),
538    ];
539    specs
540        .iter()
541        .enumerate()
542        .map(
543            |(index, (title, subtitle, kind, accent, paragraph_index))| {
544                let paragraph = paragraphs
545                    .get(*paragraph_index)
546                    .or_else(|| paragraphs.get(index % paragraphs.len().max(1)))
547                    .cloned()
548                    .unwrap_or_else(|| source.to_string());
549                let extra = match kind {
550                    EffectKind::Matrix => "Data falls until it becomes purpose.",
551                    EffectKind::Burn => "The forge removes everything that does not serve motion.",
552                    EffectKind::Thunderstorm => "Noise becomes weather; weather becomes signal.",
553                    EffectKind::LaserEtch => "Leverage is written as geometry and timing.",
554                    EffectKind::Blackhole => {
555                        "Weight collapses into balance before it expands into gait."
556                    }
557                    EffectKind::Rings => "Joints orbit a center of intention.",
558                    EffectKind::Swarm => "Many corrections gather into one quiet step.",
559                    _ => "The machine disappears into the grace of the whole.",
560                };
561                let text = wrap_text(&format!("{}\n\n{}", paragraph, extra), effect_w);
562                let gradient = Gradient::new(
563                    vec![*accent, accent.brighten(0.36), Color::rgb(235, 244, 250)],
564                    32,
565                );
566                let config = EffectConfig::default()
567                    .with_duration(scene_ticks.max(8))
568                    .with_seed(700 + index as u64 * 97)
569                    .with_canvas_size(effect_w, effect_h)
570                    .with_gradient(gradient, GradientDirection::Diagonal);
571                let frames = Effect::with_config(*kind, text.clone(), config).frames();
572                Scene {
573                    title,
574                    subtitle,
575                    effect: *kind,
576                    accent: *accent,
577                    frames,
578                    quote: paragraph,
579                }
580            },
581        )
582        .collect()
583}
Source

pub fn with_canvas_size(self, width: usize, height: usize) -> Self

Examples found in repository?
examples/demo.rs (line 17)
9fn main() {
10    let args = Args::parse();
11    let kind = EffectKind::from_str(&args.effect).unwrap_or(EffectKind::Wipe);
12    let mut config = EffectConfig::default()
13        .with_duration(args.duration)
14        .with_seed(args.seed);
15
16    if let (Some(width), Some(height)) = (args.width, args.height) {
17        config = config.with_canvas_size(width.max(1), height.max(1));
18    }
19
20    let effect = Effect::with_config(kind, args.text, config);
21
22    let mut stdout = io::stdout();
23    for frame in effect.iter() {
24        write!(stdout, "\x1b[2J\x1b[H{}", frame.to_ansi_string()).unwrap();
25        stdout.flush().unwrap();
26        thread::sleep(Duration::from_millis((1000 / args.fps.max(1)) as u64));
27    }
28    writeln!(stdout).unwrap();
29}
More examples
Hide additional examples
examples/showcase.rs (line 379)
359fn build_panes(
360    text: &str,
361    layout: &Layout,
362    base_duration: usize,
363    theme: Theme,
364) -> Vec<PaneRuntime> {
365    EffectKind::all()
366        .iter()
367        .enumerate()
368        .map(|(index, kind)| {
369            let shape = pane_shape(*kind, index, layout);
370            let (pane_width, pane_height) = pane_size(layout, shape);
371            let inner_width = pane_width.saturating_sub(2).max(8);
372            let inner_height = pane_height.saturating_sub(2).max(3);
373            let snippet = snippet(text, index, inner_width, inner_height);
374            let accent = theme.accent(*kind, index);
375            let duration = base_duration + (index % 9) * 5;
376            let config = EffectConfig::default()
377                .with_duration(duration)
378                .with_seed(1009 + index as u64 * 97)
379                .with_canvas_size(inner_width, inner_height)
380                .with_gradient(
381                    effect_gradient(*kind, index, theme),
382                    gradient_direction(index),
383                );
384            let frames = Effect::with_config(*kind, snippet, config).frames();
385            PaneRuntime {
386                index,
387                kind: *kind,
388                frames,
389                offset: index * 13,
390                speed_numerator: 1 + (index % 4),
391                accent,
392                shape,
393            }
394        })
395        .collect()
396}
examples/loader_lab.rs (line 783)
727fn build_panes(effect_width: usize, effect_height: usize, focus_ticks: usize) -> Vec<Pane> {
728    let ops = [
729        ("DOWNLOAD", "tendon-atlas", "MB"),
730        ("UPLOAD", "field-manifest", "MB"),
731        ("SYNC", "sensor-mesh", "pkt"),
732        ("VERIFY", "leverage-map", "chk"),
733        ("STREAM", "gait-vectors", "vec"),
734        ("FORGE", "actuator-curve", "N"),
735        ("DECRYPT", "intent-bus", "blk"),
736        ("MIRROR", "joint-state", "msg"),
737        ("PACK", "motion-plan", "ops"),
738        ("RELAY", "balance-loop", "hz"),
739        ("CALIBRATE", "cable-stack", "mm"),
740        ("ARCHIVE", "field-log", "MB"),
741    ];
742    let effects = [
743        EffectKind::Matrix,
744        EffectKind::Burn,
745        EffectKind::Decrypt,
746        EffectKind::Thunderstorm,
747        EffectKind::LaserEtch,
748        EffectKind::Blackhole,
749        EffectKind::Rings,
750        EffectKind::Swarm,
751        EffectKind::Fireworks,
752        EffectKind::Slice,
753        EffectKind::Waves,
754        EffectKind::Wipe,
755    ];
756    let palette = [
757        Color::rgb(74, 255, 170),
758        Color::rgb(255, 118, 54),
759        Color::rgb(92, 204, 255),
760        Color::rgb(255, 216, 92),
761        Color::rgb(172, 130, 255),
762        Color::rgb(255, 112, 218),
763        Color::rgb(112, 236, 255),
764        Color::rgb(255, 178, 72),
765    ];
766    let speeds = [1, 2, 3, 4, 5, 7, 9, 11];
767
768    LoaderKind::all()
769        .iter()
770        .enumerate()
771        .map(|(index, kind)| {
772            let (op, noun, unit) = ops[index % ops.len()];
773            let effect_kind = effects[(index * 5 + 3) % effects.len()];
774            let accent = palette[index % palette.len()];
775            let label = format!("{} {}", op.to_ascii_lowercase(), noun);
776            let effect_text = format!("{} {}\n{}", op, kind.name(), noun).to_ascii_uppercase();
777            let effect = Effect::with_config(
778                effect_kind,
779                effect_text,
780                EffectConfig::default()
781                    .with_duration(focus_ticks)
782                    .with_seed(991 + index as u64 * 37)
783                    .with_canvas_size(effect_width, effect_height.max(1))
784                    .with_gradient(
785                        Gradient::new(
786                            vec![accent, accent.brighten(0.32), Color::rgb(230, 244, 250)],
787                            20,
788                        ),
789                        GradientDirection::Diagonal,
790                    ),
791            );
792            Pane {
793                index,
794                kind: *kind,
795                op,
796                noun,
797                label,
798                unit,
799                total: 128 + ((index as u64 * 97) % 2048),
800                speed: speeds[index % speeds.len()],
801                offset: index * 17,
802                accent,
803                effect_kind,
804                effect_frames: effect.frames(),
805            }
806        })
807        .collect()
808}
examples/story.rs (line 569)
477fn build_scenes(source: &str, layout: &Layout, scene_ticks: usize) -> Vec<Scene> {
478    let paragraphs = paragraphs(source);
479    let effect_w = layout.stage.w.saturating_sub(8).max(40);
480    let effect_h = layout.stage.h.saturating_sub(16).max(5).min(12);
481    let specs = [
482        (
483            "BOOT SEQUENCE",
484            "matrix rain resolves the mission",
485            EffectKind::Matrix,
486            Color::rgb(74, 255, 170),
487            0usize,
488        ),
489        (
490            "FORGE",
491            "burning the actuator constraints",
492            EffectKind::Burn,
493            Color::rgb(255, 118, 54),
494            3,
495        ),
496        (
497            "STORM SENSORS",
498            "signal and response in the weather",
499            EffectKind::Thunderstorm,
500            Color::rgb(96, 204, 255),
501            2,
502        ),
503        (
504            "LASER ETCH",
505            "leverage maps cut into the frame",
506            EffectKind::LaserEtch,
507            Color::rgb(255, 220, 92),
508            7,
509        ),
510        (
511            "GRAVITY WELL",
512            "weight and balance collapse into order",
513            EffectKind::Blackhole,
514            Color::rgb(164, 126, 255),
515            5,
516        ),
517        (
518            "ORBITAL BALANCE",
519            "rings of motion settle around intent",
520            EffectKind::Rings,
521            Color::rgb(110, 255, 224),
522            6,
523        ),
524        (
525            "SWARM CALIBRATION",
526            "many small forces become one gait",
527            EffectKind::Swarm,
528            Color::rgb(255, 112, 218),
529            4,
530        ),
531        (
532            "FIELD DEMO",
533            "fireworks over the completed machine",
534            EffectKind::Fireworks,
535            Color::rgb(255, 180, 72),
536            1,
537        ),
538    ];
539    specs
540        .iter()
541        .enumerate()
542        .map(
543            |(index, (title, subtitle, kind, accent, paragraph_index))| {
544                let paragraph = paragraphs
545                    .get(*paragraph_index)
546                    .or_else(|| paragraphs.get(index % paragraphs.len().max(1)))
547                    .cloned()
548                    .unwrap_or_else(|| source.to_string());
549                let extra = match kind {
550                    EffectKind::Matrix => "Data falls until it becomes purpose.",
551                    EffectKind::Burn => "The forge removes everything that does not serve motion.",
552                    EffectKind::Thunderstorm => "Noise becomes weather; weather becomes signal.",
553                    EffectKind::LaserEtch => "Leverage is written as geometry and timing.",
554                    EffectKind::Blackhole => {
555                        "Weight collapses into balance before it expands into gait."
556                    }
557                    EffectKind::Rings => "Joints orbit a center of intention.",
558                    EffectKind::Swarm => "Many corrections gather into one quiet step.",
559                    _ => "The machine disappears into the grace of the whole.",
560                };
561                let text = wrap_text(&format!("{}\n\n{}", paragraph, extra), effect_w);
562                let gradient = Gradient::new(
563                    vec![*accent, accent.brighten(0.36), Color::rgb(235, 244, 250)],
564                    32,
565                );
566                let config = EffectConfig::default()
567                    .with_duration(scene_ticks.max(8))
568                    .with_seed(700 + index as u64 * 97)
569                    .with_canvas_size(effect_w, effect_h)
570                    .with_gradient(gradient, GradientDirection::Diagonal);
571                let frames = Effect::with_config(*kind, text.clone(), config).frames();
572                Scene {
573                    title,
574                    subtitle,
575                    effect: *kind,
576                    accent: *accent,
577                    frames,
578                    quote: paragraph,
579                }
580            },
581        )
582        .collect()
583}

Trait Implementations§

Source§

impl Clone for EffectConfig

Source§

fn clone(&self) -> EffectConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for EffectConfig

Source§

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

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

impl Default for EffectConfig

Source§

fn default() -> Self

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

Auto Trait Implementations§

Blanket Implementations§

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> 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<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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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> 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.