diff options
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/editor.rs | 2 | ||||
| -rw-r--r-- | src/math/rect.rs | 19 | ||||
| -rw-r--r-- | src/tool/deletion_tool.rs | 69 |
5 files changed, 85 insertions, 7 deletions
@@ -101,6 +101,7 @@ version = "0.1.0" dependencies = [ "alga", "nalgebra", + "num-traits", "raylib", "ron", "serde", @@ -10,3 +10,4 @@ ron = "*" serde = "*" nalgebra = "*" alga = "*" +num-traits = "*" diff --git a/src/editor.rs b/src/editor.rs index 09f7e0d..a68bb25 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -36,6 +36,8 @@ impl Editor { ToolType::RoomTool as usize } else if rl.is_key_pressed(KeyboardKey::KEY_W) { ToolType::WallTool as usize + } else if rl.is_key_pressed(KeyboardKey::KEY_D) { + ToolType::DeletionTool as usize } else { self.active }; diff --git a/src/math/rect.rs b/src/math/rect.rs index c126d56..6988b2c 100644 --- a/src/math/rect.rs +++ b/src/math/rect.rs @@ -1,7 +1,9 @@ use super::Vec2; +//use alga::general::{Additive, Identity}; use nalgebra::{RealField, Scalar}; +use num_traits::identities::Zero; use serde::{Deserialize, Serialize}; -use std::ops::{Add, AddAssign}; +use std::ops::{Add, AddAssign, Sub}; /// Represents a Rectangle with the value type T. #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] @@ -114,6 +116,21 @@ impl<T: Scalar + Copy> Rect<T> { && point.y <= self.y + self.h } + /// Returns true if the entire rect is contained inside this rectangle. + pub fn contains_rect(&self, rect: Rect<T>) -> bool + where + T: Add<Output = T> + Sub<Output = T> + PartialOrd + Zero, + { + /* True, if the rightmost x-coordinate of the called rectangle is further right or the same + * as the rightmost coordinate of the given rect. + */ + let x_exceeds = self.x + self.w - rect.x - rect.w >= T::zero(); + // The same for the y-coordinates + let y_exceeds = self.y + self.h - rect.y - rect.h >= T::zero(); + + x_exceeds && y_exceeds && self.x <= rect.x && self.y <= rect.y + } + /// Function to calculate the bounding rectangle that is between two vectors. The order of the /// vectors is irrelevent for this. As long as they are diagonally opposite of each other, this /// function will work. diff --git a/src/tool/deletion_tool.rs b/src/tool/deletion_tool.rs index 3eca92a..de4e255 100644 --- a/src/tool/deletion_tool.rs +++ b/src/tool/deletion_tool.rs @@ -1,20 +1,77 @@ use super::Tool; use crate::map_data::MapData; +use crate::math::{Rect, Vec2}; use crate::transform::Transform; -use raylib::core::drawing::RaylibDrawHandle; +use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; +use raylib::ffi::{Color, MouseButton}; use raylib::RaylibHandle; -pub struct DeletionTool {} +pub struct DeletionTool { + deletion_rect: Option<(Vec2<f32>, Vec2<f32>)>, +} impl DeletionTool { pub fn new() -> Self { - Self {} + Self { + deletion_rect: None, + } + } + + /// Delete all map-data that is contained inside the provided rectangular space. + pub fn delete_rect(map_data: &mut MapData, rect: Rect<f32>) { + map_data + .rooms_mut() + .retain(|&room| !rect.contains_rect(room)); + map_data + .walls_mut() + .retain(|&(pos1, pos2)| !rect.contains(pos1) || !rect.contains(pos2)); } } impl Tool for DeletionTool { - fn update(&mut self, map_data: &MapData, rl: &RaylibHandle, transform: &Transform) {} - fn active_update(&mut self, map_data: &mut MapData, rl: &RaylibHandle, transform: &Transform) {} + fn active_update(&mut self, map_data: &mut MapData, rl: &RaylibHandle, transform: &Transform) { + let mouse_pos_m = transform.point_px_to_m(rl.get_mouse_position().into()); + if let Some((_, ref mut pos2)) = &mut self.deletion_rect { + *pos2 = mouse_pos_m; + } + + if rl.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON) { + if let Some((pos1, pos2)) = self.deletion_rect { + Self::delete_rect(map_data, Rect::bounding_rect(pos1, pos2)); + self.deletion_rect = None; + } else { + self.deletion_rect = Some((mouse_pos_m, mouse_pos_m)) + } + } - fn draw(&self, map_data: &MapData, _rld: &mut RaylibDrawHandle, _transform: &Transform) {} + // Abort deletion. + if rl.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON) { + self.deletion_rect = None; + } + } + + fn draw(&self, map_data: &MapData, 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, + Color { + r: 200, + g: 150, + b: 150, + a: 50, + }, + ); + rld.draw_rectangle_lines_ex( + rect_px, + 4, + Color { + r: 200, + g: 150, + b: 150, + a: 150, + }, + ); + } + } } |
