Implement text sprite main functions
This commit is contained in:
parent
fabe090307
commit
32bfe01a1e
@ -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(
|
TextSprite::new(
|
||||||
text,
|
text,
|
||||||
size,
|
size,
|
||||||
|
text_size,
|
||||||
&self.renderer,
|
&self.renderer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/main.rs
42
src/main.rs
@ -45,6 +45,7 @@ struct ExampleState {
|
|||||||
pub last_offset: u32,
|
pub last_offset: u32,
|
||||||
pub last_pos: Position,
|
pub last_pos: Position,
|
||||||
pub last_rot: f32,
|
pub last_rot: f32,
|
||||||
|
pub frame_counter: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExampleApp {}
|
struct ExampleApp {}
|
||||||
@ -67,9 +68,9 @@ impl Application<ExampleState> for ExampleApp {
|
|||||||
sub_sprite.set_texture(texture.clone(), Some(Position {x: 350, y: 0}), 1.0);
|
sub_sprite.set_texture(texture.clone(), Some(Position {x: 350, y: 0}), 1.0);
|
||||||
|
|
||||||
let mut txt_sprites = Vec::<TextSprite>::with_capacity(10);
|
let mut txt_sprites = Vec::<TextSprite>::with_capacity(10);
|
||||||
for x in 0..5 {
|
for x in 0..10 {
|
||||||
for y in 0..2 {
|
for y in 0..5 {
|
||||||
let mut sprite = canvas.create_text_sprite("00", Size {w: 200, h: 200});
|
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});
|
sprite.set_position(Position { x: x * 100, y: y * 100});
|
||||||
txt_sprites.push(sprite);
|
txt_sprites.push(sprite);
|
||||||
}
|
}
|
||||||
@ -89,20 +90,47 @@ impl Application<ExampleState> for ExampleApp {
|
|||||||
last_offset: 0,
|
last_offset: 0,
|
||||||
last_pos: Position::origin(),
|
last_pos: Position::origin(),
|
||||||
last_rot: 0.0,
|
last_rot: 0.0,
|
||||||
|
frame_counter: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tick(state: &mut ExampleState, canvas: &mut Canvas) -> Result<(), &'static str> {
|
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 now = Instant::now();
|
||||||
let elapsed = now.duration_since(state.last_instant).as_millis();
|
let elapsed = now.duration_since(state.last_instant).as_millis();
|
||||||
state.last_instant = now;
|
state.last_instant = now;
|
||||||
debug!("frame time: {}ms", elapsed);
|
debug!("frame time: {}ms", elapsed);
|
||||||
for sprite in state.txt_sprites.iter_mut() {
|
state.frame_counter += 1;
|
||||||
sprite.set_text(&format!("{}", elapsed));
|
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.sub_sprite.for_each(|pix| unsafe {pix.flat = pix.flat.wrapping_add(1);});
|
||||||
|
|
||||||
state.last_offset += 1;
|
state.last_offset += 1;
|
||||||
|
|||||||
@ -15,33 +15,30 @@ use super::TextureSprite;
|
|||||||
//--TextSprite struct-------------------------------------------------------------------------------
|
//--TextSprite struct-------------------------------------------------------------------------------
|
||||||
pub struct TextSprite {
|
pub struct TextSprite {
|
||||||
texture_sprite: TextureSprite,
|
texture_sprite: TextureSprite,
|
||||||
font: [fontdue::Font; 1],
|
|
||||||
|
text: String,
|
||||||
|
text_size: f32,
|
||||||
|
text_color: Pixel,
|
||||||
|
|
||||||
|
font: fontdue::Font,
|
||||||
layout: fontdue::layout::Layout,
|
layout: fontdue::layout::Layout,
|
||||||
|
text_generation_needed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextSprite {
|
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::{
|
use crate::{
|
||||||
renderer::Texture,
|
renderer::Texture,
|
||||||
texture::TextureHandle,
|
texture::TextureHandle,
|
||||||
};
|
};
|
||||||
use fontdue::layout::{CoordinateSystem, Layout, TextStyle};
|
use fontdue::layout::{CoordinateSystem, Layout, TextStyle};
|
||||||
|
|
||||||
//load fonts
|
let font = Self::configure_font(text_size);
|
||||||
//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 mut layout = Layout::new(CoordinateSystem::PositiveYDown);
|
let mut layout = Layout::new(CoordinateSystem::PositiveYDown);
|
||||||
|
|
||||||
//compute text layout
|
//configure text layout to fit sprite size, keep default settings
|
||||||
layout.append(&font, &TextStyle::new(text, 40.0, 0));
|
layout.append(&[&font], &TextStyle::new(text, text_size, 0));
|
||||||
|
|
||||||
//draw text to the texture
|
//draw text to the texture
|
||||||
let mut raw_texture : Vec::<Pixel>
|
let mut raw_texture : Vec::<Pixel>
|
||||||
@ -49,7 +46,7 @@ impl TextSprite {
|
|||||||
|
|
||||||
//draw each glyph at the corresponding position on the texture
|
//draw each glyph at the corresponding position on the texture
|
||||||
for glyph in layout.glyphs() {
|
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_x = glyph.x as usize;
|
||||||
let glyph_y = glyph.y as usize;
|
let glyph_y = glyph.y as usize;
|
||||||
@ -76,23 +73,42 @@ impl TextSprite {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
texture_sprite,
|
texture_sprite,
|
||||||
|
text: text.to_string(),
|
||||||
|
text_size,
|
||||||
|
text_color: Color::BLACK,
|
||||||
font,
|
font,
|
||||||
layout,
|
layout,
|
||||||
|
text_generation_needed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_text(&mut self, text: &str) {
|
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.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();
|
let size = self.texture_sprite.get_size();
|
||||||
self.texture_sprite.fill(Color::NONE);
|
self.texture_sprite.fill(Color::NONE);
|
||||||
|
|
||||||
//draw each glyph at the corresponding position on the texture
|
//draw each glyph at the corresponding position on the texture
|
||||||
for glyph in self.layout.glyphs() {
|
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_x = glyph.x as usize;
|
||||||
let glyph_y = glyph.y as usize;
|
let glyph_y = glyph.y as usize;
|
||||||
@ -111,13 +127,19 @@ impl TextSprite {
|
|||||||
x: (glyph_x + x) as u32,
|
x: (glyph_x + x) as u32,
|
||||||
y: (glyph_y + y) 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) {
|
fn configure_font(text_size: f32) -> fontdue::Font
|
||||||
todo!();
|
{
|
||||||
|
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) {
|
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);
|
self.texture_sprite.render(renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user