From bfe6a86bd5b1d02988dbd9a3bb5759854d76a050 Mon Sep 17 00:00:00 2001 From: Akshay Date: Mon, 24 May 2021 22:27:41 +0530 Subject: basic primitives to repeat last paint op --- src/app.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/bitmap.rs | 13 ++++++++++++- src/lisp/prelude.rs | 9 +++++++++ src/undo.rs | 2 +- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/app.rs b/src/app.rs index 3e7ac0f..d8a6132 100644 --- a/src/app.rs +++ b/src/app.rs @@ -257,6 +257,40 @@ impl<'ctx> AppState<'ctx> { } } + pub fn repeat_last_paint(&mut self, target: MapPoint) { + self.commit_operation(); + if let Some(ModifyRecord::Paint(records)) = self + .undo_stack + .operations + .iter() + .rev() + .find(|&o| matches!(o, ModifyRecord::Paint(_))) + { + dbg!(target); + // find center of paint cluster + let centroid: MapPoint = records + .iter() + .fold(MapPoint { x: 0, y: 0 }, |acc, x| acc + x.point) + .reduce(records.len() as u32); + dbg!(centroid); + // re-center cluster around target + let centered_op = records + .iter() + .map(|x| PaintRecord { + point: x.point + target - centroid, + ..*x + }) + .collect::>(); + let mut ud = Vec::new(); + for r in ¢ered_op { + let p = r.point; + let v = r.new; + ud.push(PaintRecord::new(p, self.pixmap.set(p, v), v)); + } + self.undo_stack.push(ModifyRecord::Paint(ud)); + } + } + pub fn zoom_in(&mut self, p: (i32, i32)) { // attempt to center around cursor if let Some(p) = self.idx_at_coord(p) { @@ -774,6 +808,11 @@ impl<'ctx> AppState<'ctx> { let cursor = (mouse.x(), mouse.y()); self.zoom_out(cursor); } + Keycode::Period => { + if let Some(contact) = self.idx_at_coord(self.mouse) { + self.repeat_last_paint(contact.into()); + } + } // brush ops Keycode::Q => self.brush.shrink(), Keycode::E => self.brush.grow(), diff --git a/src/bitmap.rs b/src/bitmap.rs index ff41cb8..ffc0258 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -13,7 +13,7 @@ pub struct Pixmap { pub data: Vec, } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct MapPoint { pub x: u32, pub y: u32, @@ -110,6 +110,17 @@ impl MapPoint { } } + #[inline] + pub fn reduce(self, c: u32) -> MapPoint { + if c == 0 { + panic!("reduce MapPoint by zero") + } + MapPoint { + x: self.x / c, + y: self.y / c, + } + } + #[inline] pub fn mirror_about(self, line: u32, axis: Axis) -> MapPoint { let MapPoint { x, y } = self; diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs index dddce5f..ce3f97b 100644 --- a/src/lisp/prelude.rs +++ b/src/lisp/prelude.rs @@ -536,6 +536,15 @@ pub fn new_env() -> Result { ])) }); + primitive!(env, Arity::Exact(0), "active-color", |_, app| { + Ok(LispExpr::BoolLit(app.active_color)) + }); + + primitive!(env, Arity::Exact(1), "set-active-color!", |args, app| { + app.active_color = args[0].cast_bool(); + Ok(LispExpr::Unit) + }); + primitive!(env, Arity::Exact(2), "range", |args, _| { if type_match!( args, diff --git a/src/undo.rs b/src/undo.rs index 5effd79..f6c41ce 100644 --- a/src/undo.rs +++ b/src/undo.rs @@ -27,7 +27,7 @@ pub enum OpKind { #[derive(Debug)] pub struct UndoStack { - operations: Vec, + pub operations: Vec, position: Option, } -- cgit v1.2.3