tachyonfx/pattern/
sweep.rs

1#[cfg(feature = "dsl")]
2use compact_str::{format_compact, CompactString};
3use ratatui::layout::{Position, Rect};
4
5#[cfg(feature = "dsl")]
6use crate::dsl::DslFormat;
7use crate::{
8    fx::sliding_window_alpha::SlidingWindowAlpha,
9    pattern::{InstancedPattern, Pattern, PreparedPattern},
10    Motion,
11};
12
13#[derive(Clone, Debug, Copy, PartialEq)]
14pub struct SweepPattern {
15    direction: Motion,
16    gradient_span: u16,
17}
18
19impl SweepPattern {
20    pub fn left_to_right(gradient_span: u16) -> Self {
21        Self { direction: Motion::LeftToRight, gradient_span }
22    }
23
24    pub fn right_to_left(gradient_span: u16) -> Self {
25        Self { direction: Motion::RightToLeft, gradient_span }
26    }
27
28    pub fn up_to_down(gradient_span: u16) -> Self {
29        Self { direction: Motion::UpToDown, gradient_span }
30    }
31
32    pub fn down_to_up(gradient_span: u16) -> Self {
33        Self { direction: Motion::DownToUp, gradient_span }
34    }
35
36    /// Creates a sweep pattern with custom gradient span
37    ///
38    /// # Arguments
39    /// * `direction` - The direction of the slide
40    /// * `gradient_span` - The relative width of the gradient (0.1 = sharp, 0.5 = wide)
41    pub fn new(direction: Motion, gradient_span: u16) -> Self {
42        Self { direction, gradient_span }
43    }
44}
45
46impl Pattern for SweepPattern {
47    type Context = SlidingWindowAlpha;
48
49    fn for_frame(self, global_alpha: f32, area: Rect) -> PreparedPattern<SlidingWindowAlpha, Self>
50    where
51        Self: Sized,
52    {
53        // Apply the same timer flipping logic used by slide effects
54        // to compensate for the semantic mismatch in SlidingWindowAlpha
55        let adjusted_progress =
56            if self.direction.flips_timer() { 1.0 - global_alpha } else { global_alpha };
57
58        PreparedPattern {
59            pattern: self,
60            context: SlidingWindowAlpha::builder()
61                .direction(self.direction)
62                .progress(adjusted_progress)
63                .area(area)
64                .gradient_len(self.gradient_span)
65                .build(),
66        }
67    }
68}
69
70impl InstancedPattern for PreparedPattern<SlidingWindowAlpha, SweepPattern> {
71    fn map_alpha(&mut self, pos: Position) -> f32 {
72        self.context.alpha(pos)
73    }
74}
75
76#[cfg(feature = "dsl")]
77impl DslFormat for SweepPattern {
78    fn dsl_format(&self) -> CompactString {
79        match self.direction {
80            Motion::LeftToRight => {
81                format_compact!("SweepPattern::left_to_right({})", self.gradient_span)
82            },
83            Motion::RightToLeft => {
84                format_compact!("SweepPattern::right_to_left({})", self.gradient_span)
85            },
86            Motion::UpToDown => format_compact!("SweepPattern::up_to_down({})", self.gradient_span),
87            Motion::DownToUp => format_compact!("SweepPattern::down_to_up({})", self.gradient_span),
88        }
89    }
90}