diff options
| -rw-r--r-- | Cargo.lock | 151 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/dimension_indicator.rs | 123 | ||||
| -rw-r--r-- | src/main.rs | 6 | ||||
| -rw-r--r-- | src/math/vec2.rs | 23 | ||||
| -rw-r--r-- | src/tool/room_tool.rs | 11 |
6 files changed, 312 insertions, 4 deletions
@@ -1,6 +1,15 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] name = "alga" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -30,6 +39,17 @@ dependencies = [ ] [[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -69,6 +89,19 @@ dependencies = [ ] [[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] name = "float-cmp" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -106,8 +139,10 @@ name = "graf_karto" version = "0.1.1" dependencies = [ "alga", + "log", "nalgebra", "num-traits", + "pretty_env_logger", "raylib", "ron", "serde", @@ -116,6 +151,24 @@ dependencies = [ ] [[package]] +name = "hermit-abi" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -134,6 +187,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] +name = "log" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +dependencies = [ + "cfg-if", +] + +[[package]] name = "matrixmultiply" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -143,6 +205,12 @@ dependencies = [ ] [[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] name = "nalgebra" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -223,6 +291,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" [[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger", + "log", +] + +[[package]] name = "proc-macro2" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -232,6 +310,12 @@ dependencies = [ ] [[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -320,6 +404,24 @@ dependencies = [ ] [[package]] +name = "regex" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" + +[[package]] name = "ron" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -390,6 +492,24 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -414,6 +534,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] name = "xml-rs" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -13,3 +13,5 @@ alga = "*" num-traits = "*" svgtypes = "*" xmltree = "*" +pretty_env_logger = "*" +log = "*" diff --git a/src/dimension_indicator.rs b/src/dimension_indicator.rs new file mode 100644 index 0000000..a08d22c --- /dev/null +++ b/src/dimension_indicator.rs @@ -0,0 +1,123 @@ +use crate::math::Vec2; +use crate::transform::Transform; +use raylib::drawing::RaylibDraw; +use raylib::ffi::Color; + +pub struct DimensionIndicator { + /// The lines that are used to draw the Dimension Indicator. For a rectangle for instance these + /// would be two. One for width and one for height. + length_lines: Vec<(Vec2<f32>, Vec2<f32>)>, +} + +impl DimensionIndicator { + pub fn new() -> Self { + Self { + length_lines: Vec::new(), + } + } + + pub fn from_corner_points(corner_points: &Vec<Vec2<f32>>) -> Self { + let mut this = Self::new(); + this.update_dimensions(corner_points); + + this + } + + /// Update the dimensions by analysing a given set of points and adjusting the internal + /// (measured) dimensions. + pub fn update_dimensions(&mut self, corner_points: &[Vec2<f32>]) { + if corner_points.len() < 2 { + warn!("Cannot discern dimensions when not at least two points are given. The dimensions were not updated."); + return; + } + + // Discern the bounding box for the given corner points. + let mut min = corner_points[0]; + let mut max = corner_points[0]; + for point in corner_points.iter().skip(1) { + if point.x < min.x { + min.x = point.x; + } + if point.x > max.x { + max.x = point.x; + } + + if point.y < min.y { + min.y = point.y; + } + if point.y > max.y { + max.y = point.y; + } + } + + // For now, only use the width and height vectors. + // TODO: Change to a more sophisticated approach. + self.length_lines.clear(); + // Horizontal dimensions, left to right. + self.length_lines + .push((Vec2::new(min.x, max.y), Vec2::new(max.x, max.y))); + // Vertical dimensions, bottom to top. + self.length_lines + .push((Vec2::new(max.x, max.y), Vec2::new(max.x, min.y))); + } + + pub fn draw(&self, rld: &mut impl RaylibDraw, transform: &Transform) { + // Draw all the dimension lines. + for (start, end) in &self.length_lines { + // Don't draw anything if the length is zero. + if start == end { + continue; + } + + /* Get the vector that is perpendicular and points right/down from the line, assuming + * the lines prefer left as start over right and bottom over top. + */ + let line_normal = { + // Start with the direction of the line vector. + let dir = *start - *end; + // Calculate perpendicular vec and normalise. + dir.rotated_90_clockwise() / dir.len() + }; + + // To not have the line directly in the rect, move start and end outside a bit. + let start_px = transform.point_m_to_px(*start) + line_normal * 10.; + 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, + ); + rld.draw_line_ex( + end_px - line_normal * 5., + end_px + line_normal * 5., + 2., + line_colour, + ); + // Then the actual indicator line. + rld.draw_line_ex(start_px, end_px, 2., line_colour); + + /* 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 + * will be moved out by the normal. + */ + let text_pos = transform.point_m_to_px((*end + *start) / 2.) + line_normal * 20.; + rld.draw_text( + &format!("{}m", &(*end - *start).len()), + text_pos.x as i32, + text_pos.y as i32, + 20, + line_colour, + ); + } + } +} diff --git a/src/main.rs b/src/main.rs index a0d8a13..e40a40e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,9 @@ +#[macro_use] +extern crate log; + pub mod button; pub mod config; +pub mod dimension_indicator; pub mod editor; pub mod grid; pub mod map_data; @@ -17,6 +21,8 @@ use transform::Transform; pub const CONFIG_FILE: &str = "config.ron"; fn main() { + pretty_env_logger::init(); + let (mut rl, thread) = raylib::init().resizable().title("Hello there!").build(); rl.set_target_fps(120); rl.set_exit_key(None); diff --git a/src/math/vec2.rs b/src/math/vec2.rs index ea549d7..7834ffc 100644 --- a/src/math/vec2.rs +++ b/src/math/vec2.rs @@ -1,11 +1,12 @@ use crate::math::Rect; use alga::general::{ClosedAdd, ClosedSub}; use nalgebra::{RealField, Scalar}; +use num_traits::One; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::convert::{From, Into}; -use std::fmt; -use std::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign}; +use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}; +use std::{fmt, mem}; #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize, Eq)] pub struct Vec2<T: Scalar + Copy> { @@ -24,6 +25,24 @@ impl<T: Scalar + Copy> Vec2<T> { { (self.x * self.x + self.y * self.y).sqrt() } + + pub fn rotated_90_clockwise(mut self) -> Vec2<T> + where + T: One + Neg<Output = T> + MulAssign, + { + mem::swap(&mut self.x, &mut self.y); + self.y *= -T::one(); + self + } + + pub fn rotated_90_counterclockwise(mut self) -> Vec2<T> + where + T: One + Neg<Output = T> + MulAssign, + { + mem::swap(&mut self.x, &mut self.y); + self.x *= -T::one(); + self + } } // This is sad, but also sadly necessary :/ diff --git a/src/tool/room_tool.rs b/src/tool/room_tool.rs index 1bfb225..52748fc 100644 --- a/src/tool/room_tool.rs +++ b/src/tool/room_tool.rs @@ -1,6 +1,7 @@ use super::Tool; use crate::button::Button; use crate::config::{RoomToolKeybindings, ToolKeybindings}; +use crate::dimension_indicator::DimensionIndicator; use crate::grid::snap_to_grid; use crate::map_data::MapData; use crate::math::{Rect, Vec2}; @@ -14,6 +15,7 @@ pub struct RoomTool { /// The rectangle that is currently being drawn by the user. Once it is finished, it will be /// pushed into the room_rects. unfinished_rect: Option<(Vec2<f32>, Vec2<f32>)>, + dimension_indicator: DimensionIndicator, } impl RoomTool { @@ -22,6 +24,7 @@ impl RoomTool { Self { keybindings, unfinished_rect: None, + dimension_indicator: DimensionIndicator::new(), } } } @@ -29,9 +32,11 @@ impl RoomTool { impl Tool for RoomTool { 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()); - // Update the currently drawn rectangle, if it exists - if let Some((_, ref mut pos2)) = &mut self.unfinished_rect { + // Update the currently drawn rectangle, if it exists, and also its dimension indicator. + if let Some((ref pos1, ref mut pos2)) = &mut self.unfinished_rect { *pos2 = snap_to_grid(mouse_pos_m, 0.5); + + self.dimension_indicator.update_dimensions(&[*pos1, *pos2]); } // Start or finish drawing the currently unfinished rectangle @@ -73,6 +78,8 @@ impl Tool for RoomTool { a: 255, }, ); + + self.dimension_indicator.draw(rld, transform); } } |
