1use bevy::{
9 color::palettes::css::*,
10 math::ops,
11 prelude::*,
12 sprite::Anchor,
13 text::{FontSmoothing, LineBreak, TextBounds},
14};
15
16fn main() {
17 App::new()
18 .add_plugins(DefaultPlugins)
19 .add_systems(Startup, setup)
20 .add_systems(
21 Update,
22 (animate_translation, animate_rotation, animate_scale),
23 )
24 .run();
25}
26
27#[derive(Component)]
28struct AnimateTranslation;
29
30#[derive(Component)]
31struct AnimateRotation;
32
33#[derive(Component)]
34struct AnimateScale;
35
36fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
37 let font = asset_server.load("fonts/FiraSans-Bold.ttf");
38 let text_font = TextFont {
39 font: font.clone(),
40 font_size: 50.0,
41 ..default()
42 };
43 let text_justification = JustifyText::Center;
44 commands.spawn(Camera2d);
45 commands.spawn((
47 Text2d::new("translation"),
48 text_font.clone(),
49 TextLayout::new_with_justify(text_justification),
50 AnimateTranslation,
51 ));
52 commands.spawn((
54 Text2d::new("rotation"),
55 text_font.clone(),
56 TextLayout::new_with_justify(text_justification),
57 AnimateRotation,
58 ));
59 commands.spawn((
61 Text2d::new("scale"),
62 text_font,
63 TextLayout::new_with_justify(text_justification),
64 Transform::from_translation(Vec3::new(400.0, 0.0, 0.0)),
65 AnimateScale,
66 ));
67 let slightly_smaller_text_font = TextFont {
69 font,
70 font_size: 35.0,
71 ..default()
72 };
73 let box_size = Vec2::new(300.0, 200.0);
74 let box_position = Vec2::new(0.0, -250.0);
75 commands
76 .spawn((
77 Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), box_size),
78 Transform::from_translation(box_position.extend(0.0)),
79 ))
80 .with_children(|builder| {
81 builder.spawn((
82 Text2d::new("this text wraps in the box\n(Unicode linebreaks)"),
83 slightly_smaller_text_font.clone(),
84 TextLayout::new(JustifyText::Left, LineBreak::WordBoundary),
85 TextBounds::from(box_size),
87 Transform::from_translation(Vec3::Z),
89 ));
90 });
91
92 let other_box_size = Vec2::new(300.0, 200.0);
93 let other_box_position = Vec2::new(320.0, -250.0);
94 commands
95 .spawn((
96 Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), other_box_size),
97 Transform::from_translation(other_box_position.extend(0.0)),
98 ))
99 .with_children(|builder| {
100 builder.spawn((
101 Text2d::new("this text wraps in the box\n(AnyCharacter linebreaks)"),
102 slightly_smaller_text_font.clone(),
103 TextLayout::new(JustifyText::Left, LineBreak::AnyCharacter),
104 TextBounds::from(other_box_size),
106 Transform::from_translation(Vec3::Z),
108 ));
109 });
110
111 commands.spawn((
113 Text2d::new("This text has\nFontSmoothing::None\nAnd JustifyText::Center"),
114 slightly_smaller_text_font
115 .clone()
116 .with_font_smoothing(FontSmoothing::None),
117 TextLayout::new_with_justify(JustifyText::Center),
118 Transform::from_translation(Vec3::new(-400.0, -250.0, 0.0)),
119 ));
120
121 commands
122 .spawn((
123 Sprite {
124 color: Color::Srgba(LIGHT_CYAN),
125 custom_size: Some(Vec2::new(10., 10.)),
126 ..Default::default()
127 },
128 Transform::from_translation(250. * Vec3::Y),
129 ))
130 .with_children(|commands| {
131 for (text_anchor, color) in [
132 (Anchor::TopLeft, Color::Srgba(LIGHT_SALMON)),
133 (Anchor::TopRight, Color::Srgba(LIGHT_GREEN)),
134 (Anchor::BottomRight, Color::Srgba(LIGHT_BLUE)),
135 (Anchor::BottomLeft, Color::Srgba(LIGHT_YELLOW)),
136 ] {
137 commands
138 .spawn((
139 Text2d::new(" Anchor".to_string()),
140 slightly_smaller_text_font.clone(),
141 text_anchor,
142 ))
143 .with_child((
144 TextSpan("::".to_string()),
145 slightly_smaller_text_font.clone(),
146 TextColor(LIGHT_GREY.into()),
147 ))
148 .with_child((
149 TextSpan(format!("{text_anchor:?} ")),
150 slightly_smaller_text_font.clone(),
151 TextColor(color),
152 ));
153 }
154 });
155}
156
157fn animate_translation(
158 time: Res<Time>,
159 mut query: Query<&mut Transform, (With<Text2d>, With<AnimateTranslation>)>,
160) {
161 for mut transform in &mut query {
162 transform.translation.x = 100.0 * ops::sin(time.elapsed_secs()) - 400.0;
163 transform.translation.y = 100.0 * ops::cos(time.elapsed_secs());
164 }
165}
166
167fn animate_rotation(
168 time: Res<Time>,
169 mut query: Query<&mut Transform, (With<Text2d>, With<AnimateRotation>)>,
170) {
171 for mut transform in &mut query {
172 transform.rotation = Quat::from_rotation_z(ops::cos(time.elapsed_secs()));
173 }
174}
175
176fn animate_scale(
177 time: Res<Time>,
178 mut query: Query<&mut Transform, (With<Text2d>, With<AnimateScale>)>,
179) {
180 for mut transform in &mut query {
183 let scale = (ops::sin(time.elapsed_secs()) + 1.1) * 2.0;
184 transform.scale.x = scale;
185 transform.scale.y = scale;
186 }
187}