From 32bfe01a1e179351f67870998fabb2546543066e Mon Sep 17 00:00:00 2001 From: Steins7 Date: Thu, 29 Dec 2022 16:55:47 +0100 Subject: [PATCH] Implement text sprite main functions --- src/canvas.rs | 4 ++- src/main.rs | 42 ++++++++++++++++++---- src/sprite/text_sprite.rs | 73 +++++++++++++++++++++++++++------------ 3 files changed, 89 insertions(+), 30 deletions(-) diff --git a/src/canvas.rs b/src/canvas.rs index 9da8f89..dbea979 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -80,10 +80,12 @@ impl Canvas { ) } - pub fn create_text_sprite(&mut self, text: &'static str, size: Size) -> TextSprite { + pub fn create_text_sprite(&mut self, text: &'static str, size: Size, text_size: f32) + -> TextSprite { TextSprite::new( text, size, + text_size, &self.renderer, ) } diff --git a/src/main.rs b/src/main.rs index 47a58e1..83209d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,7 @@ struct ExampleState { pub last_offset: u32, pub last_pos: Position, pub last_rot: f32, + pub frame_counter: u8, } struct ExampleApp {} @@ -67,9 +68,9 @@ impl Application for ExampleApp { sub_sprite.set_texture(texture.clone(), Some(Position {x: 350, y: 0}), 1.0); let mut txt_sprites = Vec::::with_capacity(10); - for x in 0..5 { - for y in 0..2 { - let mut sprite = canvas.create_text_sprite("00", Size {w: 200, h: 200}); + for x in 0..10 { + for y in 0..5 { + let mut sprite = canvas.create_text_sprite("00", Size {w: 200, h: 200}, 11.0); sprite.set_position(Position { x: x * 100, y: y * 100}); txt_sprites.push(sprite); } @@ -89,20 +90,47 @@ impl Application for ExampleApp { last_offset: 0, last_pos: Position::origin(), last_rot: 0.0, + frame_counter: 0, }) } fn tick(state: &mut ExampleState, canvas: &mut Canvas) -> Result<(), &'static str> { - use canvas::sprite::Sprite; + use canvas::{ + sprite::Sprite, + utils::Color, + }; let now = Instant::now(); let elapsed = now.duration_since(state.last_instant).as_millis(); state.last_instant = now; debug!("frame time: {}ms", elapsed); - for sprite in state.txt_sprites.iter_mut() { - sprite.set_text(&format!("{}", elapsed)); - } + state.frame_counter += 1; + if state.frame_counter >= 60 { + state.frame_counter = 0; + for sprite in state.txt_sprites.iter_mut() { + sprite.set_text(&format!("{}", elapsed)); + sprite.set_text_size(elapsed as f32); + } + } + match state.frame_counter { + 0 => { + for sprite in state.txt_sprites.iter_mut() { + sprite.set_color(Color::RED); + } + }, + 20 => { + for sprite in state.txt_sprites.iter_mut() { + sprite.set_color(Color::BLUE); + } + }, + 40 => { + for sprite in state.txt_sprites.iter_mut() { + sprite.set_color(Color::GREEN); + } + }, + _ => (), + } //state.sub_sprite.for_each(|pix| unsafe {pix.flat = pix.flat.wrapping_add(1);}); state.last_offset += 1; diff --git a/src/sprite/text_sprite.rs b/src/sprite/text_sprite.rs index d3b5bd7..c4af1f1 100644 --- a/src/sprite/text_sprite.rs +++ b/src/sprite/text_sprite.rs @@ -15,33 +15,30 @@ use super::TextureSprite; //--TextSprite struct------------------------------------------------------------------------------- pub struct TextSprite { texture_sprite: TextureSprite, - font: [fontdue::Font; 1], + + text: String, + text_size: f32, + text_color: Pixel, + + font: fontdue::Font, layout: fontdue::layout::Layout, + text_generation_needed: bool, } impl TextSprite { - pub fn new(text: &'static str, size: Size, renderer: &WgpuRenderer) -> Self { + pub fn new(text: &'static str, size: Size, text_size: f32, renderer: &WgpuRenderer) -> Self { use crate::{ renderer::Texture, texture::TextureHandle, }; use fontdue::layout::{CoordinateSystem, Layout, TextStyle}; - //load fonts - //TODO add support for dynamic fonts - let font = include_bytes!("../../assets/DejaVuSansMono.ttf"); - let settings = fontdue::FontSettings { - scale: 11.0, - ..fontdue::FontSettings::default() - }; - let font = [fontdue::Font::from_bytes(&font[..], settings).unwrap()]; - - //configure text layout to fit sprite size, keep default settings + let font = Self::configure_font(text_size); let mut layout = Layout::new(CoordinateSystem::PositiveYDown); - //compute text layout - layout.append(&font, &TextStyle::new(text, 40.0, 0)); + //configure text layout to fit sprite size, keep default settings + layout.append(&[&font], &TextStyle::new(text, text_size, 0)); //draw text to the texture let mut raw_texture : Vec:: @@ -49,7 +46,7 @@ impl TextSprite { //draw each glyph at the corresponding position on the texture for glyph in layout.glyphs() { - let (_metrics, bitmap) = font[0].rasterize_config(glyph.key); + let (_metrics, bitmap) = font.rasterize_config(glyph.key); let glyph_x = glyph.x as usize; let glyph_y = glyph.y as usize; @@ -76,23 +73,42 @@ impl TextSprite { Self { texture_sprite, + text: text.to_string(), + text_size, + text_color: Color::BLACK, font, layout, + text_generation_needed: false, } } pub fn set_text(&mut self, text: &str) { + self.text = text.to_string(); + self.text_generation_needed = true; + } + + pub fn set_text_size(&mut self, text_size: f32) { + self.text_size = text_size; + self.text_generation_needed = true; + } + + pub fn set_color(&mut self, color: Pixel) { + self.text_color = color; + self.text_generation_needed = true; + } + + fn generate_text(&mut self) { - //compute text layout self.layout.clear(); - self.layout.append(&self.font, &fontdue::layout::TextStyle::new(text, 40.0, 0)); + self.layout.append(&[&self.font], + &fontdue::layout::TextStyle::new(&self.text, self.text_size, 0)); let size = self.texture_sprite.get_size(); self.texture_sprite.fill(Color::NONE); //draw each glyph at the corresponding position on the texture for glyph in self.layout.glyphs() { - let (_metrics, bitmap) = self.font[0].rasterize_config(glyph.key); + let (_metrics, bitmap) = self.font.rasterize_config(glyph.key); let glyph_x = glyph.x as usize; let glyph_y = glyph.y as usize; @@ -111,13 +127,19 @@ impl TextSprite { x: (glyph_x + x) as u32, y: (glyph_y + y) as u32, }, - Color::BLACK.with_alpha(bitmap[x + y * glyph.width]) + self.text_color.with_alpha(bitmap[x + y * glyph.width]) ); - } } } } + } } } } } - pub fn set_color(&mut self, _color: Pixel) { - todo!(); + fn configure_font(text_size: f32) -> fontdue::Font + { + let font = include_bytes!("../../assets/DejaVuSansMono.ttf"); + let settings = fontdue::FontSettings { + scale: text_size, + ..fontdue::FontSettings::default() + }; + fontdue::Font::from_bytes(&font[..], settings).unwrap() } } @@ -140,6 +162,13 @@ impl Sprite for TextSprite { } fn render(&mut self, renderer: &mut WgpuRenderer) { + + // generate text if any setting changed + if self.text_generation_needed == true { + self.generate_text(); + self.text_generation_needed = false; + } + self.texture_sprite.render(renderer); } }