mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-11-17 21:46:39 +00:00
Add renderer and mocks
This commit is contained in:
parent
26f4960276
commit
43cecf57b3
@ -10,4 +10,5 @@ repository = "https://github.com/ricoriedel/wipe"
|
|||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
clap = { version = "3.1", features = ["derive"]}
|
clap = { version = "3.1", features = ["derive"]}
|
||||||
crossterm = "0.23"
|
crossterm = "0.23"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
mockall = "0.11"
|
11
src/main.rs
11
src/main.rs
@ -10,6 +10,7 @@ use crate::color::{ColorSampler, SimpleColorSampler};
|
|||||||
use crate::fill::circle::CircleFillMode;
|
use crate::fill::circle::CircleFillMode;
|
||||||
use crate::fill::FillMode;
|
use crate::fill::FillMode;
|
||||||
use crate::fill::level::LevelFillMode;
|
use crate::fill::level::LevelFillMode;
|
||||||
|
use crate::render::{Renderer, SamplerRenderer};
|
||||||
use crate::sampler::ComposedSampler;
|
use crate::sampler::ComposedSampler;
|
||||||
use crate::surface::WriteSurface;
|
use crate::surface::WriteSurface;
|
||||||
use crate::vec::Vector;
|
use crate::vec::Vector;
|
||||||
@ -22,6 +23,7 @@ mod array;
|
|||||||
mod surface;
|
mod surface;
|
||||||
mod animation;
|
mod animation;
|
||||||
mod sampler;
|
mod sampler;
|
||||||
|
mod render;
|
||||||
|
|
||||||
#[derive(Copy, Clone, ArgEnum)]
|
#[derive(Copy, Clone, ArgEnum)]
|
||||||
enum AnimationType {
|
enum AnimationType {
|
||||||
@ -76,8 +78,13 @@ fn main() -> Result<(), Error> {
|
|||||||
let color = create_color(args.color[0]);
|
let color = create_color(args.color[0]);
|
||||||
let char = Box::new(SimpleCharSampler::new(args.chars));
|
let char = Box::new(SimpleCharSampler::new(args.chars));
|
||||||
|
|
||||||
let _ = Box::new(ComposedSampler::new(animation, fill, color, char));
|
let sampler = Box::new(ComposedSampler::new(animation, fill, color, char));
|
||||||
let _ = Box::new(WriteSurface::new(stdout(), width, height));
|
let surface = Box::new(WriteSurface::new(stdout(), width, height));
|
||||||
|
|
||||||
|
let mut renderer = Box::new(SamplerRenderer::new(surface, sampler));
|
||||||
|
|
||||||
|
renderer.render(0.5);
|
||||||
|
renderer.present()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
87
src/render.rs
Normal file
87
src/render.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
use anyhow::Error;
|
||||||
|
use crate::sampler::{Sample, Sampler};
|
||||||
|
use crate::surface::Surface;
|
||||||
|
use crate::Vector;
|
||||||
|
|
||||||
|
pub trait Renderer {
|
||||||
|
fn render(&mut self, step: f32);
|
||||||
|
fn present(&mut self) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SamplerRenderer {
|
||||||
|
surface: Box<dyn Surface>,
|
||||||
|
sampler: Box<dyn Sampler>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SamplerRenderer {
|
||||||
|
pub fn new(surface: Box<dyn Surface>,
|
||||||
|
sampler: Box<dyn Sampler>) -> Self {
|
||||||
|
Self { surface, sampler }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderer for SamplerRenderer {
|
||||||
|
fn render(&mut self, step: f32) {
|
||||||
|
for x in 0..self.surface.width() {
|
||||||
|
for y in 0..self.surface.height() {
|
||||||
|
let pos = Vector::from_terminal(x, y);
|
||||||
|
let sample = self.sampler.sample(step, pos);
|
||||||
|
|
||||||
|
match sample {
|
||||||
|
Sample::Keep => (),
|
||||||
|
Sample::Draw { char, color } => self.surface.draw(x, y, char, color),
|
||||||
|
Sample::Clear => self.surface.clear(x, y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn present(&mut self) -> Result<(), Error> {
|
||||||
|
self.surface.present()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crossterm::style::*;
|
||||||
|
use mockall::predicate::*;
|
||||||
|
use super::*;
|
||||||
|
use crate::surface::MockSurface;
|
||||||
|
use crate::sampler::MockSampler;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render() {
|
||||||
|
let mut surface = Box::new(MockSurface::new());
|
||||||
|
let mut sampler = Box::new(MockSampler::new());
|
||||||
|
|
||||||
|
sampler.expect_sample().withf(|_, pos| pos.x == 0.0 && pos.y == 0.0).returning(|_,_| Sample::Clear);
|
||||||
|
sampler.expect_sample().withf(|_, pos| pos.x == 1.0 && pos.y == 0.0).returning(|_,_| Sample::Keep);
|
||||||
|
sampler.expect_sample().withf(|_, pos| pos.x == 0.0 && pos.y == 2.0).returning(|_,_| Sample::Draw { char: 'a', color: Color::Red });
|
||||||
|
sampler.expect_sample().withf(|_, pos| pos.x == 1.0 && pos.y == 2.0).returning(|_,_| Sample::Keep);
|
||||||
|
sampler.expect_sample().withf(|_, pos| pos.x == 0.0 && pos.y == 4.0).returning(|_,_| Sample::Draw { char: 'x', color: Color::Yellow });
|
||||||
|
sampler.expect_sample().withf(|_, pos| pos.x == 1.0 && pos.y == 4.0).returning(|_,_| Sample::Clear);
|
||||||
|
|
||||||
|
surface.expect_width().return_const(2 as usize);
|
||||||
|
surface.expect_height().return_const(3 as usize);
|
||||||
|
surface.expect_clear().once().with(eq(0), eq(0)).return_const(());
|
||||||
|
surface.expect_draw().once().with(eq(0), eq(1), eq('a'), eq(Color::Red)).return_const(());
|
||||||
|
surface.expect_draw().once().with(eq(0), eq(2), eq('x'), eq(Color::Yellow)).return_const(());
|
||||||
|
surface.expect_clear().once().with(eq(1), eq(2)).return_const(());
|
||||||
|
|
||||||
|
let mut renderer = SamplerRenderer::new(surface, sampler);
|
||||||
|
|
||||||
|
renderer.render(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn present() {
|
||||||
|
let mut surface = Box::new(MockSurface::new());
|
||||||
|
let sampler = Box::new(MockSampler::new());
|
||||||
|
|
||||||
|
surface.expect_present().once().returning(|| Ok(()));
|
||||||
|
|
||||||
|
let mut renderer = SamplerRenderer::new(surface, sampler);
|
||||||
|
|
||||||
|
renderer.present().unwrap();
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
use crossterm::style::Color;
|
use crossterm::style::Color;
|
||||||
|
use mockall::automock;
|
||||||
use crate::animation::Animation;
|
use crate::animation::Animation;
|
||||||
use crate::char::CharSampler;
|
use crate::char::CharSampler;
|
||||||
use crate::color::ColorSampler;
|
use crate::color::ColorSampler;
|
||||||
@ -11,6 +12,7 @@ pub enum Sample {
|
|||||||
Clear,
|
Clear,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[automock]
|
||||||
pub trait Sampler {
|
pub trait Sampler {
|
||||||
fn sample(&self, step: f32, pos: Vector) -> Sample;
|
fn sample(&self, step: f32, pos: Vector) -> Sample;
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ use crossterm::cursor::MoveTo;
|
|||||||
use crossterm::{ExecutableCommand, QueueableCommand};
|
use crossterm::{ExecutableCommand, QueueableCommand};
|
||||||
use crossterm::style::{Color, Print, SetForegroundColor};
|
use crossterm::style::{Color, Print, SetForegroundColor};
|
||||||
use crossterm::terminal::{Clear, ClearType};
|
use crossterm::terminal::{Clear, ClearType};
|
||||||
|
use mockall::automock;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use crate::array::Array2D;
|
use crate::array::Array2D;
|
||||||
|
|
||||||
|
#[automock]
|
||||||
pub trait Surface {
|
pub trait Surface {
|
||||||
fn width(&self) -> usize;
|
fn width(&self) -> usize;
|
||||||
fn height(&self) -> usize;
|
fn height(&self) -> usize;
|
||||||
|
Loading…
Reference in New Issue
Block a user