Browse Source

Added alternative pen modes

master
Thomas Johnson 3 years ago
parent
commit
89c7e85283
  1. 8
      src/grid.rs
  2. 115
      src/head.rs
  3. 32
      src/main.rs

8
src/grid.rs

@ -101,12 +101,12 @@ impl Cell {
self.dirs = [false; 4];
}
pub fn draw_to_center(&mut self, from: Direction) {
self.dirs[from as usize] = true;
pub fn draw_to_center(&mut self, from: Direction, state: bool) {
self.dirs[from as usize] = state;
}
pub fn draw_from_center(&mut self, to: Direction) {
self.dirs[to as usize] = true;
pub fn draw_from_center(&mut self, to: Direction, state: bool) {
self.dirs[to as usize] = state;
}
pub fn to_char(&self) -> char {

115
src/head.rs

@ -5,10 +5,19 @@ use core::cell::RefCell;
use crate::grid::{add_v2, Grid, Direction};
#[derive(Clone, Copy, Debug)]
pub enum HeadMode {
Pen(),
Unmarker(),
Eraser(),
BlockEraser((isize, isize)),
}
#[derive(Clone, Debug)]
pub struct Head<G: Clone + Debug> {
grid: G,
down: bool,
mode: HeadMode,
coords: (isize, isize),
}
@ -18,20 +27,71 @@ G: Clone + Debug + Deref<Target=RefCell<Grid>> {
Self {
grid,
down: true,
mode: HeadMode::Pen(),
coords,
}
}
pub fn pen_mode(&mut self) {
self.mode = HeadMode::Pen();
}
pub fn go(&mut self, dir: Direction) {
pub fn unmarker_mode(&mut self) {
self.mode = HeadMode::Unmarker();
}
pub fn eraser_mode(&mut self) {
self.mode = HeadMode::Eraser();
}
pub fn block_eraser_mode(&mut self) {
self.mode = HeadMode::BlockEraser(self.coords);
}
pub fn mode(&self) -> HeadMode {
self.mode
}
pub fn visibility_box(&self) -> Box2 {
match self.mode {
_ if !self.down => Box2(self.coords.0, self.coords.1, 1, 1),
HeadMode::Pen() | HeadMode::Unmarker() | HeadMode::Eraser() => Box2(self.coords.0, self.coords.1, 1, 1),
HeadMode::BlockEraser(corner) => Box2::from_contained_corners(self.coords, corner),
}
}
pub fn is_down(&self) -> bool {
self.down
}
fn do_leading(&mut self, dir: Direction) {
if self.down && self.grid.borrow().in_bounds(self.coords) {
self.grid.borrow_mut()[self.coords].draw_from_center(dir);
match self.mode {
HeadMode::Pen() => self.grid.borrow_mut()[self.coords].draw_from_center(dir, true),
HeadMode::Unmarker() => self.grid.borrow_mut()[self.coords].draw_from_center(dir, false),
HeadMode::Eraser() => (),
HeadMode::BlockEraser(_) => (),
}
}
self.coords = add_v2(self.coords, dir.offset());
}
fn do_trailing(&mut self, dir: Direction) {
if self.down && self.grid.borrow().in_bounds(self.coords) {
self.grid.borrow_mut()[self.coords].draw_to_center(dir.opposite());
match self.mode {
HeadMode::Pen() => self.grid.borrow_mut()[self.coords].draw_to_center(dir.opposite(), true),
HeadMode::Unmarker() => self.grid.borrow_mut()[self.coords].draw_to_center(dir.opposite(), false),
HeadMode::Eraser() => self.grid.borrow_mut()[self.coords].reset(),
HeadMode::BlockEraser(_) => (),
}
}
}
pub fn go(&mut self, dir: Direction) {
self.do_leading(dir);
self.coords = add_v2(self.coords, dir.offset());
self.do_trailing(dir);
}
pub fn checked_go(&mut self, dir: Direction) -> bool {
if self.grid.borrow().in_bounds(add_v2(self.coords, dir.offset())) {
self.go(dir);
@ -43,14 +103,27 @@ G: Clone + Debug + Deref<Target=RefCell<Grid>> {
pub fn up(&mut self) {
self.down = false;
if let HeadMode::BlockEraser(corner) = self.mode() {
let mut gr = self.grid.borrow_mut();
Box2::from_contained_corners(corner, self.coords).foreach(|zap| {
gr[zap].reset();
})
}
}
pub fn down(&mut self) {
self.down = true;
if let HeadMode::BlockEraser(_) = self.mode() {
self.mode = HeadMode::BlockEraser(self.coords);
}
}
pub fn toggle_down(&mut self) {
self.down = !self.down;
if self.down {
self.up()
} else {
self.down()
}
}
pub fn coords(&self) -> (isize, isize) {
@ -61,3 +134,35 @@ G: Clone + Debug + Deref<Target=RefCell<Grid>> {
self.coords = coords;
}
}
pub struct Box2(isize, isize, usize, usize);
impl Box2 {
pub fn lower_left(&self) -> (isize, isize) {
(self.0, self.1)
}
pub fn upper_right(&self) -> (isize, isize) {
(self.0 + self.2 as isize, self.1 + self.3 as isize)
}
pub fn from_contained_corners(a: (isize, isize), b: (isize, isize)) -> Self {
let ll = (isize::min(a.0, b.0), isize::min(a.1, b.1));
let size = ((a.0 - b.0).abs() as usize + 1, (a.1 - b.1).abs() as usize + 1);
Self(ll.0, ll.1, size.0, size.1)
}
pub fn contains(&self, point: (isize, isize)) -> bool {
(self.0..(self.0 + self.2 as isize)).contains(&point.0)
&& (self.1..(self.1 + self.3 as isize)).contains(&point.1)
}
pub fn foreach<F: FnMut((isize, isize))>(&self, mut f: F) {
for x in self.0..(self.0 + self.2 as isize) {
for y in self.1..(self.1 + self.3 as isize) {
f((x, y))
}
}
}
}

32
src/main.rs

@ -9,7 +9,30 @@ use core::cell::RefCell;
use crate::grid::{Grid, Direction::*};
use crate::head::Head;
use termion::{raw::IntoRawMode, input::TermRead, event::Key, cursor::Goto};
use termion::{raw::IntoRawMode, input::TermRead, event::Key, cursor::Goto, color::{Black, Bg, AnsiValue}};
fn draw_grid_with_head(grid: &Grid, head: &Head<Rc<RefCell<Grid>>>) {
let mut s = String::new();
let mut bg_on = false;
let vb = head.visibility_box();
for y in 0..grid.dims().1 {
for x in 0..grid.dims().0 {
let real_coords = (x as isize - grid.origin().0, y as isize - grid.origin().1);
let head_visible = vb.contains(real_coords);
if bg_on && !head_visible {
s.push_str(&format!("{}", Bg(Black)));
bg_on = false;
}
if !bg_on && head_visible {
s.push_str(&format!("{}", Bg(AnsiValue::rgb(0, 0, 1))));
bg_on = true;
}
s.push(grid[real_coords].to_char());
}
s.push_str("\r\n");
}
print!("{}", s);
}
fn main() {
if !termion::is_tty(&std::io::stdout()) {
@ -21,7 +44,8 @@ fn main() {
let grid = Rc::new(RefCell::new(Grid::new((dims.0 as usize, dims.1 as usize), (dims.0 as isize / 2, dims.1 as isize / 2))));
let mut head = Head::new_at(grid.clone(), (0, 0));
loop {
print!("{}{}", Goto(1, 1), grid.borrow().to_2d_string());
print!("{}", Goto(1, 1));
draw_grid_with_head(&*grid.borrow(), &head);
let key = keys.next();
if let Some(Ok(key)) = key {
match key.clone() {
@ -35,6 +59,10 @@ fn main() {
};
head.go(dir);
}
Key::Char('p') => head.pen_mode(),
Key::Char('u') => head.unmarker_mode(),
Key::Char('e') => head.eraser_mode(),
Key::Char('b') => head.block_eraser_mode(),
Key::Char('\n') => head.toggle_down(),
Key::Char('q') => break,
_ => {}

Loading…
Cancel
Save