diff options
Diffstat (limited to 'src/app.rs')
-rw-r--r-- | src/app.rs | 147 |
1 files changed, 69 insertions, 78 deletions
@@ -1,9 +1,9 @@ | |||
1 | use crate::{ | 1 | use crate::{ |
2 | bitmap::{MapPoint, Pixmap}, | 2 | bitmap::{Axis, MapPoint, Pixmap}, |
3 | undo::{ModifyRecord, OpKind, Operation, UndoStack}, | 3 | undo::{ModifyRecord, OpKind, Operation, UndoStack}, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use std::convert::{From, TryFrom}; | 6 | use std::convert::From; |
7 | 7 | ||
8 | use sdl2::{ | 8 | use sdl2::{ |
9 | event::Event, | 9 | event::Event, |
@@ -19,17 +19,18 @@ use sdl2::{ | |||
19 | use crate::consts::{BLACK, GRID_COLOR, WHITE}; | 19 | use crate::consts::{BLACK, GRID_COLOR, WHITE}; |
20 | 20 | ||
21 | pub struct AppState<'ctx> { | 21 | pub struct AppState<'ctx> { |
22 | start: Point, | 22 | active_color: bool, |
23 | pixmap: Pixmap<bool>, | ||
24 | zoom: u8, | ||
25 | brush_size: u8, | 23 | brush_size: u8, |
26 | grid: Grid, | ||
27 | context: &'ctx Sdl, | ||
28 | canvas: Canvas<Window>, | 24 | canvas: Canvas<Window>, |
25 | context: &'ctx Sdl, | ||
26 | current_operation: Operation, | ||
27 | grid: Grid, | ||
29 | last_point: Option<Point>, | 28 | last_point: Option<Point>, |
30 | active_color: bool, | 29 | pixmap: Pixmap<bool>, |
30 | start: Point, | ||
31 | symmetry: Symmetry, | ||
31 | undo_stack: UndoStack<Operation>, | 32 | undo_stack: UndoStack<Operation>, |
32 | current_operation: Operation, | 33 | zoom: u8, |
33 | } | 34 | } |
34 | 35 | ||
35 | struct Grid { | 36 | struct Grid { |
@@ -240,14 +241,9 @@ impl<'ctx> AppState<'ctx> { | |||
240 | } | 241 | } |
241 | } | 242 | } |
242 | 243 | ||
243 | fn modify<F>(&mut self, func: F) | 244 | fn redraw(&mut self) { |
244 | where | 245 | self.canvas.set_draw_color(BLACK); |
245 | F: FnOnce(&mut Self), | ||
246 | { | ||
247 | func(self); | ||
248 | self.canvas.set_draw_color(Color::RGB(0, 0, 0)); | ||
249 | self.canvas.clear(); | 246 | self.canvas.clear(); |
250 | self.canvas.set_draw_color(Color::RGB(64, 64, 64)); | ||
251 | self.draw(); | 247 | self.draw(); |
252 | self.canvas.present(); | 248 | self.canvas.present(); |
253 | } | 249 | } |
@@ -274,17 +270,18 @@ impl<'ctx> AppState<'ctx> { | |||
274 | 270 | ||
275 | let pixmap = Pixmap::new_with(width, height, false); | 271 | let pixmap = Pixmap::new_with(width, height, false); |
276 | Self { | 272 | Self { |
277 | start: Point::new(60, 60), | 273 | active_color: true, |
278 | zoom: 5, | ||
279 | brush_size: 0, | 274 | brush_size: 0, |
280 | pixmap, | ||
281 | grid: Grid::new(), | ||
282 | canvas, | 275 | canvas, |
283 | context, | 276 | context, |
277 | current_operation: Vec::new(), | ||
278 | grid: Grid::new(), | ||
284 | last_point: None, | 279 | last_point: None, |
285 | active_color: true, | 280 | pixmap, |
281 | start: Point::new(60, 60), | ||
282 | symmetry: Default::default(), | ||
286 | undo_stack: UndoStack::new(), | 283 | undo_stack: UndoStack::new(), |
287 | current_operation: Vec::new(), | 284 | zoom: 5, |
288 | } | 285 | } |
289 | } | 286 | } |
290 | 287 | ||
@@ -305,52 +302,53 @@ impl<'ctx> AppState<'ctx> { | |||
305 | } => { | 302 | } => { |
306 | match k { | 303 | match k { |
307 | // pan | 304 | // pan |
308 | Keycode::W => self.modify(|e| e.pan((0, 10))), | 305 | Keycode::W => self.pan((0, 10)), |
309 | Keycode::A => self.modify(|e| e.pan((10, 0))), | 306 | Keycode::A => self.pan((10, 0)), |
310 | Keycode::S => self.modify(|e| e.pan((0, -10))), | 307 | Keycode::S => self.pan((0, -10)), |
311 | Keycode::D => self.modify(|e| e.pan((-10, 0))), | 308 | Keycode::D => self.pan((-10, 0)), |
312 | // zoom | 309 | // zoom |
313 | Keycode::C => { | 310 | Keycode::C => { |
314 | let cursor = (mouse.x(), mouse.y()); | 311 | let cursor = (mouse.x(), mouse.y()); |
315 | self.modify(|e| e.zoom_in(cursor)); | 312 | self.zoom_in(cursor); |
316 | } | 313 | } |
317 | Keycode::Z => { | 314 | Keycode::Z => { |
318 | let cursor = (mouse.x(), mouse.y()); | 315 | let cursor = (mouse.x(), mouse.y()); |
319 | self.modify(|e| e.zoom_out(cursor)); | 316 | self.zoom_out(cursor); |
320 | } | 317 | } |
321 | // brush ops | 318 | // brush ops |
322 | Keycode::Q => self.decrease_brush_size(), | 319 | Keycode::Q => self.decrease_brush_size(), |
323 | Keycode::E => self.increase_brush_size(), | 320 | Keycode::E => self.increase_brush_size(), |
324 | // flip color | 321 | // flip color |
325 | Keycode::X => self.modify(|e| e.change_active_color()), | 322 | Keycode::X => self.change_active_color(), |
326 | // toggle grid | 323 | // toggle grid |
327 | Keycode::Tab => self.modify(|e| e.toggle_grid()), | 324 | Keycode::Tab => self.toggle_grid(), |
328 | // line drawing | 325 | // line drawing |
329 | Keycode::F => self.modify(|e| { | 326 | Keycode::F => { |
330 | let end = (mouse.x(), mouse.y()).into(); | 327 | let end = (mouse.x(), mouse.y()).into(); |
331 | if let Some(start) = e.last_point { | 328 | if let Some(start) = self.last_point { |
332 | if let Ok(o) = e.paint_line(start, end) { | 329 | if let Ok(o) = self.paint_line(start, end) { |
333 | e.commit_operation(); | 330 | self.commit_operation(); |
334 | e.current_operation = | 331 | self.current_operation = |
335 | o.into_iter().filter(|v| !v.old_val == v.val).collect(); | 332 | o.into_iter().filter(|v| !v.old_val == v.val).collect(); |
336 | e.commit_operation(); | 333 | self.commit_operation(); |
337 | e.last_point = Some(end); | 334 | self.last_point = Some(end); |
338 | } | 335 | } |
339 | } | 336 | } |
340 | }), | 337 | } |
338 | Keycode::V => self.cycle_symmetry(), | ||
341 | // exit | 339 | // exit |
342 | Keycode::Escape => break 'running, | 340 | Keycode::Escape => break 'running, |
343 | // undo & redo | 341 | // undo & redo |
344 | Keycode::U => self.modify(|e| { | 342 | Keycode::U => { |
345 | if let Some(op) = e.undo_stack.undo() { | 343 | if let Some(op) = self.undo_stack.undo() { |
346 | e.apply_operation(op, OpKind::Undo); | 344 | self.apply_operation(op, OpKind::Undo); |
347 | } | 345 | } |
348 | }), | 346 | } |
349 | Keycode::R => self.modify(|e| { | 347 | Keycode::R => { |
350 | if let Some(op) = e.undo_stack.redo() { | 348 | if let Some(op) = self.undo_stack.redo() { |
351 | e.apply_operation(op, OpKind::Redo); | 349 | self.apply_operation(op, OpKind::Redo); |
352 | } | 350 | } |
353 | }), | 351 | } |
354 | _ => (), | 352 | _ => (), |
355 | } | 353 | } |
356 | } | 354 | } |
@@ -358,57 +356,50 @@ impl<'ctx> AppState<'ctx> { | |||
358 | Event::MouseButtonDown { | 356 | Event::MouseButtonDown { |
359 | x, y, mouse_btn, .. | 357 | x, y, mouse_btn, .. |
360 | } => { | 358 | } => { |
361 | self.modify(|e| { | 359 | let pt = (x, y); |
362 | let pt = (x, y); | 360 | self.last_point = Some(pt.into()); |
363 | e.last_point = Some(pt.into()); | 361 | let val = match mouse_btn { |
364 | let val = match mouse_btn { | 362 | MouseButton::Right => !self.active_color, |
365 | MouseButton::Right => !e.active_color, | 363 | _ => self.active_color, |
366 | _ => e.active_color, | 364 | }; |
367 | }; | 365 | if let Ok(o) = self.paint_point(pt, val) { |
368 | if let Ok(o) = e.paint_point(pt, val) { | 366 | self.current_operation.extend(o); |
369 | e.current_operation.extend(o); | 367 | } |
370 | } | ||
371 | }); | ||
372 | } | 368 | } |
373 | // click and drag | 369 | // click and drag |
374 | Event::MouseMotion { | 370 | Event::MouseMotion { |
375 | x, y, mousestate, .. | 371 | x, y, mousestate, .. |
376 | } => { | 372 | } => { |
377 | if mousestate.is_mouse_button_pressed(MouseButton::Left) { | 373 | if mousestate.is_mouse_button_pressed(MouseButton::Left) { |
378 | self.modify(|e| { | 374 | let pt = (x, y); |
379 | let pt = (x, y); | 375 | let val = self.active_color; |
380 | let val = e.active_color; | 376 | if let Ok(o) = self.paint_point(pt, val) { |
381 | if let Ok(o) = e.paint_point(pt, val) { | 377 | self.current_operation.extend(o); |
382 | e.current_operation.extend(o); | 378 | } |
383 | } | ||
384 | }); | ||
385 | } else if mousestate.is_mouse_button_pressed(MouseButton::Right) { | 379 | } else if mousestate.is_mouse_button_pressed(MouseButton::Right) { |
386 | self.modify(|e| { | 380 | let pt = (x, y); |
387 | let pt = (x, y); | 381 | let val = !self.active_color; |
388 | let val = !e.active_color; | 382 | if let Ok(o) = self.paint_point(pt, val) { |
389 | if let Ok(o) = e.paint_point(pt, val) { | 383 | self.current_operation.extend(o); |
390 | e.current_operation.extend(o); | 384 | } |
391 | } | ||
392 | }); | ||
393 | } | 385 | } |
394 | } | 386 | } |
395 | // end of operation | 387 | // end of operation |
396 | Event::MouseButtonUp { .. } => self.modify(|e| { | 388 | Event::MouseButtonUp { .. } => { |
397 | let op = e | 389 | let op = self |
398 | .current_operation | 390 | .current_operation |
399 | .drain(..) | 391 | .drain(..) |
400 | .filter(|v| !v.old_val == v.val) | 392 | .filter(|v| !v.old_val == v.val) |
401 | .collect::<Vec<_>>(); | 393 | .collect::<Vec<_>>(); |
402 | e.undo_stack.push(op); | 394 | self.undo_stack.push(op); |
403 | }), | 395 | } |
404 | Event::Quit { .. } => { | 396 | Event::Quit { .. } => { |
405 | break 'running; | 397 | break 'running; |
406 | } | 398 | } |
407 | _ => { | 399 | _ => {} |
408 | self.modify(|_| ()); | ||
409 | } | ||
410 | } | 400 | } |
411 | } | 401 | } |
402 | self.redraw(); | ||
412 | } | 403 | } |
413 | } | 404 | } |
414 | } | 405 | } |