parent
2b0ee24a5d
commit
d4ab2f4d47
@ -39,15 +39,16 @@ impl FontAtlas {
|
|||||||
texture_atlases: &mut Assets<TextureAtlas>,
|
texture_atlases: &mut Assets<TextureAtlas>,
|
||||||
character: char,
|
character: char,
|
||||||
texture: &Texture,
|
texture: &Texture,
|
||||||
) {
|
) -> bool {
|
||||||
let texture_atlas = texture_atlases.get_mut(&self.texture_atlas).unwrap();
|
let texture_atlas = texture_atlases.get_mut(&self.texture_atlas).unwrap();
|
||||||
if let Some(index) =
|
if let Some(index) =
|
||||||
self.dynamic_texture_atlas_builder
|
self.dynamic_texture_atlas_builder
|
||||||
.add_texture(texture_atlas, textures, texture)
|
.add_texture(texture_atlas, textures, texture)
|
||||||
{
|
{
|
||||||
self.glyph_to_index.insert(character, index);
|
self.glyph_to_index.insert(character, index);
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
panic!("ran out of space in font atlas");
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ type FontSizeKey = FloatOrd;
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FontAtlasSet {
|
pub struct FontAtlasSet {
|
||||||
font: Handle<Font>,
|
font: Handle<Font>,
|
||||||
font_atlases: HashMap<FontSizeKey, FontAtlas>,
|
font_atlases: HashMap<FontSizeKey, Vec<FontAtlas>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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()
|
self.font_atlases.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,9 @@ impl FontAtlasSet {
|
|||||||
self.font_atlases
|
self.font_atlases
|
||||||
.get(&FloatOrd(font_size))
|
.get(&FloatOrd(font_size))
|
||||||
.map_or(false, |font_atlas| {
|
.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 {
|
) -> f32 {
|
||||||
let font = fonts.get(&self.font).unwrap();
|
let font = fonts.get(&self.font).unwrap();
|
||||||
let scaled_font = ab_glyph::Font::as_scaled(&font.font, font_size);
|
let scaled_font = ab_glyph::Font::as_scaled(&font.font, font_size);
|
||||||
let font_atlas = self
|
let font_atlases = self
|
||||||
.font_atlases
|
.font_atlases
|
||||||
.entry(FloatOrd(font_size))
|
.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 last_glyph: Option<Glyph> = None;
|
||||||
let mut width = 0.0;
|
let mut width = 0.0;
|
||||||
@ -67,10 +75,30 @@ impl FontAtlasSet {
|
|||||||
if let Some(last_glyph) = last_glyph.take() {
|
if let Some(last_glyph) = last_glyph.take() {
|
||||||
width += scaled_font.kern(last_glyph.id, glyph.id);
|
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()) {
|
if let Some(outlined_glyph) = scaled_font.outline_glyph(glyph.clone()) {
|
||||||
let glyph_texture = Font::get_outlined_glyph_texture(outlined_glyph);
|
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);
|
width += scaled_font.h_advance(glyph.id);
|
||||||
@ -85,9 +113,14 @@ impl FontAtlasSet {
|
|||||||
.get(&FloatOrd(font_size))
|
.get(&FloatOrd(font_size))
|
||||||
.and_then(|font_atlas| {
|
.and_then(|font_atlas| {
|
||||||
font_atlas
|
font_atlas
|
||||||
|
.iter()
|
||||||
|
.find_map(|atlas| {
|
||||||
|
atlas
|
||||||
.get_char_index(character)
|
.get_char_index(character)
|
||||||
.map(|char_index| GlyphAtlasInfo {
|
.map(|char_index| (char_index, atlas.texture_atlas))
|
||||||
texture_atlas: font_atlas.texture_atlas,
|
})
|
||||||
|
.map(|(char_index, texture_atlas)| GlyphAtlasInfo {
|
||||||
|
texture_atlas,
|
||||||
char_index,
|
char_index,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -12,7 +12,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
added: bool,
|
atlas_count: u32,
|
||||||
handle: Handle<Font>,
|
handle: Handle<Font>,
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ struct State {
|
|||||||
impl Default for State {
|
impl Default for State {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
added: false,
|
atlas_count: 0,
|
||||||
handle: Handle::default(),
|
handle: Handle::default(),
|
||||||
timer: Timer::from_seconds(0.05, true),
|
timer: Timer::from_seconds(0.05, true),
|
||||||
}
|
}
|
||||||
@ -34,20 +34,23 @@ fn atlas_render_system(
|
|||||||
font_atlas_sets: Res<Assets<FontAtlasSet>>,
|
font_atlas_sets: Res<Assets<FontAtlasSet>>,
|
||||||
texture_atlases: Res<Assets<TextureAtlas>>,
|
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(set) = font_atlas_sets.get(&state.handle.as_handle::<FontAtlasSet>()) {
|
||||||
if let Some((_size, font_atlas)) = set.iter().next() {
|
if let Some((_size, font_atlas)) = set.iter().next() {
|
||||||
state.added = true;
|
let x_offset = state.atlas_count as f32;
|
||||||
let texture_atlas = texture_atlases.get(&font_atlas.texture_atlas).unwrap();
|
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 {
|
commands.spawn(ImageComponents {
|
||||||
material: materials.add(texture_atlas.texture.into()),
|
material: materials.add(texture_atlas.texture.into()),
|
||||||
style: Style {
|
style: Style {
|
||||||
position_type: PositionType::Absolute,
|
position_type: PositionType::Absolute,
|
||||||
position: Rect {
|
position: Rect {
|
||||||
top: Val::Px(0.0),
|
top: Val::Px(0.0),
|
||||||
left: Val::Px(0.0),
|
left: Val::Px(512.0 * x_offset),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..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>) {
|
fn text_update_system(mut state: ResMut<State>, time: Res<Time>, mut query: Query<&mut Text>) {
|
||||||
for mut text in &mut query.iter() {
|
for mut text in &mut query.iter() {
|
||||||
state.timer.tick(time.delta_seconds);
|
state.timer.tick(time.delta_seconds);
|
||||||
if state.timer.finished {
|
let c = rand::random::<u8>() as char;
|
||||||
text.value = format!("{}", rand::random::<u8>() as char);
|
if !text.value.contains(c) && state.timer.finished {
|
||||||
|
text.value = format!("{}{}", text.value, c);
|
||||||
state.timer.reset();
|
state.timer.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user