diff options
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/colours.rs | 14 | ||||
| -rw-r--r-- | src/editor.rs | 3 | ||||
| -rw-r--r-- | src/gui/dimension_indicator.rs | 189 | ||||
| -rw-r--r-- | src/gui/mod.rs | 4 | ||||
| -rw-r--r-- | src/main.rs | 9 | ||||
| -rw-r--r-- | src/map/mappable.rs | 8 | ||||
| -rw-r--r-- | src/map/polygon_room.rs | 26 | ||||
| -rw-r--r-- | src/map/rect_room.rs | 18 | ||||
| -rw-r--r-- | src/map/wall.rs | 29 | ||||
| -rw-r--r-- | src/math/rect.rs | 2 | ||||
| -rw-r--r-- | src/math/vec2.rs | 13 | ||||
| -rw-r--r-- | src/scaleable.rs | 11 | ||||
| -rw-r--r-- | src/tool/deletion_tool.rs | 13 | ||||
| -rw-r--r-- | src/tool/polygon_room_tool.rs | 10 | ||||
| -rw-r--r-- | src/tool/rect_room_tool.rs | 4 | ||||
| -rw-r--r-- | src/tool/selection_tool.rs | 13 | ||||
| -rw-r--r-- | src/transformable.rs | 8 |
18 files changed, 254 insertions, 122 deletions
@@ -15,4 +15,4 @@ svgtypes = "*" xmltree = "*" pretty_env_logger = "*" log = "*" -thiserror = "*" +thiserror = "*"
\ No newline at end of file diff --git a/src/colours.rs b/src/colours.rs index 8d69869..bafb53c 100644 --- a/src/colours.rs +++ b/src/colours.rs @@ -13,6 +13,8 @@ pub struct Colours { pub wall_selected: Color, pub icon_normal: Color, pub icon_selected: Color, + pub dimension_indicators: Color, + pub dimension_text: Color, } impl Colours { @@ -81,6 +83,18 @@ impl Colours { b: 150, a: 255, }, + dimension_indicators: Color { + r: 200, + g: 200, + b: 200, + a: 255, + }, + dimension_text: Color { + r: 200, + g: 200, + b: 200, + a: 255, + }, } } } diff --git a/src/editor.rs b/src/editor.rs index e6a2dcb..87a8db4 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -184,4 +184,7 @@ impl Editor { pub fn map(&self) -> &Map { &self.map } + pub fn map_mut(&mut self) -> &mut Map { + &mut self.map + } } diff --git a/src/gui/dimension_indicator.rs b/src/gui/dimension_indicator.rs index 3d8313d..aa00f67 100644 --- a/src/gui/dimension_indicator.rs +++ b/src/gui/dimension_indicator.rs @@ -1,10 +1,11 @@ -use crate::math::{self, Vec2, Rect}; +use crate::colours::DEFAULT_COLOURS; +use crate::map::Map; +use crate::math::{self, Rect, Vec2}; use crate::transform::Transform; +use nalgebra::{Matrix3, Vector2}; use raylib::drawing::RaylibDraw; +use raylib::ffi::{Color, KeyboardKey}; use raylib::RaylibHandle; -use raylib::ffi::{KeyboardKey, Color}; -use crate::map::Map; -use std::mem; /// A state the [DimensionIndicator] is currently in. This determines the behaviour of it and what /// inputs it might be waiting for. @@ -18,8 +19,8 @@ enum State { Ruling { dim_x: String, dim_y: String, - editing_x: bool - } + editing_x: bool, + }, } /// Used to render the horizontal and vertical dimensions of whatever is selected on the map and, if @@ -28,7 +29,7 @@ pub struct DimensionIndicator { /// The [State] the dimension indicator is currently in. state: State, /// The last dimensions that were valid. - dimensions: Rect<f64> + bounds: Rect<f64>, } impl Default for State { @@ -44,7 +45,7 @@ impl DimensionIndicator { pub fn new() -> Self { Self { state: State::default(), - dimensions: Rect::new(0., 0., 0., 0.); + bounds: Rect::new(0., 0., 0., 0.), } } @@ -52,7 +53,7 @@ impl DimensionIndicator { pub fn update(&mut self, map: &mut Map, rl: &mut RaylibHandle) { match &self.state { &State::Watching => self.update_watching(map, rl), - &State::Ruling{ .. } => self.update_ruling(map, rl), + &State::Ruling { .. } => self.update_ruling(map, rl), }; } @@ -73,22 +74,21 @@ impl DimensionIndicator { min.y = math::partial_min(min.y, element_bounds.y); max.x = math::partial_max(max.x, element_bounds.x + element_bounds.w); max.y = math::partial_max(max.y, element_bounds.y + element_bounds.h); - } - else { + } else { // No selection size detected yet. Set now. min.x = element_bounds.x; min.y = element_bounds.y; max.x = element_bounds.x + element_bounds.w; max.y = element_bounds.y + element_bounds.h; } + selection_exists = true; } } // Set the current selection limits, if any. - self.dimensions = if selection_exists { + self.bounds = if selection_exists { Rect::bounding_rect(min, max) - } - else { + } else { Rect::new(0., 0., 0., 0.) }; @@ -96,28 +96,151 @@ impl DimensionIndicator { // is a selection to begin with. if selection_exists && rl.is_key_pressed(KeyboardKey::KEY_TAB) { self.state = State::Ruling { - dim_x: self.dimensions.w.to_string(), - dim_y: self.dimensions.h.to_string(), - editing_x: true + dim_x: self.bounds.w.to_string(), + dim_y: self.bounds.h.to_string(), + editing_x: true, }; } } fn update_ruling(&mut self, map: &mut Map, rl: &mut RaylibHandle) { - /* Capture the current key press and interpret it, if it exists. Otherwise, there is nothing - * to update. - */ - let key = match rl.get_key_pressed() { - Some(key) => key, - None => return, + // Get the currently edited dimension for processing. + let (edited_dim, editing_x) = match &mut self.state { + State::Watching => panic!("Called ruler update when in watching state"), + State::Ruling { + dim_x, + dim_y, + editing_x, + } => { + if *editing_x { + (dim_x, editing_x) + } else { + (dim_y, editing_x) + } + } }; + // Switch the currently edited dimension when pressing tab. + if rl.is_key_pressed(KeyboardKey::KEY_TAB) { + *editing_x = !*editing_x; + return; + } + // Finish editing mode on enter. + if rl.is_key_pressed(KeyboardKey::KEY_ENTER) { + self.state = State::Watching; + return; + } + + // Marker to see if the dimensions will have to be checked for an update. + let mut dimension_changed = false; + // Delete the last character of the dimension on backspace. + if rl.is_key_pressed(KeyboardKey::KEY_BACKSPACE) { + edited_dim.pop(); + dimension_changed = true; + } + /* Capture the current key and try to add it to the string of the current dimension, + * if possible. + */ + else if let Some(key) = rl.get_key_pressed() { + match key { + // Add a decimal point to the dimension if possible. + KeyboardKey::KEY_PERIOD => { + if !edited_dim.contains('.') { + edited_dim.push('.'); + } + // Nothing changed here, since there is an implicit .0 at the end. + } + // Handle the entered key if it is a number to append it to the currently edited dimension. + _ => { + if key as u16 >= KeyboardKey::KEY_ZERO as u16 + && key as u16 <= KeyboardKey::KEY_NINE as u16 + { + edited_dim.push(key as u8 as char); + dimension_changed = true; + } + } + }; + } + + if dimension_changed { + /* Try to parse the dimension from the currently edited string. If it + * is valid, change the dimensions of the currently selected items. If + * not, ignore the change and wait for a valid dimension. + */ + if let Ok(dim) = edited_dim.parse::<f64>() { + let new_bounds = if *editing_x { + Rect::new(self.bounds.x, self.bounds.y, dim, self.bounds.h) + } else { + Rect::new(self.bounds.x, self.bounds.y, self.bounds.h, dim) + }; + self.set_bounds(map, new_bounds); + } + } + } + + /// Set the selection boundaries to the given bounds. Tries to transform the + /// currently selected items in the map so they fit inside of the new bounding box. + /// + /// # Panics + /// If the `bounds` have a negative value for width or height, the dimensions + /// cannot be set and the function will panic. + pub fn set_bounds(&mut self, map: &mut Map, bounds: Rect<f64>) { + if bounds.w <= 0. || bounds.h <= 0. { + panic!("Cannot set dimensions of elements to zero."); + } + + // If the bounds are the same as before, there is nothing to do. + if self.bounds == bounds { + return; + } + + /* Create a matrix to transform from the current rectangle bounds into the + * new bounds. Internally, this is a three-step process. First, we + * translate the points currently in the bounding box to the origin + * (0, 0) origin vector of the map, then scale and finally move it to the + * origin of the new rectangle. This needs to be applied to all vertices + * of all elements that can be scaled. + */ + let scale = Vector2::new(bounds.w / self.bounds.w, bounds.h / self.bounds.h); + let transform = Matrix3::new_translation(&Vector2::new(-self.bounds.x, -self.bounds.y)) + .append_nonuniform_scaling(&scale) + .append_translation(&Vector2::new(bounds.x, bounds.y)); + + for element in map.elements_mut() { + if element.selected() { + if let Some(transformable) = element.as_non_rigid_mut() { + transformable.apply_matrix(&transform); + } + } + } + + self.bounds = bounds; } pub fn draw(&self, rld: &mut impl RaylibDraw, transform: &Transform) { - // Draw all the dimension lines. - for (start, end) in &self.length_lines { + /* Ignore a selection that has no non-null dimensions, since this usually + * indicates that there is nothing to be scaled. + */ + if self.bounds.w == 0. && self.bounds.h == 0. { + return; + } + + let (dim_str_width, dim_str_height) = match &self.state { + State::Watching => (self.bounds.w.to_string(), self.bounds.h.to_string()), + State::Ruling { dim_x, dim_y, .. } => (dim_x.clone(), dim_y.clone()), + }; + + // Draw the horizontal dimension at the bottom and the vertical dimension to the right. + // Use the valid dimensions, but show the edited dimensions in the String (should they differ) + let top_right = Vec2::new(self.bounds.x + self.bounds.w, self.bounds.y); + let bot_left = Vec2::new(self.bounds.x, self.bounds.y + self.bounds.h); + let bot_right = Vec2::new(self.bounds.x + self.bounds.w, self.bounds.y + self.bounds.h); + let dimensions = [ + (bot_left, bot_right, dim_str_width), + (bot_right, top_right, dim_str_height), + ]; + for (start, end, dim_str) in &dimensions { // Don't draw anything if the length is zero. if start == end { continue; @@ -138,27 +261,21 @@ impl DimensionIndicator { let end_px = transform.point_m_to_px(end) + line_normal * 10.; /* Draw the indicator line, with stubs at both ends. */ - let line_colour = Color { - r: 200, - g: 200, - b: 200, - a: 255, - }; // First the two stubs. rld.draw_line_ex( start_px - line_normal * 5., start_px + line_normal * 5., 2., - line_colour, + DEFAULT_COLOURS.dimension_indicators, ); rld.draw_line_ex( end_px - line_normal * 5., end_px + line_normal * 5., 2., - line_colour, + DEFAULT_COLOURS.dimension_indicators, ); // Then the actual indicator line. - rld.draw_line_ex(start_px, end_px, 2., line_colour); + rld.draw_line_ex(start_px, end_px, 2., DEFAULT_COLOURS.dimension_indicators); /* Draw the indicator text showing how long this line is in meters. * It should be placed in the middle of the line, but not into the line directly, so it @@ -166,11 +283,11 @@ impl DimensionIndicator { */ let text_pos = transform.point_m_to_px(&((*end + *start) / 2.)) + line_normal * 20.; rld.draw_text( - &format!("{}m", &(*end - *start).length()), + &format!("{}m", dim_str), text_pos.x as i32, text_pos.y as i32, 20, - line_colour, + DEFAULT_COLOURS.dimension_text, ); } } diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 0351ab3..032d430 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -1,5 +1,5 @@ -pub mod tool_sidebar; pub mod dimension_indicator; +pub mod tool_sidebar; +pub use self::dimension_indicator::*; pub use self::tool_sidebar::*; -pub use self::dimension_indicator::*;
\ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 7957f14..6e54c59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,14 +12,14 @@ pub mod grid; pub mod gui; pub mod map; pub mod math; -pub mod scaleable; pub mod svg; pub mod tool; pub mod transform; +pub mod transformable; use config::Config; use editor::Editor; -use gui::ToolSidebar; +use gui::{DimensionIndicator, ToolSidebar}; use raylib::prelude::*; use std::ffi::CString; use std::io; @@ -65,6 +65,7 @@ fn main() { )); let mut editor = Editor::new(&mut rl, &thread, config); + let mut dimension_indicator = DimensionIndicator::new(); let tool_sidebar = ToolSidebar::new(&mut rl, &thread); let mut transform = Transform::new(); @@ -90,6 +91,8 @@ fn main() { ); } + dimension_indicator.update(editor.map_mut(), &mut rl); + editor.update( &mut rl, &transform, @@ -105,6 +108,8 @@ fn main() { editor.draw_tools(&mut d, &transform); tool_sidebar.draw(screen_height as u16, &mut d, &mut editor); + + dimension_indicator.draw(&mut d, &transform); } } } diff --git a/src/map/mappable.rs b/src/map/mappable.rs index b348c4b..323361a 100644 --- a/src/map/mappable.rs +++ b/src/map/mappable.rs @@ -2,8 +2,8 @@ //! dimension on the map and may be scaleable use crate::math::Rect; -use crate::scaleable::Scaleable; use crate::transform::Transform; +use crate::transformable::NonRigidTransformable; use raylib::drawing::RaylibDrawHandle; pub trait Mappable { @@ -21,7 +21,11 @@ pub trait Mappable { /// Get the rectangle that contains the mappable object in its entirety without excess. fn bounding_rect(&self) -> Rect<f64>; - fn as_scaleable(&self) -> Option<&dyn Scaleable> { + fn as_non_rigid(&self) -> Option<&dyn NonRigidTransformable> { + None + } + + fn as_non_rigid_mut(&mut self) -> Option<&mut dyn NonRigidTransformable> { None } } diff --git a/src/map/polygon_room.rs b/src/map/polygon_room.rs index a209a7c..65eeaab 100644 --- a/src/map/polygon_room.rs +++ b/src/map/polygon_room.rs @@ -1,9 +1,10 @@ use super::Mappable; use crate::colours::DEFAULT_COLOURS; -use crate::math::{self, Polygon, Rect, Triangle, Vec2}; -use crate::scaleable::Scaleable; +use crate::math::{self, Polygon, Rect, Triangle}; use crate::transform::Transform; +use crate::transformable::NonRigidTransformable; use raylib::drawing::{RaylibDraw, RaylibDrawHandle}; +use nalgebra::{Matrix3, Point2}; pub type PolygonRoomData = Polygon<f64>; @@ -56,20 +57,21 @@ impl Mappable for PolygonRoom { Rect::bounding_rect_n(&self.data.corners()) } - fn as_scaleable(&self) -> Option<&dyn Scaleable> { - Some(self as &dyn Scaleable) + fn as_non_rigid(&self) -> Option<&dyn NonRigidTransformable> { + Some(self as &dyn NonRigidTransformable) } -} -impl Scaleable for PolygonRoom { - fn scale(&mut self, by: &Vec2<f64>) { - if by.x < 0. || by.y < 0. { - panic!("Cannot set dimensions with negative size"); - } + fn as_non_rigid_mut(&mut self) -> Option<&mut dyn NonRigidTransformable> { + Some(self as &mut dyn NonRigidTransformable) + } +} +impl NonRigidTransformable for PolygonRoom { + fn apply_matrix(&mut self, matrix: &Matrix3<f64>) { for corner in self.data.corners_mut() { - corner.x *= by.x; - corner.y *= by.y; + *corner = matrix + .transform_point(&Point2::new(corner.x, corner.y)) + .into(); } self.retriangulate(); diff --git a/src/map/rect_room.rs b/src/map/rect_room.rs index 5008c63..ee184fb 100644 --- a/src/map/rect_room.rs +++ b/src/map/rect_room.rs @@ -1,7 +1,6 @@ use crate::colours::DEFAULT_COLOURS; use crate::map::Mappable; -use crate::math::{Rect, Vec2}; -use crate::scaleable::Scaleable; +use crate::math::Rect; use crate::transform::Transform; use raylib::drawing::{RaylibDraw, RaylibDrawHandle}; use serde::Serialize; @@ -47,21 +46,6 @@ impl Mappable for RectRoom { fn bounding_rect(&self) -> Rect<f64> { self.data.clone() } - - fn as_scaleable(&self) -> Option<&dyn Scaleable> { - Some(self as &dyn Scaleable) - } -} - -impl Scaleable for RectRoom { - fn scale(&mut self, by: &Vec2<f64>) { - if by.x < 0. || by.y < 0. { - panic!("Cannot set dimensions with negative size"); - } - - self.data.x *= by.x; - self.data.y *= by.y; - } } impl Deref for RectRoom { diff --git a/src/map/wall.rs b/src/map/wall.rs index 22393bb..d18096b 100644 --- a/src/map/wall.rs +++ b/src/map/wall.rs @@ -1,10 +1,11 @@ use super::Mappable; use crate::colours::DEFAULT_COLOURS; use crate::math::{LineSegment, Rect, Vec2}; -use crate::scaleable::Scaleable; use crate::transform::Transform; +use crate::transformable::NonRigidTransformable; use raylib::drawing::{RaylibDraw, RaylibDrawHandle}; use std::ops::{Deref, DerefMut}; +use nalgebra::{Matrix3, Point2}; pub type WallData = LineSegment<f64>; @@ -81,18 +82,24 @@ impl Mappable for Wall { fn bounding_rect(&self) -> Rect<f64> { Rect::bounding_rect(self.data.start, self.data.end) } -} -impl Scaleable for Wall { - fn scale(&mut self, by: &Vec2<f64>) { - if by.x <= 0. || by.y <= 0. { - panic!("Cannot set dimensions with negative size"); - } + fn as_non_rigid(&self) -> Option<&dyn NonRigidTransformable> { + Some(self as &dyn NonRigidTransformable) + } + + fn as_non_rigid_mut(&mut self) -> Option<&mut dyn NonRigidTransformable> { + Some(self as &mut dyn NonRigidTransformable) + } +} - self.data.start.x *= by.x; - self.data.start.y *= by.y; - self.data.end.x *= by.x; - self.data.end.y *= by.y; +impl NonRigidTransformable for Wall { + fn apply_matrix(&mut self, matrix: &Matrix3<f64>) { + self.data.start = matrix + .transform_point(&self.data.start.into()) + .into(); + self.data.end = matrix + .transform_point(&self.data.end.into()) + .into(); } } diff --git a/src/math/rect.rs b/src/math/rect.rs index 50c1cb0..b571644 100644 --- a/src/math/rect.rs +++ b/src/math/rect.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use std::ops::{Add, AddAssign}; /// Represents a Rectangle with the value type T. -#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct Rect<T: Scalar + Copy> { /// The x coordinate, or leftmost coordinate of the Rect. pub x: T, diff --git a/src/math/vec2.rs b/src/math/vec2.rs index d591f1d..b9e3215 100644 --- a/src/math/vec2.rs +++ b/src/math/vec2.rs @@ -7,6 +7,7 @@ use std::cmp::Ordering; use std::convert::{From, Into}; use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}; use std::{fmt, mem}; +use nalgebra::Point2; #[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize, Eq, Hash)] pub struct Vec2<T: Scalar + Copy> { @@ -45,6 +46,18 @@ impl<T: Scalar + Copy> Vec2<T> { } } +impl<T: Scalar + Copy> Into<Point2<T>> for Vec2<T> { + fn into(self) -> Point2<T> { + Point2::new(self.x, self.y) + } +} + +impl<T: Scalar + Copy> From<Point2<T>> for Vec2<T> { + fn from(v: Point2<T>) -> Self { + Self::new(v.x, v.y) + } +} + // This is sad, but also sadly necessary :/ impl<T> From<raylib::ffi::Vector2> for Vec2<T> where diff --git a/src/scaleable.rs b/src/scaleable.rs deleted file mode 100644 index 450e61e..0000000 --- a/src/scaleable.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::math::Vec2; - -/// Trait representing something that covers an area and that can be resized accordingly. -pub trait Scaleable { - /// Scale the object by the specified amount in horizontal and vertical direction (right and - /// downwards). - /// - /// # Panics - /// If at least one of the dimensions is zero or less, the object cannot be scaled and panics. - fn scale(&mut self, by: &Vec2<f64>); -} diff --git a/src/tool/deletion_tool.rs b/src/tool/deletion_tool.rs index 5ff3e6a..cd38f6c 100644 --- a/src/tool/deletion_tool.rs +++ b/src/tool/deletion_tool.rs @@ -1,8 +1,8 @@ use super::Tool; +use crate::colours::DEFAULT_COLOURS; use crate::map::Map; use crate::math::{Rect, Surface, Vec2}; use crate::transform::Transform; -use crate::colours::DEFAULT_COLOURS; use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; pub struct DeletionTool { @@ -36,15 +36,8 @@ impl Tool for DeletionTool { 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 - ); + rld.draw_rectangle_rec(rect_px, DEFAULT_COLOURS.deletion_rect); + rld.draw_rectangle_lines_ex(rect_px, 4, DEFAULT_COLOURS.deletion_rect_outline); } } diff --git a/src/tool/polygon_room_tool.rs b/src/tool/polygon_room_tool.rs index 1b079d2..de6714d 100644 --- a/src/tool/polygon_room_tool.rs +++ b/src/tool/polygon_room_tool.rs @@ -1,8 +1,8 @@ use super::Tool; +use crate::colours::DEFAULT_COLOURS; use crate::map::Map; use crate::math::{self, Polygon, PolygonError, Vec2}; use crate::transform::Transform; -use crate::colours::DEFAULT_COLOURS; use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; struct UnfinishedPolygon { @@ -103,7 +103,7 @@ impl Tool for PolygonRoomTool { transform.point_m_to_px(&polygon.corners[0]), transform.point_m_to_px(&polygon.working_corner), transform.length_m_to_px(0.1) as f32, - DEFAULT_COLOURS.room_selected + DEFAULT_COLOURS.room_selected, ); } else if polygon.corners.len() == 2 { // We have three valid corners, so we can draw a triangle. @@ -111,7 +111,7 @@ impl Tool for PolygonRoomTool { transform.point_m_to_px(&polygon.corners[0]), transform.point_m_to_px(&polygon.corners[1]), transform.point_m_to_px(&polygon.working_corner), - DEFAULT_COLOURS.room_selected + DEFAULT_COLOURS.room_selected, ) } else { // A proper polygon can be drawn. @@ -126,7 +126,7 @@ impl Tool for PolygonRoomTool { transform.point_m_to_px(&triangle[0]), transform.point_m_to_px(&triangle[1]), transform.point_m_to_px(&triangle[2]), - DEFAULT_COLOURS.room_selected + DEFAULT_COLOURS.room_selected, ) } } else if polygon.check_validity_completed().is_ok() { @@ -138,7 +138,7 @@ impl Tool for PolygonRoomTool { transform.point_m_to_px(&triangle[0]), transform.point_m_to_px(&triangle[1]), transform.point_m_to_px(&triangle[2]), - DEFAULT_COLOURS.room_selected + DEFAULT_COLOURS.room_selected, ) } } diff --git a/src/tool/rect_room_tool.rs b/src/tool/rect_room_tool.rs index dfda495..29173cd 100644 --- a/src/tool/rect_room_tool.rs +++ b/src/tool/rect_room_tool.rs @@ -1,8 +1,8 @@ use super::Tool; +use crate::colours::DEFAULT_COLOURS; use crate::map::Map; use crate::math::{Rect, Vec2}; use crate::transform::Transform; -use crate::colours::DEFAULT_COLOURS; use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; pub struct RectRoomTool { @@ -35,7 +35,7 @@ impl Tool for RectRoomTool { if let Some((pos1, pos2)) = self.unfinished_rect { rld.draw_rectangle_rec( transform.rect_m_to_px(&Rect::bounding_rect(pos1, pos2)), - DEFAULT_COLOURS.room_selected + DEFAULT_COLOURS.room_selected, ); } } diff --git a/src/tool/selection_tool.rs b/src/tool/selection_tool.rs index 49efba9..30f91bf 100644 --- a/src/tool/selection_tool.rs +++ b/src/tool/selection_tool.rs @@ -1,9 +1,9 @@ use super::Tool; +use crate::colours::DEFAULT_COLOURS; use crate::map::Map; use crate::math::{Rect, Surface, Vec2}; use crate::transform::Transform; use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; -use crate::colours::DEFAULT_COLOURS; pub struct SelectionTool { selection_rect: Option<(Vec2<f64>, Vec2<f64>)>, @@ -31,15 +31,8 @@ impl Tool for SelectionTool { fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) { if let Some((pos1, pos2)) = self.selection_rect { let rect_px = transform.rect_m_to_px(&Rect::bounding_rect(pos1, pos2)); - rld.draw_rectangle_rec( - rect_px, - DEFAULT_COLOURS.selection_rect - ); - rld.draw_rectangle_lines_ex( - rect_px, - 4, - DEFAULT_COLOURS.selection_rect_outline - ); + rld.draw_rectangle_rec(rect_px, DEFAULT_COLOURS.selection_rect); + rld.draw_rectangle_lines_ex(rect_px, 4, DEFAULT_COLOURS.selection_rect_outline); } } diff --git a/src/transformable.rs b/src/transformable.rs new file mode 100644 index 0000000..c181bd6 --- /dev/null +++ b/src/transformable.rs @@ -0,0 +1,8 @@ +use nalgebra::Matrix3; + +/// Trait for things that can be stretched and rotated etc. as one pleases without +/// becoming invalid. A room for instance would fall into this category, while an icon might not. +pub trait NonRigidTransformable { + /// Applies the provided matrix to all vertices of this transformable element. + fn apply_matrix(&mut self, matrix: &Matrix3<f64>); +} |
