Skip to content

Commit f36aa72

Browse files
committed
[bevy_text] Add offset to TextSection
This makes it possible to shift text (such as for animations), while still laying it out with ab_glyph.
1 parent 19d078c commit f36aa72

File tree

8 files changed

+51
-5
lines changed

8 files changed

+51
-5
lines changed

crates/bevy_text/src/pipeline.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ impl TextPipeline {
5656
y_axis_orientation: YAxisOrientation,
5757
) -> Result<TextLayoutInfo, TextError> {
5858
let mut scaled_fonts = Vec::with_capacity(sections.len());
59+
let glyph_offsets: Vec<_> = sections
60+
.iter()
61+
.flat_map(|section| {
62+
std::iter::repeat(section.offset).take(section.value.chars().count())
63+
})
64+
.collect();
5965
let sections = sections
6066
.iter()
6167
.map(|section| {
@@ -77,9 +83,17 @@ impl TextPipeline {
7783
})
7884
.collect::<Result<Vec<_>, _>>()?;
7985

80-
let section_glyphs =
81-
self.brush
82-
.compute_glyphs(&sections, bounds, text_alignment, linebreak_behavior)?;
86+
let section_glyphs: Vec<_> = self
87+
.brush
88+
.compute_glyphs(&sections, bounds, text_alignment, linebreak_behavior)?
89+
.into_iter()
90+
.zip(glyph_offsets)
91+
.map(|(mut g, offset)| {
92+
g.glyph.position.x += offset.x;
93+
g.glyph.position.y += offset.y;
94+
g
95+
})
96+
.collect();
8397

8498
if section_glyphs.is_empty() {
8599
return Ok(TextLayoutInfo::default());

crates/bevy_text/src/text.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use bevy_asset::Handle;
22
use bevy_color::Color;
33
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
4+
use bevy_math::Vec2;
45
use bevy_reflect::prelude::*;
56
use bevy_utils::default;
67
use serde::{Deserialize, Serialize};
@@ -106,10 +107,21 @@ impl Text {
106107
}
107108
}
108109

109-
#[derive(Debug, Default, Clone, Reflect)]
110+
#[derive(Debug, Clone, Reflect)]
110111
pub struct TextSection {
111112
pub value: String,
112113
pub style: TextStyle,
114+
pub offset: Vec2,
115+
}
116+
117+
impl Default for TextSection {
118+
fn default() -> Self {
119+
Self {
120+
value: Default::default(),
121+
style: Default::default(),
122+
offset: Vec2::new(0., 0.),
123+
}
124+
}
113125
}
114126

115127
impl TextSection {
@@ -118,14 +130,18 @@ impl TextSection {
118130
Self {
119131
value: value.into(),
120132
style,
133+
134+
..Default::default()
121135
}
122136
}
123137

124138
/// Create an empty [`TextSection`] from a style. Useful when the value will be set dynamically.
125139
pub const fn from_style(style: TextStyle) -> Self {
126140
Self {
127-
value: String::new(),
128141
style,
142+
143+
value: String::new(),
144+
offset: Vec2::new(0., 0.),
129145
}
130146
}
131147
}

examples/asset/multi_asset_sync.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ fn setup_ui(mut commands: Commands) {
189189
color: Color::BLACK,
190190
..Default::default()
191191
},
192+
..Default::default()
192193
}],
193194
justify: JustifyText::Right,
194195
..Default::default()

examples/input/text_input.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
4343
font: font.clone_weak(),
4444
..default()
4545
},
46+
..default()
4647
},
4748
TextSection {
4849
value: "false\n".to_string(),
@@ -51,13 +52,15 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
5152
font_size: 30.0,
5253
..default()
5354
},
55+
..default()
5456
},
5557
TextSection {
5658
value: "IME Active: ".to_string(),
5759
style: TextStyle {
5860
font: font.clone_weak(),
5961
..default()
6062
},
63+
..default()
6164
},
6265
TextSection {
6366
value: "false\n".to_string(),
@@ -66,6 +69,7 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
6669
font_size: 30.0,
6770
..default()
6871
},
72+
..default()
6973
},
7074
TextSection {
7175
value: "click to toggle IME, press return to start a new line\n\n".to_string(),
@@ -74,6 +78,7 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
7478
font_size: 18.0,
7579
..default()
7680
},
81+
..default()
7782
},
7883
TextSection {
7984
value: "".to_string(),
@@ -82,6 +87,7 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
8287
font_size: 25.0,
8388
..default()
8489
},
90+
..default()
8591
},
8692
])
8793
.with_style(Style {

examples/stress_tests/many_glyphs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ fn setup(mut commands: Commands) {
5252
font_size: 4.,
5353
..default()
5454
},
55+
..default(),
5556
}],
5657
justify: JustifyText::Left,
5758
linebreak_behavior: BreakLineOn::AnyCharacter,

examples/stress_tests/text_pipeline.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
4949
font_size: (4 + i % 10) as f32,
5050
color: BLUE.into(),
5151
},
52+
..default()
5253
},
5354
TextSection {
5455
value: "pipeline".repeat(i),
@@ -57,6 +58,7 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
5758
font_size: (4 + i % 11) as f32,
5859
color: YELLOW.into(),
5960
},
61+
..default()
6062
},
6163
]
6264
})

examples/tools/gamepad_viewer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,17 @@ fn setup_sticks(
321321
TextSection {
322322
value: format!("{:.3}", 0.),
323323
style: style.clone(),
324+
..default()
324325
},
325326
TextSection {
326327
value: ", ".to_string(),
327328
style: style.clone(),
329+
..default()
328330
},
329331
TextSection {
330332
value: format!("{:.3}", 0.),
331333
style,
334+
..default()
332335
},
333336
]),
334337
text_anchor: Anchor::BottomCenter,
@@ -424,10 +427,12 @@ fn setup_connected(mut commands: Commands) {
424427
TextSection {
425428
value: "Connected Gamepads:\n".to_string(),
426429
style: text_style.clone(),
430+
..default()
427431
},
428432
TextSection {
429433
value: "None".to_string(),
430434
style: text_style,
435+
..default()
431436
},
432437
]),
433438
style: Style {

examples/ui/text_wrap_debug.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
124124
sections: vec![TextSection {
125125
value: message.clone(),
126126
style: text_style.clone(),
127+
..Default::default()
127128
}],
128129
justify: JustifyText::Left,
129130
linebreak_behavior,

0 commit comments

Comments
 (0)