Browse Source

Experimental renderer complete

master
Graham Northup 3 years ago
parent
commit
34c181d446
Signed by untrusted user: grissess GPG Key ID: 5D000E6F539376FB
  1. 148
      src/world/render.rs

148
src/world/render.rs

@ -1,6 +1,7 @@
use super::*;
use std::fmt::Debug;
use std::io::{self, Write};
use rogue_util::coord::*;
use rogue_util::grid::region::Region;
@ -11,6 +12,22 @@ pub struct Neighbors<'a, T: Debug> {
dl: &'a T, d: &'a T, dr: &'a T,
}
impl<'a, T: Debug + Default> Neighbors<'a, T> {
pub fn from_region_pos<'r: 'a>(r: &'r Region<T>, p: V2i, def: &'a T) -> Neighbors<'a, T> {
Neighbors {
ul: r.get(p + V2i(-1, -1)).unwrap_or(def),
u: r.get(p + V2i(0, -1)).unwrap_or(def),
ur: r.get(p + V2i(1, -1)).unwrap_or(def),
l: r.get(p + V2i(-1, 0)).unwrap_or(def),
this: r.get(p).unwrap_or(def),
r: r.get(p + V2i(1, 0)).unwrap_or(def),
dl: r.get(p + V2i(-1, 1)).unwrap_or(def),
d: r.get(p + V2i(0, 1)).unwrap_or(def),
dr: r.get(p + V2i(1, 1)).unwrap_or(def),
}
}
}
impl<'a, T: Debug> Neighbors<'a, T> {
pub fn for_each<F>(&self, mut f: F)
where
@ -41,6 +58,19 @@ impl Renderer for BasicRenderer {
}
}
pub struct InvertRenderer;
impl Renderer for InvertRenderer {
type Tile = Tile;
fn render<'a, 's: 'a>(&'s mut self, neighbors: Neighbors<'a, Tile>) -> char {
match neighbors.this.content {
Content::Air => ' ',
Content::Stone => '#',
}
}
}
pub struct EdgeRenderer;
impl Renderer for EdgeRenderer {
@ -85,7 +115,121 @@ impl RenderState {
self.center = c;
}
pub fn render(&self, r: &Region<Tile>) {
// TODO
pub fn screen_rect(&self) -> R2i {
let halfsize = self.term_size / V2i(2, 2);
R2i::origin_dim(self.center - halfsize, self.term_size)
}
pub fn render<R, W>(&self, region: &Region<Tile>, renderer: &mut R, out: &mut W) -> io::Result<()>
where
R: Renderer<Tile=Tile>,
W: Write
{
let screen = self.screen_rect();
write!(out, "{}{}",
termion::clear::All,
termion::cursor::Goto(1, 1),
)?;
let mut last_pt: Option<V2i> = None;
let def_tile = Tile::default();
for pt in &screen {
if let Some(l) = last_pt {
if l.1 != pt.1 {
write!(out, "\r\n")?;
}
}
last_pt = Some(pt);
write!(out, "{}", renderer.render(
Neighbors::from_region_pos(region, pt, &def_tile)
))?;
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
use rogue_util::grid::region::RegionConfig;
fn make_test_renderer() -> io::Result<RenderState> {
let (w, h) = termion::terminal_size()?;
Ok(RenderState::new(V2i(w as isize, h as isize)))
}
fn make_test_region() -> Region<Tile> {
RegionConfig::<Tile>::default().build().expect("Failed to make Region")
}
fn draw_line(rg: &mut Region<Tile>) {
let gs = rg.grid_size();
for pt in rogue_util::raster::line(V2i(3, 2), V2i(gs.0 - 1, gs.1 / 2)) {
rg.get_mut(pt).content = Content::Air;
}
}
#[test]
fn render_default_region() -> io::Result<()> {
let rs = make_test_renderer()?;
let rg = make_test_region();
let mut out = io::stdout();
rs.render(&rg, &mut BasicRenderer, &mut out)
}
#[test]
fn render_full_region() -> io::Result<()> {
let rs = make_test_renderer()?;
let mut rg = make_test_region();
for pt in &R2i::origin_dim(V2i(0, 0), rg.grid_size()) {
rg.get_mut(pt).content = Content::Air;
}
let mut out = io::stdout();
rs.render(&rg, &mut BasicRenderer, &mut out)
}
#[test]
fn render_line_region_basic() -> io::Result<()> {
let rs = make_test_renderer()?;
let mut rg = make_test_region();
draw_line(&mut rg);
let mut out = io::stdout();
rs.render(&rg, &mut BasicRenderer, &mut out)
}
#[test]
fn render_line_region_edge() -> io::Result<()> {
let rs = make_test_renderer()?;
let mut rg = make_test_region();
draw_line(&mut rg);
let mut out = io::stdout();
rs.render(&rg, &mut EdgeRenderer, &mut out)
}
#[test]
fn render_line_region_invert() -> io::Result<()> {
let rs = make_test_renderer()?;
let mut rg = make_test_region();
draw_line(&mut rg);
let mut out = io::stdout();
rs.render(&rg, &mut InvertRenderer, &mut out)
}
}
Loading…
Cancel
Save