diff options
Diffstat (limited to 'src/client/tool/deletion_tool.rs')
| -rw-r--r-- | src/client/tool/deletion_tool.rs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/client/tool/deletion_tool.rs b/src/client/tool/deletion_tool.rs new file mode 100644 index 0000000..3095ff5 --- /dev/null +++ b/src/client/tool/deletion_tool.rs @@ -0,0 +1,82 @@ +//! A meta tool for selecting parts of a map and removing them in a single operation. +//! +//! The user can draw a rectangle, which currently must have it's side parallel to the x and y-axes +//! of the world. With the first node placement, the mode is started, while the second placement would +//! finish the process and delete all elements that are *completely* contained in the rectangle +//! (partially contained items are not deleted) or abort it, in which case the selection is removed +//! and nothing is deleted. + +use super::Tool; +use crate::client::colours::DEFAULT_COLOURS; +use crate::client::map::Map; +use crate::client::transform::Transform; +use crate::client::Connection; +use crate::math::{ExactSurface, Rect, Vec2}; +use crate::net::Cargo; +use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; + +/// The deletion tool itself. +pub struct DeletionTool { + deletion_rect: Option<(Vec2<f64>, Vec2<f64>)>, +} + +impl DeletionTool { + /// Create a new deletion tool, there should only be one deletion tool and it should be created + /// by the editor. + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { + deletion_rect: None, + } + } +} + +fn delete_rect((pos1, pos2): (&Vec2<f64>, &Vec2<f64>), map: &Map, server: &Connection<Cargo>) { + let bounds = Rect::bounding_rect(*pos1, *pos2); + + for (id, e) in map.elements() { + if bounds.contains_rect(&e.as_component().bounding_rect()) { + server.send(Cargo::Remove(id)); + } + } +} + +impl Tool for DeletionTool { + fn deactivate(&mut self) { + self.deletion_rect = None; + } + + fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2<f64>) { + if let Some((_, ref mut pos2)) = &mut self.deletion_rect { + *pos2 = *mouse_pos_m; + } + } + + fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) { + if let Some((pos1, pos2)) = self.deletion_rect { + let rect_px = transform.rect_m_to_px(&Rect::bounding_rect(pos1, pos2)); + rld.draw_rectangle_rec(rect_px, DEFAULT_COLOURS.deletion_rect); + rld.draw_rectangle_lines_ex(rect_px, 4, DEFAULT_COLOURS.deletion_rect_outline); + } + } + + fn place_single(&mut self, map: &mut Map, server: &Connection<Cargo>, mouse_pos_m: &Vec2<f64>) { + if let Some((pos1, pos2)) = self.deletion_rect { + delete_rect((&pos1, &pos2), &map, server); + self.deletion_rect = None; + } else { + self.deletion_rect = Some((*mouse_pos_m, *mouse_pos_m)); + } + } + + fn finish(&mut self, map: &mut Map, server: &Connection<Cargo>) { + if let Some((pos1, pos2)) = self.deletion_rect { + delete_rect((&pos1, &pos2), &map, server); + self.deletion_rect = None; + } + } + + fn abort(&mut self) { + self.deletion_rect = None; + } +} |
