Skip to content

Commit ca5ab3d

Browse files
ickshonpeItsDoot
authored andcommitted
UI text layout example (bevyengine#7359)
## Objective An example that demonstrates how the `AlignItems` and `JustifyContent` properties can be composed to layout text. <img width="654" alt="text_layout_example" src="https://user-images.githubusercontent.com/27962798/215116345-daa8ef60-634b-40c6-9b6d-356de3af620c.png">
1 parent 1b1dc15 commit ca5ab3d

File tree

3 files changed

+196
-0
lines changed

3 files changed

+196
-0
lines changed

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,17 @@ description = "An example for debugging text layout"
15261526
category = "UI (User Interface)"
15271527
wasm = true
15281528

1529+
[[example]]
1530+
name = "text_layout"
1531+
path = "examples/ui/text_layout.rs"
1532+
1533+
[package.metadata.example.text_layout]
1534+
name = "Text Layout"
1535+
description = "Demonstrates how the AlignItems and JustifyContent properties can be composed to layout text"
1536+
category = "UI (User Interface)"
1537+
wasm = false
1538+
1539+
15291540
[[example]]
15301541
name = "transparency_ui"
15311542
path = "examples/ui/transparency_ui.rs"

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ Example | Description
319319
[Relative Cursor Position](../examples/ui/relative_cursor_position.rs) | Showcases the RelativeCursorPosition component
320320
[Text](../examples/ui/text.rs) | Illustrates creating and updating text
321321
[Text Debug](../examples/ui/text_debug.rs) | An example for debugging text layout
322+
[Text Layout](../examples/ui/text_layout.rs) | Demonstrates how the AlignItems and JustifyContent properties can be composed to layout text
322323
[Transparency UI](../examples/ui/transparency_ui.rs) | Demonstrates transparency for UI
323324
[UI](../examples/ui/ui.rs) | Illustrates various features of Bevy UI
324325
[UI Scaling](../examples/ui/ui_scaling.rs) | Illustrates how to scale the UI

examples/ui/text_layout.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
//! Demonstrates how the `AlignItems` and `JustifyContent` properties can be composed to layout text.
2+
use bevy::prelude::*;
3+
4+
const ALIGN_ITEMS_COLOR: Color = Color::rgb(1., 0.066, 0.349);
5+
const JUSTIFY_CONTENT_COLOR: Color = Color::rgb(0.102, 0.522, 1.);
6+
const MARGIN: Val = Val::Px(5.);
7+
8+
fn main() {
9+
App::new()
10+
.add_plugins(DefaultPlugins.set(WindowPlugin {
11+
primary_window: Some(Window {
12+
resolution: [870., 1066.].into(),
13+
title: "Bevy Text Layout Example".to_string(),
14+
..Default::default()
15+
}),
16+
..Default::default()
17+
}))
18+
.add_startup_system(spawn_layout)
19+
.run();
20+
}
21+
22+
fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
23+
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
24+
commands.spawn(Camera2dBundle::default());
25+
commands
26+
.spawn(NodeBundle {
27+
style: Style {
28+
// fill the entire window
29+
size: Size::new(Val::Percent(100.0), Val::Percent(100.0)),
30+
flex_direction: FlexDirection::Column,
31+
align_items: AlignItems::Center,
32+
..Default::default()
33+
},
34+
background_color: BackgroundColor(Color::BLACK),
35+
..Default::default()
36+
})
37+
.with_children(|builder| {
38+
// spawn the key
39+
builder
40+
.spawn(NodeBundle {
41+
style: Style {
42+
flex_direction: FlexDirection::Row,
43+
margin: UiRect::top(MARGIN),
44+
..Default::default()
45+
},
46+
..Default::default()
47+
})
48+
.with_children(|builder| {
49+
spawn_nested_text_bundle(
50+
builder,
51+
font.clone(),
52+
ALIGN_ITEMS_COLOR,
53+
UiRect::right(MARGIN),
54+
"AlignItems",
55+
);
56+
spawn_nested_text_bundle(
57+
builder,
58+
font.clone(),
59+
JUSTIFY_CONTENT_COLOR,
60+
UiRect::default(),
61+
"JustifyContent",
62+
);
63+
});
64+
65+
builder
66+
.spawn(NodeBundle {
67+
style: Style {
68+
min_size: Size::new(Val::Px(850.), Val::Px(1020.)),
69+
flex_direction: FlexDirection::Column,
70+
..Default::default()
71+
},
72+
..Default::default()
73+
})
74+
.with_children(|builder| {
75+
// spawn one child node for each combination of `AlignItems` and `JustifyContent`
76+
let justifications = [
77+
JustifyContent::FlexStart,
78+
JustifyContent::Center,
79+
JustifyContent::FlexEnd,
80+
JustifyContent::SpaceEvenly,
81+
JustifyContent::SpaceAround,
82+
JustifyContent::SpaceBetween,
83+
];
84+
let alignments = [
85+
AlignItems::Baseline,
86+
AlignItems::FlexStart,
87+
AlignItems::Center,
88+
AlignItems::FlexEnd,
89+
AlignItems::Stretch,
90+
];
91+
for justify_content in justifications {
92+
builder
93+
.spawn(NodeBundle {
94+
style: Style {
95+
flex_direction: FlexDirection::Row,
96+
..Default::default()
97+
},
98+
..Default::default()
99+
})
100+
.with_children(|builder| {
101+
for align_items in alignments {
102+
spawn_child_node(
103+
builder,
104+
font.clone(),
105+
align_items,
106+
justify_content,
107+
);
108+
}
109+
});
110+
}
111+
});
112+
});
113+
}
114+
115+
fn spawn_child_node(
116+
builder: &mut ChildBuilder,
117+
font: Handle<Font>,
118+
align_items: AlignItems,
119+
justify_content: JustifyContent,
120+
) {
121+
builder
122+
.spawn(NodeBundle {
123+
style: Style {
124+
flex_direction: FlexDirection::Column,
125+
align_items,
126+
justify_content,
127+
size: Size::new(Val::Px(160.), Val::Px(160.)),
128+
margin: UiRect::all(MARGIN),
129+
..Default::default()
130+
},
131+
background_color: BackgroundColor(Color::DARK_GRAY),
132+
..Default::default()
133+
})
134+
.with_children(|builder| {
135+
let labels = [
136+
(format!("{align_items:?}"), ALIGN_ITEMS_COLOR, 0.),
137+
(format!("{justify_content:?}"), JUSTIFY_CONTENT_COLOR, 3.),
138+
];
139+
for (text, color, top_margin) in labels {
140+
// We nest the text within a parent node because margins and padding can't be directly applied to text nodes currently.
141+
spawn_nested_text_bundle(
142+
builder,
143+
font.clone(),
144+
color,
145+
UiRect::top(Val::Px(top_margin)),
146+
&text,
147+
);
148+
}
149+
});
150+
}
151+
152+
fn spawn_nested_text_bundle(
153+
builder: &mut ChildBuilder,
154+
font: Handle<Font>,
155+
background_color: Color,
156+
margin: UiRect,
157+
text: &str,
158+
) {
159+
builder
160+
.spawn(NodeBundle {
161+
style: Style {
162+
margin,
163+
padding: UiRect {
164+
top: Val::Px(1.),
165+
left: Val::Px(5.),
166+
right: Val::Px(5.),
167+
bottom: Val::Px(1.),
168+
},
169+
..Default::default()
170+
},
171+
background_color: BackgroundColor(background_color),
172+
..Default::default()
173+
})
174+
.with_children(|builder| {
175+
builder.spawn(TextBundle::from_section(
176+
text,
177+
TextStyle {
178+
font,
179+
font_size: 24.0,
180+
color: Color::BLACK,
181+
},
182+
));
183+
});
184+
}

0 commit comments

Comments
 (0)