diff --git a/Cargo.toml b/Cargo.toml
index 83da5b0..5bb18e5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,8 +7,8 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-ansi_term = "0.12"
bincode = "1.3.1"
+crossterm = "0.18"
decorum = "0.3"
dyn-clone = "1.0"
enum_dispatch = "0.3"
@@ -22,10 +22,11 @@ ndarray = { version = "0.13", features = ["rayon", "serde"] }
piecewise-linear = "0.1"
plotly = { version = "0.6", features = ["kaleido", "plotly_ndarray"], path = "../plotly/plotly" }
serde = "1.0"
-serde_cbor = "0.11"
structopt = "0.3"
threadpool = "1.8"
y4m = "0.7"
+# ansi_term = "0.12"
+# serde_cbor = "0.11"
[dev-dependencies]
criterion = "0.3"
diff --git a/src/bin/viewer.rs b/src/bin/viewer.rs
index 2daa4a5..92d6a9c 100644
--- a/src/bin/viewer.rs
+++ b/src/bin/viewer.rs
@@ -1,10 +1,12 @@
-use coremem::StaticSim;
+use coremem::{GenericSim as _, StaticSim};
use coremem::render::{ColorTermRenderer, Renderer as _};
use std::fs::{File, read_dir};
-use std::io::BufReader;
+use std::io::{BufReader, Read as _, stdin};
+use std::ops::Deref;
use std::path::{Path, PathBuf};
use structopt::StructOpt;
+use crossterm::event::{Event, KeyCode};
#[derive(Debug, StructOpt)]
struct Opt {
@@ -16,6 +18,14 @@ struct Frame {
data: StaticSim,
}
+impl Deref for Frame {
+ type Target = StaticSim;
+ fn deref(&self) -> &Self::Target {
+ &self.data
+ }
+}
+
+#[derive(Default)]
struct Loader {
dir: PathBuf,
}
@@ -51,12 +61,46 @@ impl Loader {
struct Viewer {
viewing: Option,
z: u32,
+ loader: Loader,
renderer: ColorTermRenderer,
}
impl Viewer {
- fn switch_frame(&mut self, frame: Frame) {
- self.viewing = Some(frame);
+ fn prev_frame(&mut self) {
+ println!("");
+ }
+ fn next_frame(&mut self) {
+ let next_frame = self.loader.load_next(self.viewing.as_ref());
+ if next_frame.is_some() {
+ self.viewing = next_frame;
+ self.render();
+ } else {
+ println!("");
+ }
+ }
+ fn prev_depth(&mut self) {
+ match self.z {
+ 0 => {
+ println!("");
+ },
+ _ => {
+ self.z -= 1;
+ self.render();
+ }
+ }
+ }
+ fn next_depth(&mut self) {
+ match self.z {
+ z if z+1 < self.viewing.as_ref().map(|f| f.depth()).unwrap_or(0) => {
+ self.z += 1;
+ self.render();
+ },
+ _ => {
+ println!("");
+ }
+ }
+ }
+ fn render(&self) {
self.renderer.render_z_slice(self.viewing.as_ref().map(|f| &f.data).unwrap(), self.z, &[]);
}
}
@@ -65,6 +109,25 @@ fn main() {
let opt = Opt::from_args();
let loader = Loader::new(opt.directory);
let mut viewer = Viewer::default();
- let frame = loader.load_next(None);
- viewer.switch_frame(frame.unwrap());
+ viewer.loader = loader;
+ //let frame = loader.load_next(None);
+ //viewer.switch_frame(frame.unwrap());
+
+ // disable line buffering
+ crossterm::terminal::enable_raw_mode().unwrap();
+ loop {
+ match crossterm::event::read().unwrap() {
+ Event::Key(e) => match e.code {
+ KeyCode::Left => viewer.prev_frame(),
+ KeyCode::Right => viewer.next_frame(),
+ KeyCode::Up => viewer.prev_depth(),
+ KeyCode::Down => viewer.next_depth(),
+ KeyCode::Char('q') => break,
+ _ => {},
+ },
+ _ => {},
+ }
+ }
+ // otherwise terminal is left in a wacky state
+ crossterm::terminal::disable_raw_mode().unwrap();
}
diff --git a/src/render.rs b/src/render.rs
index f95d496..164cc05 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -1,16 +1,17 @@
-use ansi_term::Color::RGB;
use crate::geom::{Index, Meters, Vec2, Vec3, Vec3u};
use crate::{flt::{Flt, Real}, Material as _};
use crate::mat;
use crate::sim::{Cell, GenericSim};
use crate::meas::AbstractMeasurement;
+use crossterm::{cursor, ExecutableCommand as _, QueueableCommand as _};
+use crossterm::style::{style, Color, PrintStyledContent, StyledContent as _};
use font8x8::{BASIC_FONTS, GREEK_FONTS, UnicodeFonts as _};
use log::{trace, info};
use plotly;
use image::{RgbImage, Rgb};
use imageproc::{pixelops, drawing};
use std::fs::File;
-use std::io::BufWriter;
+use std::io::{BufWriter, Write as _};
use std::path::PathBuf;
use std::sync::{Mutex, RwLock};
use y4m;
@@ -274,17 +275,25 @@ pub struct ColorTermRenderer;
impl Renderer for ColorTermRenderer {
fn render_with_image(&self, _state: &dyn GenericSim, im: &RgbImage) {
- let square = "█";
- let buf: String = im
- .enumerate_rows()
- .map(|(_y, row)| {
- format!("{}\n", row.map(|(_x, _y, p)| {
- format!("{}", RGB(p.0[0], p.0[1], p.0[2]).paint(square))
- }).collect::())
- })
- .collect();
-
- println!("{}", buf);
+ // TODO: should scale the image to the size of the terminal!
+ let mut stdout = std::io::stdout();
+ let (w, h) = crossterm::terminal::size().unwrap();
+ stdout.queue(cursor::MoveTo(0, 0));
+ for (y, row) in im.enumerate_rows() {
+ if y >= h.into() {
+ break;
+ }
+ stdout.queue(cursor::MoveDown(1));
+ stdout.queue(cursor::MoveToColumn(0));
+ for (_x, _y, p) in row {
+ stdout.queue(PrintStyledContent(style(" ").on(Color::Rgb {
+ r: p.0[0],
+ g: p.0[1],
+ b: p.0[2],
+ })));
+ }
+ }
+ stdout.flush();
}
}