Skip to main content

scal_core/
anim_builders.rs

1use std::ops::Range;
2
3use uuid::Uuid;
4
5use crate::{
6    AnimOP, CodeAnimationStyle, CodeHighlightAction, Color, Ease, IntoAnimOp, Sfx, Time,
7};
8
9/// Builder for an animation of adding code lines to the code block.
10/// ```
11///                code.add_lines()
12///                    .str(
13///                        r"
14///fn fib(n: u32) -> u32 {
15///    match n {
16///        0 => 0,
17///        1 => 1,
18///        _ => fib(n - 1) + fib(n - 2),
19///    }
20///}
21///                "
22///                    )
23///                    .over(5.s())
24///                    .style(CodeAnimationStyle::TypeWriter),
25/// ```
26pub struct CodeAddLinesBuilder {
27    pub(crate) uuid: Uuid,
28    pub(crate) text: String,
29    pub(crate) from_line: usize,
30    pub(crate) duration: Time,
31    pub(crate) ease: Ease,
32    pub(crate) style: CodeAnimationStyle,
33}
34
35impl CodeAddLinesBuilder {
36    #[must_use]
37    /// Value of the lines that you want to add
38    pub fn str(mut self, text: impl Into<String>) -> Self {
39        self.text = text.into();
40        self
41    }
42    #[must_use]
43    /// Line number that you want to start adding newlines from
44    pub const fn from_line(mut self, line: usize) -> Self {
45        self.from_line = line;
46        self
47    }
48    #[must_use]
49    /// Duration that you want to be animating adding newlines over
50    pub const fn over(mut self, duration: Time) -> Self {
51        self.duration = duration;
52        self
53    }
54    #[must_use]
55    /// Ease function that you want to use on this animation
56    pub const fn ease(mut self, ease: Ease) -> Self {
57        self.ease = ease;
58        self
59    }
60    #[must_use]
61    /// Style of the adding code animation
62    pub const fn style(mut self, style: CodeAnimationStyle) -> Self {
63        self.style = style;
64        self
65    }
66}
67
68impl From<CodeAddLinesBuilder> for AnimOP {
69    fn from(b: CodeAddLinesBuilder) -> Self {
70        Self::CodeAddLines(
71            b.uuid,
72            b.text,
73            b.from_line,
74            b.duration,
75            b.ease,
76            b.style,
77            None,
78        )
79    }
80}
81
82impl IntoAnimOp for CodeAddLinesBuilder {
83    fn into_anim_op(self) -> AnimOP {
84        self.into()
85    }
86}
87
88/// Builder for an animation of modifying a line in the code block.
89/// ```
90///                code.modify_line()
91///                    .str("New Line Contents")
92///                    .line(25)
93///                    .over(5.s())
94///                    .style(CodeAnimationStyle::TypeWriter),
95/// ```
96pub struct CodeModifyLineBuilder {
97    pub(crate) uuid: Uuid,
98    pub(crate) line: u32,
99    pub(crate) text: String,
100    pub(crate) duration: Time,
101    pub(crate) ease: Ease,
102    pub(crate) style: CodeAnimationStyle,
103}
104
105impl CodeModifyLineBuilder {
106    #[must_use]
107    /// New value of the line that you want to modify
108    pub fn str(mut self, text: impl Into<String>) -> Self {
109        self.text = text.into();
110        self
111    }
112
113    #[must_use]
114    /// Line number that you want to modify
115    pub const fn line(mut self, line: u32) -> Self {
116        self.line = line;
117        self
118    }
119    #[must_use]
120    /// Duration that you want to be animating the modification over
121    pub const fn over(mut self, duration: Time) -> Self {
122        self.duration = duration;
123        self
124    }
125    #[must_use]
126    /// Ease function that you want to use on this animation
127    pub const fn ease(mut self, ease: Ease) -> Self {
128        self.ease = ease;
129        self
130    }
131    #[must_use]
132    /// Style of the code animation
133    pub const fn style(mut self, style: CodeAnimationStyle) -> Self {
134        self.style = style;
135        self
136    }
137}
138
139impl From<CodeModifyLineBuilder> for AnimOP {
140    fn from(b: CodeModifyLineBuilder) -> Self {
141        Self::CodeModifyLine(b.uuid, b.line, b.text, b.duration, b.ease, b.style, None)
142    }
143}
144
145impl IntoAnimOp for CodeModifyLineBuilder {
146    fn into_anim_op(self) -> AnimOP {
147        self.into()
148    }
149}
150
151/// Builder for an animation of removing lines from a code block.
152/// ```
153///                code.remove_lines()
154///                    .range(0..25)
155///                    .over(5.s())
156///                    .style(CodeAnimationStyle::TypeWriter),
157/// ```
158pub struct CodeRemoveLinesBuilder {
159    pub(crate) uuid: Uuid,
160    pub(crate) range: Range<u32>,
161    pub(crate) duration: Time,
162    pub(crate) ease: Ease,
163    pub(crate) style: CodeAnimationStyle,
164}
165
166impl CodeRemoveLinesBuilder {
167    #[must_use]
168    /// Range of lines that you want to remove
169    pub const fn range(mut self, range: Range<u32>) -> Self {
170        self.range = range;
171        self
172    }
173    #[must_use]
174    /// Duration that you want to be animating the removal over
175    pub const fn over(mut self, duration: Time) -> Self {
176        self.duration = duration;
177        self
178    }
179    #[must_use]
180    /// Ease function that you want to use on this animation
181    pub const fn ease(mut self, ease: Ease) -> Self {
182        self.ease = ease;
183        self
184    }
185    #[must_use]
186    /// Style of the code animation
187    pub const fn style(mut self, style: CodeAnimationStyle) -> Self {
188        self.style = style;
189        self
190    }
191}
192
193impl From<CodeRemoveLinesBuilder> for AnimOP {
194    fn from(b: CodeRemoveLinesBuilder) -> Self {
195        Self::CodeRemoveLines(b.uuid, b.range, b.duration, b.ease, b.style, None)
196    }
197}
198
199impl IntoAnimOp for CodeRemoveLinesBuilder {
200    fn into_anim_op(self) -> AnimOP {
201        self.into()
202    }
203}
204
205
206
207/// Builder for an animation of highlighting code by line range or regex pattern.
208/// ```
209///                code.highlight()
210///                    .lines(3..6)
211///                    .color(Color::new(1.0, 1.0, 0.0, 0.3))
212///                    .over(1.s())
213///                    .ease(Ease::InOutCubic),
214/// ```
215///
216/// Or with a regex pattern:
217/// ```
218///                code.highlight()
219///                    .pattern(r"fn \w+\(")
220///                    .color(Color::new(0.0, 1.0, 0.0, 0.3))
221///                    .over(1.s()),
222/// ```
223pub struct CodeHighlightBuilder {
224    pub(crate) uuid: Uuid,
225    pub(crate) ranges: Vec<Range<usize>>,
226    pub(crate) regex: Option<String>,
227    pub(crate) color: Color,
228    pub(crate) duration: Time,
229    pub(crate) ease: Ease,
230}
231
232impl CodeHighlightBuilder {
233    #[must_use]
234    /// Highlight a range of lines (can be called multiple times for multiple ranges)
235    pub fn lines(mut self, range: Range<usize>) -> Self {
236        self.ranges.push(range);
237        self
238    }
239    #[must_use]
240    /// Highlight lines matching a regex pattern
241    pub fn pattern(mut self, regex: impl Into<String>) -> Self {
242        self.regex = Some(regex.into());
243        self
244    }
245    #[must_use]
246    /// Color of the highlight overlay
247    pub fn color(mut self, color: Color) -> Self {
248        self.color = color;
249        self
250    }
251    #[must_use]
252    /// Duration of the highlight animation
253    pub fn over(mut self, duration: Time) -> Self {
254        self.duration = duration;
255        self
256    }
257    #[must_use]
258    /// Ease function for the highlight animation
259    pub fn ease(mut self, ease: Ease) -> Self {
260        self.ease = ease;
261        self
262    }
263}
264
265impl From<CodeHighlightBuilder> for AnimOP {
266    fn from(b: CodeHighlightBuilder) -> Self {
267        let action = if let Some(regex) = b.regex {
268            CodeHighlightAction::Pattern {
269                regex,
270                color: b.color,
271                duration: b.duration,
272                curve: b.ease,
273            }
274        } else {
275            CodeHighlightAction::Lines {
276                ranges: b.ranges,
277                color: b.color,
278                duration: b.duration,
279                curve: b.ease,
280            }
281        };
282        Self::CodeHighlight(b.uuid, action, None)
283    }
284}
285
286impl IntoAnimOp for CodeHighlightBuilder {
287    fn into_anim_op(self) -> AnimOP {
288        self.into()
289    }
290}
291
292/// Builder for an animation of playing a sound effect.
293/// ```
294///                sfx()
295///                    .path("./click.mp3")
296///                    .play()
297///                    .after(0.5.s()),
298/// ```
299pub struct PlaySoundBuilder {
300    pub(crate) sfx: Sfx,
301    pub(crate) delay: Time,
302}
303
304impl PlaySoundBuilder {
305    #[must_use]
306    /// Delay before the sound starts playing, relative to when the animation is triggered
307    pub fn after(mut self, delay: Time) -> AnimOP {
308        self.delay = delay;
309        self.into()
310    }
311    #[must_use]
312    /// Delay before the sound starts playing
313    pub fn delay(mut self, delay: Time) -> AnimOP {
314        self.delay = delay;
315        self.into()
316    }
317}
318
319impl From<PlaySoundBuilder> for AnimOP {
320    fn from(b: PlaySoundBuilder) -> AnimOP {
321        AnimOP::PlaySound(b.sfx, b.delay, None)
322    }
323}
324
325impl IntoAnimOp for PlaySoundBuilder {
326    fn into_anim_op(self) -> AnimOP {
327        self.into()
328    }
329}