From 07dc80e8facb3be095789a4649003e7fd41641e2 Mon Sep 17 00:00:00 2001 From: jem Date: Sat, 19 Nov 2022 15:44:29 +0000 Subject: [PATCH 01/14] rework the text renderer --- agb/examples/font/font-test-output.png | Bin 1300 -> 2670 bytes agb/src/display/font.rs | 145 +++++++++++++++---------- 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/agb/examples/font/font-test-output.png b/agb/examples/font/font-test-output.png index b07074d53101600643231d4b5a6198c488caf8a2..be7bce8b6513106006c624f0e76b176fbb1b603b 100644 GIT binary patch literal 2670 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 UU~Nu-dnD|be~4eL@A;em2h<+#`Tzg` literal 1300 zcmbtSeK^wz9RF3A=9ILq$ZLm^m6!Esb4g6t=2$(`GH<2i=8C+{%QCKXUTX4kZOU$1 zX^5$rRGSeKH;(SkTQ;`{EhDoP#>BZl`};o6^Z9(9&p+Si`#hgd9yY+&5Nrwt0KgFC z=Y4YB=hk^of8)9eUyxh?U_&+$iNvCiNUO^UaTkaeqX1xEQAUxwpXiv`s|XKo`yh}3 zI{tU;Z_wO)c+8G`taU$_<5n8Ftows$F=VH2>(kNE&d7n*SHXA?-qUCWh)+s5nN(!F zMu!mEQ!kI)N?Ei>Q39C{+Hf%Vma4l^6(yUk%R+YWBeu0$EgN~^BH2gx=G&(hJSJ;2 z={x1YGWn{R5G^~O6==nb;-B3XXA~GmaFb`e(|16DRR~q7=S~~S1b;@oTYg_eVVXF* zOr^ck=VE8hyto!D#^zP#p38r9qS<4*zAfzrk5J7WbYC(MrCo};GkqwhsC^I3$}8)p zX;;-tFUBb~m<$Hp(t8> zY%{0J2HArnGJ+PK0l4%BDfHlQ9iJP&3TIWb%wE~5d!IrHa%@VtxsS;h1%OQ$l(#1? zmGMy$l2GOZ0kFklJAMhYxBR25sRa7q%RO71AAYM7iIK>LB^ytnbAK}O>eE@T^D9(@ zQ(A7}1fd>m;_}k!cS~0yhM9**%E@#AC7wC7)Y3hF?x;#E55Y+I#|6`IVT~u4;_3d( zJmJ)28hpS)?$c^648qjHYHh=4>YRyFu99Mbr!k#BCRrH?ANO!H;R)kACquw-4z4~J z3Xc;a%z0kuQS&;R8BKfG9wY8eR(vz@`B+0tIC@0+KCz3-(Ei*sOpJ|(YC+3(-Q}mF zy10W+;e{g~YLdroc2h>bU+WfU2v;btZQd?)1~>X2>FenTUH^aZ?6aqhf1x+<+)+$( za?5UCP9S|yOCDeBSW--q4VzD!6xvJ+{XRSnYQ|>_&l+tl?kTbFvph7gk+cd?wml z+7YPGqtXhvgl7#R8;cxwR(&}}^roH*{qZnjVdg}Gr9`c@(lo+^-Dy+Evr|u`i+c~) zhUi?cIdE`?ytoxpp1d?eW82`WITf)a`KdqAbCk-%xcOYP^Y#G}FXA?>v~SHm+^tHs z1#jNi#Z9{Z&~l)St`4YvlirUWub00s6M`>jO&W|tp=6}4Zn5WN+Zl~JTfoMLvh?Lb(}=5Wrg{{6Z{M4{%n zq!Oe$vLDqx-*?>U4odP*ZxlINl$Sg|VgJy( - &'a self, - tile_pos: Vector2D, - foreground_colour: u8, - background_colour: u8, - bg: &'a mut RegularMap, - vram_manager: &'a mut VRamManager, - ) -> TextRenderer<'a> { + pub fn render_text<'a>(&'a self, tile_pos: Vector2D) -> TextRenderer<'a> { TextRenderer { current_x_pos: 0, current_y_pos: 0, font: self, tile_pos, - vram_manager, - bg, - background_colour, - foreground_colour, tiles: Default::default(), } } @@ -84,43 +73,63 @@ pub struct TextRenderer<'a> { current_y_pos: i32, font: &'a Font, tile_pos: Vector2D, - vram_manager: &'a mut VRamManager, - bg: &'a mut RegularMap, - background_colour: u8, - foreground_colour: u8, tiles: HashMap<(i32, i32), DynamicTile<'a>>, } -impl<'a> Write for TextRenderer<'a> { +pub struct TextWriter<'a, 'b: 'a, 'c> { + foreground_colour: u8, + background_colour: u8, + text_renderer: &'a mut TextRenderer<'c>, + vram_manager: &'b mut VRamManager, + bg: &'b mut RegularMap, +} + +impl<'a, 'b, 'c> Write for TextWriter<'a, 'b, 'c> { fn write_str(&mut self, text: &str) -> Result<(), Error> { for c in text.chars() { - if c == '\n' { - self.current_y_pos += self.font.line_height; - self.current_x_pos = 0; - continue; - } - - let letter = self.font.letter(c); - - self.render_letter(letter); - - self.current_x_pos += i32::from(letter.advance_width); + self.text_renderer.write_char( + c, + self.vram_manager, + self.foreground_colour, + self.background_colour, + ); } - Ok(()) } } +impl<'a, 'b, 'c> TextWriter<'a, 'b, 'c> { + pub fn commit(self) { + self.text_renderer.commit(self.bg, self.vram_manager) + } +} fn div_ceil(quotient: i32, divisor: i32) -> i32 { (quotient + divisor - 1) / divisor } -impl<'a> TextRenderer<'a> { - fn render_letter(&mut self, letter: &FontLetter) { - let vram_manager = &mut self.vram_manager; - let foreground_colour = self.foreground_colour; - let background_colour = self.background_colour; - +impl<'a, 'b, 'c> TextRenderer<'c> { + pub fn writer( + &'a mut self, + foreground_colour: u8, + background_colour: u8, + bg: &'b mut RegularMap, + vram_manager: &'b mut VRamManager, + ) -> TextWriter<'a, 'b, 'c> { + TextWriter { + text_renderer: self, + foreground_colour, + background_colour, + bg, + vram_manager, + } + } + fn render_letter( + &mut self, + letter: &FontLetter, + vram_manager: &mut VRamManager, + foreground_colour: u8, + background_colour: u8, + ) { let x_start = (self.current_x_pos + i32::from(letter.xmin)).max(0); let y_start = self.current_y_pos + self.font.ascent - i32::from(letter.height) @@ -182,27 +191,39 @@ impl<'a> TextRenderer<'a> { } } - pub fn commit(mut self) { - let tiles = core::mem::take(&mut self.tiles); - - for ((x, y), tile) in tiles.into_iter() { - self.bg.set_tile( - self.vram_manager, - (self.tile_pos.x + x as u16, self.tile_pos.y + y as u16).into(), + pub fn commit(&self, bg: &'b mut RegularMap, vram_manager: &'b mut VRamManager) { + for ((x, y), tile) in self.tiles.iter() { + bg.set_tile( + vram_manager, + (self.tile_pos.x + *x as u16, self.tile_pos.y + *y as u16).into(), &tile.tile_set(), TileSetting::from_raw(tile.tile_index()), ); - self.vram_manager.remove_dynamic_tile(tile); } } -} - -impl<'a> Drop for TextRenderer<'a> { - fn drop(&mut self) { + pub fn write_char( + &mut self, + c: char, + vram_manager: &mut VRamManager, + foreground_colour: u8, + background_colour: u8, + ) { + if c == '\n' { + self.current_y_pos += self.font.line_height; + self.current_x_pos = 0; + } else { + let letter = self.font.letter(c); + self.render_letter(letter, vram_manager, foreground_colour, background_colour); + self.current_x_pos += i32::from(letter.advance_width); + } + } + pub fn clear(&mut self, vram_manager: &mut VRamManager) { + self.current_x_pos = 0; + self.current_y_pos = 0; let tiles = core::mem::take(&mut self.tiles); for (_, tile) in tiles.into_iter() { - self.vram_manager.remove_dynamic_tile(tile); + vram_manager.remove_dynamic_tile(tile); } } } @@ -242,16 +263,30 @@ mod tests { vram.remove_dynamic_tile(background_tile); - let mut writer = FONT.render_text((0u16, 3u16).into(), 1, 2, &mut bg, &mut vram); + let mut renderer = FONT.render_text((0u16, 3u16).into()); - writeln!(&mut writer, "Hello, World!").unwrap(); - writeln!(&mut writer, "This is a font rendering example").unwrap(); + // Test twice to ensure that clearing works + for _ in 0..2 { + let mut writer = renderer.writer(1, 2, &mut bg, &mut vram); + write!(&mut writer, "Hello, ").unwrap(); + writer.commit(); - writer.commit(); + // Test changing color + let mut writer = renderer.writer(4, 2, &mut bg, &mut vram); + writeln!(&mut writer, "World!").unwrap(); + writer.commit(); + bg.commit(&mut vram); + bg.show(); - bg.commit(&mut vram); - bg.show(); + // Test writing with same renderer after showing background + let mut writer = renderer.writer(1, 2, &mut bg, &mut vram); + writeln!(&mut writer, "This is a font rendering example").unwrap(); + writer.commit(); + bg.commit(&mut vram); + bg.show(); - crate::test_runner::assert_image_output("examples/font/font-test-output.png"); + crate::test_runner::assert_image_output("examples/font/font-test-output.png"); + renderer.clear(&mut vram); + } } } From e576f0685e7339afe2566c4eb8ca9747f5c5817f Mon Sep 17 00:00:00 2001 From: jem Date: Sat, 19 Nov 2022 15:49:55 +0000 Subject: [PATCH 02/14] readd new line --- agb/src/display/font.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/agb/src/display/font.rs b/agb/src/display/font.rs index 1549d2d7..9527aa75 100644 --- a/agb/src/display/font.rs +++ b/agb/src/display/font.rs @@ -94,6 +94,7 @@ impl<'a, 'b, 'c> Write for TextWriter<'a, 'b, 'c> { self.background_colour, ); } + Ok(()) } } From e7d87b8eeeb50ec6657ffbaecee7afe60e57d852 Mon Sep 17 00:00:00 2001 From: jem Date: Sat, 19 Nov 2022 15:57:38 +0000 Subject: [PATCH 03/14] fix clippy warnings --- agb/src/display/font.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/agb/src/display/font.rs b/agb/src/display/font.rs index 9527aa75..ddc3a672 100644 --- a/agb/src/display/font.rs +++ b/agb/src/display/font.rs @@ -57,7 +57,8 @@ impl Font { } impl Font { - pub fn render_text<'a>(&'a self, tile_pos: Vector2D) -> TextRenderer<'a> { + #[must_use] + pub fn render_text(&self, tile_pos: Vector2D) -> TextRenderer<'_> { TextRenderer { current_x_pos: 0, current_y_pos: 0, @@ -100,7 +101,7 @@ impl<'a, 'b, 'c> Write for TextWriter<'a, 'b, 'c> { } impl<'a, 'b, 'c> TextWriter<'a, 'b, 'c> { pub fn commit(self) { - self.text_renderer.commit(self.bg, self.vram_manager) + self.text_renderer.commit(self.bg, self.vram_manager); } } From 75fe0532f120cc94f9f64dcae156287a8028ac3d Mon Sep 17 00:00:00 2001 From: jem Date: Sun, 20 Nov 2022 19:33:39 +0000 Subject: [PATCH 04/14] add docs --- agb/src/display/font.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/agb/src/display/font.rs b/agb/src/display/font.rs index ddc3a672..26025e72 100644 --- a/agb/src/display/font.rs +++ b/agb/src/display/font.rs @@ -5,6 +5,11 @@ use crate::hash_map::HashMap; use super::tiled::{DynamicTile, RegularMap, TileSetting, VRamManager}; +/// The text renderer renders a variable width fixed size +/// bitmap font using dynamic tiles as a rendering surface. +/// Does not support any unicode features. +/// For usage see the `text_render.rs` example + pub struct FontLetter { width: u8, height: u8, @@ -58,6 +63,7 @@ impl Font { impl Font { #[must_use] + /// Create renderer starting at the given tile co-ordinates. pub fn render_text(&self, tile_pos: Vector2D) -> TextRenderer<'_> { TextRenderer { current_x_pos: 0, @@ -70,6 +76,7 @@ impl Font { } pub struct TextRenderer<'a> { + /// Keeps track of the cursor and manages rendered tiles. current_x_pos: i32, current_y_pos: i32, font: &'a Font, @@ -78,6 +85,8 @@ pub struct TextRenderer<'a> { } pub struct TextWriter<'a, 'b: 'a, 'c> { + /// Generated from the renderer for use + /// with `Write` trait methods. foreground_colour: u8, background_colour: u8, text_renderer: &'a mut TextRenderer<'c>, @@ -100,6 +109,7 @@ impl<'a, 'b, 'c> Write for TextWriter<'a, 'b, 'c> { } } impl<'a, 'b, 'c> TextWriter<'a, 'b, 'c> { + /// Calls commit on the parent renderer, consuming the writer. pub fn commit(self) { self.text_renderer.commit(self.bg, self.vram_manager); } @@ -125,6 +135,9 @@ impl<'a, 'b, 'c> TextRenderer<'c> { vram_manager, } } + + /// Renders a single character creating as many dynamic tiles as needed. + /// The foreground and background colour are palette indicies. fn render_letter( &mut self, letter: &FontLetter, @@ -192,7 +205,7 @@ impl<'a, 'b, 'c> TextRenderer<'c> { } } } - + /// Commit the dynamic tiles that contain the text to the background. pub fn commit(&self, bg: &'b mut RegularMap, vram_manager: &'b mut VRamManager) { for ((x, y), tile) in self.tiles.iter() { bg.set_tile( @@ -203,6 +216,7 @@ impl<'a, 'b, 'c> TextRenderer<'c> { ); } } + /// Write another char into the text, moving the cursor as appropriate. pub fn write_char( &mut self, c: char, @@ -219,6 +233,8 @@ impl<'a, 'b, 'c> TextRenderer<'c> { self.current_x_pos += i32::from(letter.advance_width); } } + + /// Clear the text, removing the tiles from vram and resetting the cursor. pub fn clear(&mut self, vram_manager: &mut VRamManager) { self.current_x_pos = 0; self.current_y_pos = 0; From 0f3182d5b81e9d9d303e4a2790ec4fa786429073 Mon Sep 17 00:00:00 2001 From: jem Date: Sun, 20 Nov 2022 19:35:03 +0000 Subject: [PATCH 05/14] fix examples --- agb/examples/mixer_32768.rs | 10 +++++++--- agb/examples/stereo_sound.rs | 11 +++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/agb/examples/mixer_32768.rs b/agb/examples/mixer_32768.rs index 2d9f60d7..6d733d18 100644 --- a/agb/examples/mixer_32768.rs +++ b/agb/examples/mixer_32768.rs @@ -27,9 +27,10 @@ fn main(mut gba: Gba) -> ! { init_background(&mut bg, &mut vram); - let mut writer = FONT.render_text((0u16, 3u16).into(), 1, 0, &mut bg, &mut vram); + let mut title_renderer = FONT.render_text((0u16, 3u16).into()); + let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram); - writeln!(&mut writer, "Crazy Glue by Josh Woodward").unwrap(); + writeln!(&mut writer, "Crazy Glue by Josh Woodward\n\n").unwrap(); writer.commit(); @@ -51,6 +52,7 @@ fn main(mut gba: Gba) -> ! { let mut frame_counter = 0i32; let mut has_written_frame_time = false; + let mut stats_renderer = FONT.render_text((0u16, 6u16).into()); loop { vblank_provider.wait_for_vblank(); bg.commit(&mut vram); @@ -66,7 +68,9 @@ fn main(mut gba: Gba) -> ! { let percent = (total_cycles * 100) / 280896; - let mut writer = FONT.render_text((0u16, 6u16).into(), 2, 0, &mut bg, &mut vram); + stats_renderer.clear(&mut vram); + + let mut writer = stats_renderer.writer(1, 0, &mut bg, &mut vram); writeln!(&mut writer, "{total_cycles} cycles").unwrap(); writeln!(&mut writer, "{percent} percent").unwrap(); diff --git a/agb/examples/stereo_sound.rs b/agb/examples/stereo_sound.rs index 66dbcdee..d3c39d72 100644 --- a/agb/examples/stereo_sound.rs +++ b/agb/examples/stereo_sound.rs @@ -27,9 +27,10 @@ fn main(mut gba: Gba) -> ! { init_background(&mut bg, &mut vram); - let mut writer = FONT.render_text((0u16, 3u16).into(), 1, 0, &mut bg, &mut vram); + let mut title_renderer = FONT.render_text((0u16, 3u16).into()); + let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram); - writeln!(&mut writer, "Let it in by Josh Woodward").unwrap(); + writeln!(&mut writer, "Crazy Glue by Josh Woodward\n\n").unwrap(); writer.commit(); @@ -49,6 +50,8 @@ fn main(mut gba: Gba) -> ! { let mut frame_counter = 0i32; let mut has_written_frame_time = false; + + let mut stats_renderer = FONT.render_text((0u16, 6u16).into()); loop { vblank_provider.wait_for_vblank(); bg.commit(&mut vram); @@ -64,8 +67,8 @@ fn main(mut gba: Gba) -> ! { let total_cycles = after_mixing_cycles.wrapping_sub(before_mixing_cycles) as u32; let percent = (total_cycles * 100) / 280896; - - let mut writer = FONT.render_text((0u16, 6u16).into(), 2, 0, &mut bg, &mut vram); + + let mut writer = stats_renderer.writer(1, 0, &mut bg, &mut vram); writeln!(&mut writer, "{total_cycles} cycles").unwrap(); writeln!(&mut writer, "{percent} percent").unwrap(); From 31c4d478720e3e05bc760b54043ceeb013c495f3 Mon Sep 17 00:00:00 2001 From: jem Date: Sun, 20 Nov 2022 23:15:09 +0000 Subject: [PATCH 06/14] whitespace --- agb/examples/stereo_sound.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agb/examples/stereo_sound.rs b/agb/examples/stereo_sound.rs index d3c39d72..74bd501b 100644 --- a/agb/examples/stereo_sound.rs +++ b/agb/examples/stereo_sound.rs @@ -67,7 +67,7 @@ fn main(mut gba: Gba) -> ! { let total_cycles = after_mixing_cycles.wrapping_sub(before_mixing_cycles) as u32; let percent = (total_cycles * 100) / 280896; - + let mut writer = stats_renderer.writer(1, 0, &mut bg, &mut vram); writeln!(&mut writer, "{total_cycles} cycles").unwrap(); writeln!(&mut writer, "{percent} percent").unwrap(); From 8b23b7d54a01f33dfebd9671a2a345beb9bc5af3 Mon Sep 17 00:00:00 2001 From: jem Date: Sun, 20 Nov 2022 23:16:23 +0000 Subject: [PATCH 07/14] wrong title --- agb/examples/stereo_sound.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/agb/examples/stereo_sound.rs b/agb/examples/stereo_sound.rs index 74bd501b..1af3eb6c 100644 --- a/agb/examples/stereo_sound.rs +++ b/agb/examples/stereo_sound.rs @@ -30,7 +30,8 @@ fn main(mut gba: Gba) -> ! { let mut title_renderer = FONT.render_text((0u16, 3u16).into()); let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram); - writeln!(&mut writer, "Crazy Glue by Josh Woodward\n\n").unwrap(); + writeln!(&mut writer, "Let it in by Josh Woodward").unwrap(); + writer.commit(); From fbcf001986748688fa0a639dfbb5600a540c9e1d Mon Sep 17 00:00:00 2001 From: jem Date: Sun, 20 Nov 2022 23:17:49 +0000 Subject: [PATCH 08/14] unneeded newlines --- agb/examples/mixer_32768.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agb/examples/mixer_32768.rs b/agb/examples/mixer_32768.rs index 6d733d18..a37aca62 100644 --- a/agb/examples/mixer_32768.rs +++ b/agb/examples/mixer_32768.rs @@ -30,7 +30,7 @@ fn main(mut gba: Gba) -> ! { let mut title_renderer = FONT.render_text((0u16, 3u16).into()); let mut writer = title_renderer.writer(1, 0, &mut bg, &mut vram); - writeln!(&mut writer, "Crazy Glue by Josh Woodward\n\n").unwrap(); + writeln!(&mut writer, "Crazy Glue by Josh Woodward").unwrap(); writer.commit(); From 707c2bf7e7f8761f20fdb1e6441793a58c89910c Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Nov 2022 07:26:48 +0000 Subject: [PATCH 09/14] Remove the 'b lifetime --- agb/src/display/font.rs | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/agb/src/display/font.rs b/agb/src/display/font.rs index 26025e72..d8a16b12 100644 --- a/agb/src/display/font.rs +++ b/agb/src/display/font.rs @@ -8,8 +8,7 @@ use super::tiled::{DynamicTile, RegularMap, TileSetting, VRamManager}; /// The text renderer renders a variable width fixed size /// bitmap font using dynamic tiles as a rendering surface. /// Does not support any unicode features. -/// For usage see the `text_render.rs` example - +/// For usage see the `text_render.rs` example pub struct FontLetter { width: u8, height: u8, @@ -75,8 +74,8 @@ impl Font { } } +/// Keeps track of the cursor and manages rendered tiles. pub struct TextRenderer<'a> { - /// Keeps track of the cursor and manages rendered tiles. current_x_pos: i32, current_y_pos: i32, font: &'a Font, @@ -84,17 +83,17 @@ pub struct TextRenderer<'a> { tiles: HashMap<(i32, i32), DynamicTile<'a>>, } -pub struct TextWriter<'a, 'b: 'a, 'c> { - /// Generated from the renderer for use - /// with `Write` trait methods. +/// Generated from the renderer for use +/// with `Write` trait methods. +pub struct TextWriter<'a, 'c> { foreground_colour: u8, background_colour: u8, text_renderer: &'a mut TextRenderer<'c>, - vram_manager: &'b mut VRamManager, - bg: &'b mut RegularMap, + vram_manager: &'a mut VRamManager, + bg: &'a mut RegularMap, } -impl<'a, 'b, 'c> Write for TextWriter<'a, 'b, 'c> { +impl<'a, 'b> Write for TextWriter<'a, 'b> { fn write_str(&mut self, text: &str) -> Result<(), Error> { for c in text.chars() { self.text_renderer.write_char( @@ -108,8 +107,8 @@ impl<'a, 'b, 'c> Write for TextWriter<'a, 'b, 'c> { Ok(()) } } -impl<'a, 'b, 'c> TextWriter<'a, 'b, 'c> { - /// Calls commit on the parent renderer, consuming the writer. + +impl<'a, 'b> TextWriter<'a, 'b> { pub fn commit(self) { self.text_renderer.commit(self.bg, self.vram_manager); } @@ -119,14 +118,14 @@ fn div_ceil(quotient: i32, divisor: i32) -> i32 { (quotient + divisor - 1) / divisor } -impl<'a, 'b, 'c> TextRenderer<'c> { +impl<'a, 'c> TextRenderer<'c> { pub fn writer( &'a mut self, foreground_colour: u8, background_colour: u8, - bg: &'b mut RegularMap, - vram_manager: &'b mut VRamManager, - ) -> TextWriter<'a, 'b, 'c> { + bg: &'a mut RegularMap, + vram_manager: &'a mut VRamManager, + ) -> TextWriter<'a, 'c> { TextWriter { text_renderer: self, foreground_colour, @@ -205,8 +204,9 @@ impl<'a, 'b, 'c> TextRenderer<'c> { } } } + /// Commit the dynamic tiles that contain the text to the background. - pub fn commit(&self, bg: &'b mut RegularMap, vram_manager: &'b mut VRamManager) { + pub fn commit(&self, bg: &'a mut RegularMap, vram_manager: &'a mut VRamManager) { for ((x, y), tile) in self.tiles.iter() { bg.set_tile( vram_manager, @@ -216,6 +216,7 @@ impl<'a, 'b, 'c> TextRenderer<'c> { ); } } + /// Write another char into the text, moving the cursor as appropriate. pub fn write_char( &mut self, From 9660b6df12f42ef052df8998396a3c6836a45a2d Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Nov 2022 07:28:40 +0000 Subject: [PATCH 10/14] Fix the text_render example --- agb/examples/text_render.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/agb/examples/text_render.rs b/agb/examples/text_render.rs index 79470d3d..e9289f3c 100644 --- a/agb/examples/text_render.rs +++ b/agb/examples/text_render.rs @@ -40,7 +40,8 @@ fn main(mut gba: agb::Gba) -> ! { vram.remove_dynamic_tile(background_tile); - let mut writer = FONT.render_text((0u16, 3u16).into(), 1, 2, &mut bg, &mut vram); + let mut renderer = FONT.render_text((0u16, 3u16).into()); + let mut writer = renderer.writer(1, 2, &mut bg, &mut vram); writeln!(&mut writer, "Hello, World!").unwrap(); writeln!(&mut writer, "This is a font rendering example").unwrap(); @@ -53,7 +54,8 @@ fn main(mut gba: agb::Gba) -> ! { let mut frame = 0; loop { - let mut writer = FONT.render_text((4u16, 0u16).into(), 1, 2, &mut bg, &mut vram); + let mut renderer = FONT.render_text((4u16, 0u16).into()); + let mut writer = renderer.writer(1, 2, &mut bg, &mut vram); writeln!(&mut writer, "Frame {}", frame).unwrap(); writer.commit(); From 08ceef09cd07a2e224886e79f6442a18f2fb7163 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Nov 2022 07:30:33 +0000 Subject: [PATCH 11/14] Rename 'c to 'b --- agb/src/display/font.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/agb/src/display/font.rs b/agb/src/display/font.rs index d8a16b12..cd627306 100644 --- a/agb/src/display/font.rs +++ b/agb/src/display/font.rs @@ -85,10 +85,10 @@ pub struct TextRenderer<'a> { /// Generated from the renderer for use /// with `Write` trait methods. -pub struct TextWriter<'a, 'c> { +pub struct TextWriter<'a, 'b> { foreground_colour: u8, background_colour: u8, - text_renderer: &'a mut TextRenderer<'c>, + text_renderer: &'a mut TextRenderer<'b>, vram_manager: &'a mut VRamManager, bg: &'a mut RegularMap, } @@ -118,14 +118,14 @@ fn div_ceil(quotient: i32, divisor: i32) -> i32 { (quotient + divisor - 1) / divisor } -impl<'a, 'c> TextRenderer<'c> { +impl<'a, 'b> TextRenderer<'b> { pub fn writer( &'a mut self, foreground_colour: u8, background_colour: u8, bg: &'a mut RegularMap, vram_manager: &'a mut VRamManager, - ) -> TextWriter<'a, 'c> { + ) -> TextWriter<'a, 'b> { TextWriter { text_renderer: self, foreground_colour, From 212fd3210867335915cdc994d49c5efd16f66e18 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Nov 2022 07:37:03 +0000 Subject: [PATCH 12/14] Remember to clear the renderer --- agb/examples/text_render.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/agb/examples/text_render.rs b/agb/examples/text_render.rs index e9289f3c..9f38f6b5 100644 --- a/agb/examples/text_render.rs +++ b/agb/examples/text_render.rs @@ -64,5 +64,7 @@ fn main(mut gba: agb::Gba) -> ! { vblank.wait_for_vblank(); bg.commit(&mut vram); + + renderer.clear(&mut vram); } } From 77275e27189d2a82df8435d4cd60b1dddb15088a Mon Sep 17 00:00:00 2001 From: jem Date: Mon, 21 Nov 2022 21:50:43 +0000 Subject: [PATCH 13/14] add in asserts for palette indicies --- agb/src/display/font.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/agb/src/display/font.rs b/agb/src/display/font.rs index cd627306..7f4df874 100644 --- a/agb/src/display/font.rs +++ b/agb/src/display/font.rs @@ -144,6 +144,9 @@ impl<'a, 'b> TextRenderer<'b> { foreground_colour: u8, background_colour: u8, ) { + assert!(foreground_colour < 16); + assert!(background_colour < 16); + let x_start = (self.current_x_pos + i32::from(letter.xmin)).max(0); let y_start = self.current_y_pos + self.font.ascent - i32::from(letter.height) From e8282fd2b589068cbdbde5db93d6e62e0c50e32e Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Nov 2022 23:06:04 +0000 Subject: [PATCH 14/14] Add changelog entry for text render rework --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 612cf105..11497da3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- Text renderer can now be re-used which is useful for rpg style character/word at a time text boxes. + ## [0.12.2] - 2022/10/22 This is a minor release to fix an alignment issue with background tiles.