1 | use std::f64::consts::PI;
|
2 |
|
3 | use glam::{DVec3, dvec2, dvec3};
|
4 | use ranim::{
|
5 | animation::{creation::WritingAnimSchedule, transform::GroupTransformAnimSchedule},
|
6 | color::palettes::manim,
|
7 | components::{Anchor, ScaleHint},
|
8 | items::{
|
9 | group::Group,
|
10 | vitem::{Polygon, Rectangle, Square, VItem},
|
11 | },
|
12 | prelude::*,
|
13 | timeline::TimeMark,
|
14 | typst_svg,
|
15 | utils::rate_functions::{linear, smooth},
|
16 | };
|
17 |
|
18 | fn build_logo(logo_width: f64) -> [VItem; 6] {
|
19 | let mut red_bg_rect = Rectangle(logo_width / 2.0, logo_width).build();
|
20 | red_bg_rect
|
21 | .set_color(manim::RED_C.with_alpha(0.5))
|
22 | .put_center_on(dvec3(-logo_width / 4.0, 0.0, 0.0));
|
23 | let mut red_rect = Rectangle(logo_width / 4.0, logo_width).build();
|
24 | red_rect
|
25 | .set_color(manim::RED_C)
|
26 | .put_anchor_on(Anchor::edge(1, 0, 0), dvec3(-logo_width / 4.0, 0.0, 0.0));
|
27 |
|
28 | let mut green_bg_sq = Square(logo_width / 2.0).build();
|
29 | green_bg_sq
|
30 | .set_color(manim::GREEN_C.with_alpha(0.5))
|
31 | .put_center_on(dvec3(logo_width / 4.0, logo_width / 4.0, 0.0));
|
32 | let mut green_triangle = Polygon(vec![
|
33 | dvec3(0.0, logo_width / 2.0, 0.0),
|
34 | dvec3(logo_width / 2.0, logo_width / 2.0, 0.0),
|
35 | dvec3(logo_width / 2.0, 0.0, 0.0),
|
36 | ])
|
37 | .build(); |
38 | green_triangle.set_color(manim::GREEN_C);
|
39 |
|
40 | let mut blue_bg_sq = Square(logo_width / 2.0).build();
|
41 | blue_bg_sq
|
42 | .set_color(manim::BLUE_C.with_alpha(0.5))
|
43 | .put_center_on(dvec3(logo_width / 4.0, -logo_width / 4.0, 0.0));
|
44 | let mut blue_triangle = green_triangle.clone();
|
45 | blue_triangle
|
46 | .set_color(manim::BLUE_C)
|
47 | .rotate(PI, DVec3::Z)
|
48 | .shift(DVec3::NEG_Y * logo_width / 2.0); |
49 |
|
50 | [
|
51 | red_bg_rect,
|
52 | red_rect,
|
53 | green_bg_sq,
|
54 | green_triangle,
|
55 | blue_bg_sq,
|
56 | blue_triangle,
|
57 | ]
|
58 | }
|
59 | #[scene]
|
60 | struct RanimLogoScene;
|
61 |
|
62 | impl TimelineConstructor for RanimLogoScene {
|
63 | fn construct<'t: 'r, 'r>(
|
64 | self,
|
65 | timeline: &'t RanimTimeline,
|
66 | _camera: &'r mut Rabject<'t, CameraFrame>,
|
67 | ) {
|
68 | let frame_size = dvec2(8.0 * 16.0 / 9.0, 8.0);
|
69 | let logo_width = frame_size.y * 0.618;
|
70 |
|
71 | let mut logo = build_logo(logo_width)
|
72 | .map(|item| timeline.insert(item))
|
73 | .into_iter()
|
74 | .collect::<Group<_>>();
|
75 |
|
76 | timeline
|
77 | .play(logo.lagged_anim(0.0, |item| {
|
78 | item.write().with_duration(3.0).with_rate_func(smooth)
|
79 | }))
|
80 | .sync();
|
81 |
|
82 | let gap_ratio = 1.0 / 60.0;
|
83 | let gap = logo_width * gap_ratio;
|
84 | let scale = (logo_width - gap * 2.0) / logo_width;
|
85 | let scale = [
|
86 | dvec3(scale, 1.0, 1.0),
|
87 | dvec3(scale, scale, 1.0),
|
88 | dvec3(scale, scale, 1.0),
|
89 | ];
|
90 | let anchor = [
|
91 | Anchor::edge(-1, 0, 0),
|
92 | Anchor::edge(1, 1, 0),
|
93 | Anchor::edge(1, -1, 0),
|
94 | ];
|
95 | logo.chunks_mut(2)
|
96 | .zip(scale.into_iter().zip(anchor))
|
97 | .for_each(|(chunk, (scale, anchor))| {
|
98 | timeline.play(
|
99 | chunk
|
100 | .transform(|data| {
|
101 | data.scale_by_anchor(scale, anchor)
|
102 | .scale_by_anchor(dvec3(0.9, 0.9, 1.0), Anchor::origin())
|
103 | .shift(dvec3(0.0, 1.3, 0.0));
|
104 | })
|
105 | .with_rate_func(smooth)
|
106 | .apply(),
|
107 | );
|
108 | });
|
109 |
|
110 | let mut ranim_text = Group::<VItem>::from_svg(typst_svg!(
|
111 | r#"
|
112 | #align(center)[
|
113 | #text(10pt, font: "LXGW Bright")[Ranim]
|
114 | ]"#
|
115 | ));
|
116 | ranim_text
|
117 | .scale_to(ScaleHint::PorportionalHeight(1.0))
|
118 | .put_center_on(DVec3::NEG_Y * 2.5);
|
119 | let mut ranim_text = ranim_text
|
120 | .into_iter()
|
121 | .map(|item| timeline.insert(item))
|
122 | .collect::<Group<_>>();
|
123 | timeline.play(
|
124 | ranim_text
|
125 | .lagged_anim(0.2, |item| item.write())
|
126 | .with_duration(2.0)
|
127 | .with_rate_func(linear),
|
128 | );
|
129 | timeline.sync();
|
130 |
|
131 | timeline.insert_time_mark(
|
132 | timeline.duration_secs(),
|
133 | TimeMark::Capture("preview.png".to_string()),
|
134 | );
|
135 | timeline.forward(1.0);
|
136 |
|
137 | let mut all = logo.into_iter().chain(ranim_text).collect::<Group<_>>();
|
138 | timeline.play(all.lagged_anim(0.0, |item| {
|
139 | item.unwrite().with_duration(3.0).with_rate_func(smooth)
|
140 | }));
|
141 | }
|
142 | }
|
143 |
|
144 | fn main() {
|
145 | render_scene(RanimLogoScene, &AppOptions::default());
|
146 | }
|
147 |
|