From 9b0dff82215da7dfcefcea12862d18faab55bb91 Mon Sep 17 00:00:00 2001 From: Akshay Date: Mon, 15 Mar 2021 10:55:44 +0530 Subject: ui changes: symmetry lines and brush size indicator --- src/app.rs | 128 ++++++++++++++++++++++++++++++---------------------------- src/consts.rs | 14 ++++--- src/main.rs | 1 + 3 files changed, 76 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/app.rs b/src/app.rs index 695d097..03389fb 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,9 +1,11 @@ use crate::{ - bitmap::{Axis, MapPoint, Pixmap}, + bitmap::{MapPoint, Pixmap}, + consts::{colors::*, FONT_PATH}, + symmetry::Symmetry, undo::{ModifyRecord, OpKind, Operation, UndoStack}, }; -use std::convert::From; +use std::convert::{From, TryFrom}; use sdl2::{ event::Event, @@ -11,7 +13,7 @@ use sdl2::{ mouse::MouseButton, pixels::Color, rect::{Point, Rect}, - render::{Canvas, Texture}, + render::Canvas, ttf::Sdl2TtfContext, video::Window, Sdl, @@ -23,8 +25,6 @@ macro_rules! quick_rect( ) ); -use crate::consts::{BLACK, FONT_PATH, GRID_COLOR, WHITE}; - pub struct AppState<'ctx> { active_color: bool, brush_size: u8, @@ -47,12 +47,6 @@ struct Grid { color: Color, } -#[derive(Debug, Default, Copy, Clone)] -struct Symmetry { - x: Option, - y: Option, -} - impl Grid { fn new() -> Self { Self { @@ -133,25 +127,6 @@ impl<'ctx> AppState<'ctx> { } } - fn apply_symmetry(&self, figure: &[MapPoint]) -> Vec { - let Symmetry { x, y } = self.symmetry; - match (x, y) { - (None, None) => vec![], - (Some(line), None) => self.pixmap.mirror_figure(figure, line, Axis::X), - (None, Some(line)) => self.pixmap.mirror_figure(figure, line, Axis::Y), - (Some(x), Some(y)) => { - let along_x = self.pixmap.mirror_figure(figure, x, Axis::X); - let along_y = self.pixmap.mirror_figure(figure, y, Axis::Y); - let reflected = self.pixmap.reflect_figure(figure, (x, y).into()); - along_x - .into_iter() - .chain(along_y) - .chain(reflected) - .collect() - } - } - } - fn paint_point>( &mut self, center: P, @@ -159,9 +134,12 @@ impl<'ctx> AppState<'ctx> { ) -> Result, ()> { let radius = self.brush_size as u32; let center = self.idx_at_coord(center).ok_or(())?; + + let circle = self.pixmap.get_circle(center, radius, true); + let sym_circle = self.symmetry.apply(&circle); + let mut modify_record = vec![]; - let circle = self.pixmap.get_circle(center, radius); - let sym_circle = self.apply_symmetry(&circle); + for point in circle.into_iter().chain(sym_circle) { let old_val = self.pixmap.set(point, val); modify_record.push(ModifyRecord::new(point, old_val, val)); @@ -169,15 +147,21 @@ impl<'ctx> AppState<'ctx> { Ok(modify_record) } - fn paint_line>(&mut self, start: P, end: P) -> Result, ()> { + fn paint_line>( + &mut self, + start: P, + end: P, + val: bool, + ) -> Result, ()> { let start = self.idx_at_coord(start).ok_or(())?; let end = self.idx_at_coord(end).ok_or(())?; + let line = self.pixmap.get_line(start, end); - let sym_line = self.apply_symmetry(&line); + let sym_line = self.symmetry.apply(&line); + let mut line_modify_record = vec![]; - let val = self.active_color; for point in line.into_iter().chain(sym_line) { - let circle_around_point = self.pixmap.get_circle(point, self.brush_size as u32); + let circle_around_point = self.pixmap.get_circle(point, self.brush_size as u32, true); for c in circle_around_point { let old_val = self.pixmap.set(c, val); line_modify_record.push(ModifyRecord::new(c, old_val, val)); @@ -283,30 +267,15 @@ impl<'ctx> AppState<'ctx> { status_height )) .unwrap(); - let symmetry_symbol = match self.symmetry { - Symmetry { x: None, y: None } => "", - Symmetry { - x: Some(_), - y: None, - } => "-", - Symmetry { - x: None, - y: Some(_), - } => "|", - Symmetry { - x: Some(_), - y: Some(_), - } => "+", - }; let mouse_coords = if let Some((x, y)) = self.idx_at_coord(self.mouse) { format!("{:3}, {:3}", x, y) } else { - format!("--, --") + format!("---, ---") }; let status_text = format!( - "[BRUSH {}] [SYM {:1}] {}", + "[BRUSH {}] [SYM {}] {}", self.brush_size + 1, - symmetry_symbol, + self.symmetry, mouse_coords ); draw_text( @@ -318,32 +287,67 @@ impl<'ctx> AppState<'ctx> { ); } + fn draw_mouse(&mut self) { + let brush_size = self.brush_size; + let cs = self.zoom as u32; + let pt = self.idx_at_coord(self.mouse); + if let Some(center) = pt { + let circle = self.pixmap.get_circle(center, brush_size as u32, false); + for MapPoint { x, y } in circle.into_iter() { + self.canvas.set_draw_color(GREY); + self.canvas + .fill_rect(Rect::new( + x as i32 * cs as i32 + self.start.x(), + y as i32 * cs as i32 + self.start.y(), + cs, + cs, + )) + .unwrap(); + } + } + } + fn draw(&mut self) { let cs = self.zoom as u32; let (width, height) = (self.width(), self.height()); let start = self.start; - let canvas = &mut self.canvas; + let grid_enabled = self.grid.enabled; + let (winsize_x, winsize_y) = self.canvas.window().size(); + let Symmetry { x: sym_x, y: sym_y } = self.symmetry; for (idx, val) in self.pixmap.data.iter().enumerate() { if *val { let idx = idx as i32; let (x, y) = (idx % width as i32, idx / height as i32); - canvas.set_draw_color(WHITE); - canvas + self.canvas.set_draw_color(WHITE); + self.canvas .fill_rect(Rect::new( - // start drawing 1 pixel after the grid line x * cs as i32 + start.x(), y * cs as i32 + start.y(), - // stop drawing 1 pixel before the grid line cs, cs, )) .unwrap(); } } - if self.grid.enabled { + if grid_enabled { self.draw_grid(); } + if let Some(line) = sym_x { + self.canvas.set_draw_color(CYAN); + let line_coord = (line * cs) as i32 + self.start.y() + (cs / 2) as i32; + self.canvas + .draw_line((0, line_coord), (winsize_x as i32, line_coord)) + .unwrap(); + } + if let Some(line) = sym_y { + self.canvas.set_draw_color(CYAN); + let line_coord = (line * cs) as i32 + self.start.x() + (cs / 2) as i32; + self.canvas + .draw_line((line_coord, 0), (line_coord, winsize_y as i32)) + .unwrap(); + } self.draw_statusline(); + self.draw_mouse(); } fn redraw(&mut self) { @@ -439,7 +443,7 @@ impl<'ctx> AppState<'ctx> { Keycode::F => { let end = (mouse.x(), mouse.y()).into(); if let Some(start) = self.last_point { - if let Ok(o) = self.paint_line(start, end) { + if let Ok(o) = self.paint_line(start, end, self.active_color) { self.commit_operation(); self.current_operation = o.into_iter().filter(|v| !v.old_val == v.val).collect(); @@ -535,5 +539,5 @@ fn draw_text>( .unwrap(); let (width, height) = font.size_of_latin1(text.as_bytes()).unwrap(); let area = quick_rect!(x, y, width, height); - canvas.copy(&texture, None, area); + canvas.copy(&texture, None, area).unwrap(); } diff --git a/src/consts.rs b/src/consts.rs index 8c90693..2f7576e 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,7 +1,11 @@ -use sdl2::pixels::Color; - -pub const GRID_COLOR: Color = Color::RGB(64, 64, 64); -pub const WHITE: Color = Color::RGB(255, 255, 255); -pub const BLACK: Color = Color::RGB(0, 0, 0); +pub mod colors { + use sdl2::pixels::Color; + pub const GRID_COLOR: Color = Color::RGB(64, 64, 64); + pub const WHITE: Color = Color::RGB(255, 255, 255); + pub const BLACK: Color = Color::RGB(0, 0, 0); + pub const GREY: Color = Color::RGB(127, 127, 127); + pub const CYAN: Color = Color::RGB(121, 255, 225); + pub const PINK: Color = Color::RGB(255, 50, 153); +} pub const FONT_PATH: &'static str = "./assets/NerdInput-Regular.ttf"; diff --git a/src/main.rs b/src/main.rs index bd0590e..1aaa954 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod app; mod bitmap; mod consts; +mod symmetry; mod undo; use app::AppState; -- cgit v1.2.3