diff options
| author | Mica White <botahamec@outlook.com> | 2026-06-17 17:41:28 -0400 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2026-06-17 17:41:28 -0400 |
| commit | b9570962cfc214bbac0f3fef1e6c1f9848f52658 (patch) | |
| tree | 4c131b0208b394f7c10d395c3a6e72f91b0a57fc /src/buffer.rs | |
| parent | 0403d02e376fd0b95abe2f06ffbf836dd2a8ddf0 (diff) | |
Basic renderer and framerate test
Diffstat (limited to 'src/buffer.rs')
| -rw-r--r-- | src/buffer.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/buffer.rs b/src/buffer.rs new file mode 100644 index 0000000..fa0feaa --- /dev/null +++ b/src/buffer.rs @@ -0,0 +1,92 @@ +use std::io::Write; + +use crossterm::{ + cursor::{Hide, MoveTo, Show}, + event::{self, Event}, + execute, + style::{ContentStyle, PrintStyledContent, StyledContent}, + terminal::{ + BeginSynchronizedUpdate, Clear, ClearType, EndSynchronizedUpdate, EnterAlternateScreen, + LeaveAlternateScreen, WindowSize, disable_raw_mode, enable_raw_mode, window_size, + }, +}; + +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)] +pub struct Cell { + pub character: char, + pub style: ContentStyle, + pub x: u16, + pub y: u16, + pub z: u8, +} + +#[derive(Debug)] +pub struct Buffer<'a, W: Write> { + stdout: &'a mut W, + pub cells: Vec<Cell>, + pub window_size: WindowSize, +} + +impl<'a, W: Write> Buffer<'a, W> { + pub fn new(stdout: &'a mut W) -> std::io::Result<Self> { + Ok(Self { + stdout, + cells: Vec::new(), + window_size: window_size()?, + }) + } + + fn initialize(writer: &mut impl Write) -> std::io::Result<()> { + enable_raw_mode()?; + execute!(writer, Hide, EnterAlternateScreen)?; + Ok(()) + } + + fn render(&mut self) -> std::io::Result<()> { + self.cells.sort_unstable_by_key(|cell| cell.z); + execute!(self.stdout, BeginSynchronizedUpdate, Clear(ClearType::All))?; + for cell in &self.cells { + execute!( + self.stdout, + MoveTo(cell.x, cell.y), + PrintStyledContent(StyledContent::new(cell.style, cell.character)) + )?; + } + execute!(self.stdout, EndSynchronizedUpdate)?; + Ok(()) + } + + pub fn finish(&mut self) -> std::io::Result<()> { + execute!(self.stdout, Show, LeaveAlternateScreen)?; + disable_raw_mode()?; + Ok(()) + } + + pub fn render_loop( + &mut self, + mut event_handler: impl FnMut(&mut Self, Event), + mut update: impl FnMut(&mut Self), + ) -> std::io::Result<()> { + Self::initialize(self.stdout)?; + let (sender, receiver) = std::sync::mpsc::channel(); + std::thread::scope(|scope| -> std::io::Result<()> { + scope.spawn(|| { + loop { + let Ok(event) = event::read() else { + continue; + }; + let _ = sender.send(event); + } + }); + loop { + while let Ok(event) = receiver.try_recv() { + event_handler(self, event); + } + update(self); + self.render()?; + } + })?; + self.finish()?; + Ok(()) + } +} |
