mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
parent
2b0ee24a5d
commit
d4ab2f4d47
3 changed files with 60 additions and 22 deletions
|
@ -39,15 +39,16 @@ impl FontAtlas {
|
|||
texture_atlases: &mut Assets<TextureAtlas>,
|
||||
character: char,
|
||||
texture: &Texture,
|
||||
) {
|
||||
) -> bool {
|
||||
let texture_atlas = texture_atlases.get_mut(&self.texture_atlas).unwrap();
|
||||
if let Some(index) =
|
||||
self.dynamic_texture_atlas_builder
|
||||
.add_texture(texture_atlas, textures, texture)
|
||||
{
|
||||
self.glyph_to_index.insert(character, index);
|
||||
true
|
||||
} else {
|
||||
panic!("ran out of space in font atlas");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ type FontSizeKey = FloatOrd;
|
|||
#[derive(Default)]
|
||||
pub struct FontAtlasSet {
|
||||
font: Handle<Font>,
|
||||
font_atlases: HashMap<FontSizeKey, FontAtlas>,
|
||||
font_atlases: HashMap<FontSizeKey, Vec<FontAtlas>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -30,7 +30,7 @@ impl FontAtlasSet {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&FontSizeKey, &FontAtlas)> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&FontSizeKey, &Vec<FontAtlas>)> {
|
||||
self.font_atlases.iter()
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,9 @@ impl FontAtlasSet {
|
|||
self.font_atlases
|
||||
.get(&FloatOrd(font_size))
|
||||
.map_or(false, |font_atlas| {
|
||||
font_atlas.get_char_index(character).is_some()
|
||||
font_atlas
|
||||
.iter()
|
||||
.any(|atlas| atlas.get_char_index(character).is_some())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -52,10 +54,16 @@ impl FontAtlasSet {
|
|||
) -> f32 {
|
||||
let font = fonts.get(&self.font).unwrap();
|
||||
let scaled_font = ab_glyph::Font::as_scaled(&font.font, font_size);
|
||||
let font_atlas = self
|
||||
let font_atlases = self
|
||||
.font_atlases
|
||||
.entry(FloatOrd(font_size))
|
||||
.or_insert_with(|| FontAtlas::new(textures, texture_atlases, Vec2::new(512.0, 512.0)));
|
||||
.or_insert_with(|| {
|
||||
vec![FontAtlas::new(
|
||||
textures,
|
||||
texture_atlases,
|
||||
Vec2::new(512.0, 512.0),
|
||||
)]
|
||||
});
|
||||
|
||||
let mut last_glyph: Option<Glyph> = None;
|
||||
let mut width = 0.0;
|
||||
|
@ -67,10 +75,30 @@ impl FontAtlasSet {
|
|||
if let Some(last_glyph) = last_glyph.take() {
|
||||
width += scaled_font.kern(last_glyph.id, glyph.id);
|
||||
}
|
||||
if font_atlas.get_char_index(character).is_none() {
|
||||
if !font_atlases
|
||||
.iter()
|
||||
.any(|atlas| atlas.get_char_index(character).is_some())
|
||||
{
|
||||
if let Some(outlined_glyph) = scaled_font.outline_glyph(glyph.clone()) {
|
||||
let glyph_texture = Font::get_outlined_glyph_texture(outlined_glyph);
|
||||
font_atlas.add_char(textures, texture_atlases, character, &glyph_texture);
|
||||
let add_char_to_font_atlas = |atlas: &mut FontAtlas| -> bool {
|
||||
atlas.add_char(textures, texture_atlases, character, &glyph_texture)
|
||||
};
|
||||
if !font_atlases.iter_mut().any(add_char_to_font_atlas) {
|
||||
font_atlases.push(FontAtlas::new(
|
||||
textures,
|
||||
texture_atlases,
|
||||
Vec2::new(512.0, 512.0),
|
||||
));
|
||||
if !font_atlases.last_mut().unwrap().add_char(
|
||||
textures,
|
||||
texture_atlases,
|
||||
character,
|
||||
&glyph_texture,
|
||||
) {
|
||||
panic!("could not add character to newly created FontAtlas");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
width += scaled_font.h_advance(glyph.id);
|
||||
|
@ -85,9 +113,14 @@ impl FontAtlasSet {
|
|||
.get(&FloatOrd(font_size))
|
||||
.and_then(|font_atlas| {
|
||||
font_atlas
|
||||
.get_char_index(character)
|
||||
.map(|char_index| GlyphAtlasInfo {
|
||||
texture_atlas: font_atlas.texture_atlas,
|
||||
.iter()
|
||||
.find_map(|atlas| {
|
||||
atlas
|
||||
.get_char_index(character)
|
||||
.map(|char_index| (char_index, atlas.texture_atlas))
|
||||
})
|
||||
.map(|(char_index, texture_atlas)| GlyphAtlasInfo {
|
||||
texture_atlas,
|
||||
char_index,
|
||||
})
|
||||
})
|
||||
|
|
|
@ -12,7 +12,7 @@ fn main() {
|
|||
}
|
||||
|
||||
struct State {
|
||||
added: bool,
|
||||
atlas_count: u32,
|
||||
handle: Handle<Font>,
|
||||
timer: Timer,
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ struct State {
|
|||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
added: false,
|
||||
atlas_count: 0,
|
||||
handle: Handle::default(),
|
||||
timer: Timer::from_seconds(0.05, true),
|
||||
}
|
||||
|
@ -34,20 +34,23 @@ fn atlas_render_system(
|
|||
font_atlas_sets: Res<Assets<FontAtlasSet>>,
|
||||
texture_atlases: Res<Assets<TextureAtlas>>,
|
||||
) {
|
||||
if state.added {
|
||||
return;
|
||||
}
|
||||
if let Some(set) = font_atlas_sets.get(&state.handle.as_handle::<FontAtlasSet>()) {
|
||||
if let Some((_size, font_atlas)) = set.iter().next() {
|
||||
state.added = true;
|
||||
let texture_atlas = texture_atlases.get(&font_atlas.texture_atlas).unwrap();
|
||||
let x_offset = state.atlas_count as f32;
|
||||
if state.atlas_count == font_atlas.len() as u32 {
|
||||
return;
|
||||
}
|
||||
let texture_atlas = texture_atlases
|
||||
.get(&font_atlas[state.atlas_count as usize].texture_atlas)
|
||||
.unwrap();
|
||||
state.atlas_count += 1;
|
||||
commands.spawn(ImageComponents {
|
||||
material: materials.add(texture_atlas.texture.into()),
|
||||
style: Style {
|
||||
position_type: PositionType::Absolute,
|
||||
position: Rect {
|
||||
top: Val::Px(0.0),
|
||||
left: Val::Px(0.0),
|
||||
left: Val::Px(512.0 * x_offset),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
|
@ -61,8 +64,9 @@ fn atlas_render_system(
|
|||
fn text_update_system(mut state: ResMut<State>, time: Res<Time>, mut query: Query<&mut Text>) {
|
||||
for mut text in &mut query.iter() {
|
||||
state.timer.tick(time.delta_seconds);
|
||||
if state.timer.finished {
|
||||
text.value = format!("{}", rand::random::<u8>() as char);
|
||||
let c = rand::random::<u8>() as char;
|
||||
if !text.value.contains(c) && state.timer.finished {
|
||||
text.value = format!("{}{}", text.value, c);
|
||||
state.timer.reset();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue