From 6f95e6109c2c81c91da2e3af3cffc8adf0bc0425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sallai=20J=C3=B3zsef?= Date: Sat, 23 Jul 2022 13:59:13 +0300 Subject: [PATCH] add methods for rendering text with sprite rects --- src/bmfont_renderer.rs | 235 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 213 insertions(+), 22 deletions(-) diff --git a/src/bmfont_renderer.rs b/src/bmfont_renderer.rs index 99e94bc..5ff6ac7 100644 --- a/src/bmfont_renderer.rs +++ b/src/bmfont_renderer.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use crate::bmfont::BMFont; @@ -62,6 +62,26 @@ impl BMFontRenderer { offset_x } + pub fn text_width_with_rects + Clone>( + &self, + iter: I, + rect_map: &HashMap>, + constants: &EngineConstants, + ) -> f32 { + let mut width = self.text_width(iter.clone(), constants); + + for chr in iter { + if let Some(rect) = rect_map.get(&chr) { + if let Some(glyph) = self.font.chars.get(&chr) { + width += rect.width() as f32; + width -= glyph.xadvance as f32 * constants.font_scale; + } + } + } + + width + } + pub fn draw_text>( &self, iter: I, @@ -74,6 +94,30 @@ impl BMFontRenderer { self.draw_colored_text(iter, x, y, (255, 255, 255, 255), constants, texture_set, ctx) } + pub fn draw_text_with_rects>( + &self, + iter: I, + x: f32, + y: f32, + constants: &EngineConstants, + texture_set: &mut TextureSet, + rect_map: &HashMap>, + sprite_batch_name: Option<&str>, + ctx: &mut Context, + ) -> GameResult { + self.draw_colored_text_with_rects( + iter, + x, + y, + (255, 255, 255, 255), + constants, + texture_set, + rect_map, + sprite_batch_name, + ctx, + ) + } + pub fn draw_text_with_shadow + Clone>( &self, iter: I, @@ -87,6 +131,41 @@ impl BMFontRenderer { self.draw_colored_text(iter, x, y, (255, 255, 255, 255), constants, texture_set, ctx) } + pub fn draw_text_with_shadow_and_rects + Clone>( + &self, + iter: I, + x: f32, + y: f32, + constants: &EngineConstants, + texture_set: &mut TextureSet, + rect_map: &HashMap>, + sprite_batch_name: Option<&str>, + ctx: &mut Context, + ) -> GameResult { + self.draw_colored_text_with_rects( + iter.clone(), + x + 1.0, + y + 1.0, + (0, 0, 0, 150), + constants, + texture_set, + rect_map, + None, + ctx, + )?; + self.draw_colored_text_with_rects( + iter, + x, + y, + (255, 255, 255, 255), + constants, + texture_set, + rect_map, + sprite_batch_name, + ctx, + ) + } + pub fn draw_colored_text_with_shadow_scaled + Clone>( &self, iter: I, @@ -111,6 +190,45 @@ impl BMFontRenderer { self.draw_colored_text_scaled(iter, x, y, scale, color, constants, texture_set, ctx) } + pub fn draw_colored_text_with_shadow_and_rects_scaled + Clone>( + &self, + iter: I, + x: f32, + y: f32, + scale: f32, + color: (u8, u8, u8, u8), + constants: &EngineConstants, + texture_set: &mut TextureSet, + rect_map: &HashMap>, + sprite_batch_name: Option<&str>, + ctx: &mut Context, + ) -> GameResult { + self.draw_colored_text_with_rects_scaled( + iter.clone(), + x + scale, + y + scale, + scale, + (0, 0, 0, 150), + constants, + texture_set, + rect_map, + None, + ctx, + )?; + self.draw_colored_text_with_rects_scaled( + iter, + x, + y, + scale, + color, + constants, + texture_set, + rect_map, + sprite_batch_name, + ctx, + ) + } + pub fn draw_colored_text_scaled>( &self, iter: I, @@ -122,22 +240,47 @@ impl BMFontRenderer { texture_set: &mut TextureSet, ctx: &mut Context, ) -> GameResult { + let rect_map: HashMap> = HashMap::new(); + + self.draw_colored_text_with_rects_scaled(iter, x, y, scale, color, constants, texture_set, &rect_map, None, ctx) + } + + pub fn draw_colored_text_with_rects_scaled>( + &self, + iter: I, + x: f32, + y: f32, + scale: f32, + color: (u8, u8, u8, u8), + constants: &EngineConstants, + texture_set: &mut TextureSet, + rect_map: &HashMap>, + sprite_batch_name: Option<&str>, + ctx: &mut Context, + ) -> GameResult { + let mut sprite_rects: Vec<(f32, f32, &Rect)> = Vec::new(); + if self.pages.len() == 1 { let batch = texture_set.get_or_load_batch(ctx, constants, self.pages.get(0).unwrap())?; let mut offset_x = x; for chr in iter { if let Some(glyph) = self.font.chars.get(&chr) { - batch.add_rect_scaled_tinted( - offset_x + (glyph.xoffset as f32 * constants.font_scale), - y + (glyph.yoffset as f32 * constants.font_scale), - color, - constants.font_scale * scale, - constants.font_scale * scale, - &Rect::new_size(glyph.x as u16, glyph.y as u16, glyph.width as u16, glyph.height as u16), - ); + if let Some(rect) = rect_map.get(&chr) { + sprite_rects.push((offset_x, self.line_height(constants) - rect.height() as f32 / 2.0, rect)); + offset_x += rect.width() as f32; + } else { + batch.add_rect_scaled_tinted( + offset_x + (glyph.xoffset as f32 * constants.font_scale), + y + (glyph.yoffset as f32 * constants.font_scale), + color, + constants.font_scale * scale, + constants.font_scale * scale, + &Rect::new_size(glyph.x as u16, glyph.y as u16, glyph.width as u16, glyph.height as u16), + ); - offset_x += glyph.xadvance as f32 * constants.font_scale * scale; + offset_x += glyph.xadvance as f32 * constants.font_scale * scale; + } } } @@ -163,25 +306,47 @@ impl BMFontRenderer { let batch = texture_set.get_or_load_batch(ctx, constants, page_tex)?; let mut offset_x = x; - for (_chr, glyph) in chars.iter() { - if glyph.page == page { - batch.add_rect_scaled_tinted( - offset_x + (glyph.xoffset as f32 * constants.font_scale), - y + (glyph.yoffset as f32 * constants.font_scale), - color, - constants.font_scale * scale, - constants.font_scale * scale, - &Rect::new_size(glyph.x as u16, glyph.y as u16, glyph.width as u16, glyph.height as u16), - ); - } + for (chr, glyph) in chars.iter() { + if let Some(rect) = rect_map.get(&chr) { + sprite_rects.push((offset_x, self.line_height(constants) - rect.height() as f32 / 2.0, rect)); + offset_x += rect.width() as f32; + } else { + if glyph.page == page { + batch.add_rect_scaled_tinted( + offset_x + (glyph.xoffset as f32 * constants.font_scale), + y + (glyph.yoffset as f32 * constants.font_scale), + color, + constants.font_scale * scale, + constants.font_scale * scale, + &Rect::new_size( + glyph.x as u16, + glyph.y as u16, + glyph.width as u16, + glyph.height as u16, + ), + ); + } - offset_x += scale * (glyph.xadvance as f32 * constants.font_scale); + offset_x += scale * (glyph.xadvance as f32 * constants.font_scale); + } } batch.draw(ctx)?; } } + if let Some(sprite_batch_name) = sprite_batch_name { + if !sprite_rects.is_empty() { + let sprite_batch = texture_set.get_or_load_batch(ctx, constants, sprite_batch_name)?; + + for (x, y, rect) in sprite_rects { + sprite_batch.add_rect_scaled(x, y, scale, scale, rect); + } + + sprite_batch.draw(ctx)?; + } + } + Ok(()) } @@ -197,4 +362,30 @@ impl BMFontRenderer { ) -> GameResult { self.draw_colored_text_scaled(iter, x, y, 1.0, color, constants, texture_set, ctx) } + + pub fn draw_colored_text_with_rects>( + &self, + iter: I, + x: f32, + y: f32, + color: (u8, u8, u8, u8), + constants: &EngineConstants, + texture_set: &mut TextureSet, + rect_map: &HashMap>, + sprite_batch_name: Option<&str>, + ctx: &mut Context, + ) -> GameResult { + self.draw_colored_text_with_rects_scaled( + iter, + x, + y, + 1.0, + color, + constants, + texture_set, + rect_map, + sprite_batch_name, + ctx, + ) + } }