From 080cb4543078d80de0d6a5ed6c464ff66b2d72a0 Mon Sep 17 00:00:00 2001 From: verzuz Date: Mon, 14 Sep 2020 21:23:25 +0200 Subject: [PATCH 1/4] manage font_atlas overflow --- crates/bevy_text/src/font_atlas.rs | 5 +++-- crates/bevy_text/src/font_atlas_set.rs | 30 +++++++++++++++++--------- examples/ui/font_atlas_debug.rs | 27 +++++++++++++---------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/crates/bevy_text/src/font_atlas.rs b/crates/bevy_text/src/font_atlas.rs index 24c67d53cbdca..9c39fcf89eede 100644 --- a/crates/bevy_text/src/font_atlas.rs +++ b/crates/bevy_text/src/font_atlas.rs @@ -39,15 +39,16 @@ impl FontAtlas { texture_atlases: &mut Assets, 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 } } } diff --git a/crates/bevy_text/src/font_atlas_set.rs b/crates/bevy_text/src/font_atlas_set.rs index 581877d110774..e45b16ab84295 100644 --- a/crates/bevy_text/src/font_atlas_set.rs +++ b/crates/bevy_text/src/font_atlas_set.rs @@ -13,7 +13,7 @@ type FontSizeKey = FloatOrd; #[derive(Default)] pub struct FontAtlasSet { font: Handle, - font_atlases: HashMap, + font_atlases: HashMap>, } #[derive(Debug)] @@ -30,7 +30,7 @@ impl FontAtlasSet { } } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator)> { self.font_atlases.iter() } @@ -38,7 +38,7 @@ 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() ) }) } @@ -55,7 +55,7 @@ impl FontAtlasSet { let font_atlas = 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 = None; let mut width = 0.0; @@ -67,10 +67,16 @@ 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_atlas.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); + + if !font_atlas.iter_mut().any( | atlas | atlas.add_char(textures, texture_atlases, character, &glyph_texture) ) { + font_atlas.push(FontAtlas::new(textures, texture_atlases, Vec2::new(512.0, 512.0))); + if !font_atlas.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); @@ -84,12 +90,16 @@ impl FontAtlasSet { self.font_atlases .get(&FloatOrd(font_size)) .and_then(|font_atlas| { - font_atlas - .get_char_index(character) - .map(|char_index| GlyphAtlasInfo { - texture_atlas: font_atlas.texture_atlas, + if let Some(atlas) = font_atlas.iter().find(|atlas| atlas.get_char_index(character).is_some()) { + let char_index = atlas.get_char_index(character).unwrap(); + Some(GlyphAtlasInfo { + texture_atlas: atlas.texture_atlas, char_index, }) + } + else { + None + } }) } } diff --git a/examples/ui/font_atlas_debug.rs b/examples/ui/font_atlas_debug.rs index cb30d82e3a2ab..a0e3061b1f787 100644 --- a/examples/ui/font_atlas_debug.rs +++ b/examples/ui/font_atlas_debug.rs @@ -12,7 +12,7 @@ fn main() { } struct State { - added: bool, + atlas_count: u32, handle: Handle, 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,21 @@ fn atlas_render_system( font_atlas_sets: Res>, texture_atlases: Res>, ) { - if state.added { - return; - } if let Some(set) = font_atlas_sets.get(&state.handle.as_handle::()) { 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,9 +62,13 @@ fn atlas_render_system( fn text_update_system(mut state: ResMut, time: Res