From fffdf4a6dd69f16176698f8b42db7dfe2a054e26 Mon Sep 17 00:00:00 2001 From: Arne Dußin Date: Thu, 4 Feb 2021 21:57:09 +0100 Subject: Fix crash when drawing rect with no area --- src/client/tool/rect_room_tool.rs | 37 +++++++++++++++++++++---------------- src/math/rect.rs | 9 +++++++++ 2 files changed, 30 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/client/tool/rect_room_tool.rs b/src/client/tool/rect_room_tool.rs index 41f2a91..60bf246 100644 --- a/src/client/tool/rect_room_tool.rs +++ b/src/client/tool/rect_room_tool.rs @@ -6,9 +6,11 @@ use super::Tool; use crate::client::colours::DEFAULT_COLOURS; use crate::client::map::Map; use crate::client::transform::Transform; +use crate::client::FLOAT_MARGIN; use crate::math::{Rect, Vec2}; use crate::net::{Cargo, Connection}; use crate::world::Room; +use float_cmp::ApproxEq; use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; /// The tool to create simple, rectangular rooms. @@ -29,6 +31,19 @@ impl RectRoomTool { } } +/* Try to create a rectangle from the given points, but only if they don't create + * a rectangle with no area. + */ +fn try_into_bounding_rect(pos1: Vec2, pos2: Vec2) -> Option> { + let bounding_rect = Rect::bounding_rect(pos1, pos2); + + if !bounding_rect.area().approx_eq(0., FLOAT_MARGIN) { + Some(bounding_rect) + } else { + None + } +} + impl Tool for RectRoomTool { fn deactivate(&mut self) { self.unfinished_rect = None; @@ -57,15 +72,10 @@ impl Tool for RectRoomTool { ) { // Try to finish the rectangle if it has been started. if let Some((pos1, pos2)) = self.unfinished_rect { - if pos1 == pos2 { - warn!("Cannot place rectangle with start and endpoint being the same"); - return; + if let Some(rect) = try_into_bounding_rect(pos1, pos2) { + server.send(Cargo::AddRoom(Room::new(rect.into()))); + self.unfinished_rect = None; } - - server.send(Cargo::AddRoom(Room::new( - Rect::bounding_rect(pos1, pos2).into(), - ))); - self.unfinished_rect = None; } else { self.unfinished_rect = Some((*mouse_pos_m, *mouse_pos_m)); } @@ -73,15 +83,10 @@ impl Tool for RectRoomTool { fn finish(&mut self, _map: &mut Map, server: &Connection) { if let Some((pos1, pos2)) = self.unfinished_rect { - if pos1 == pos2 { - warn!("Cannot place rectangle with start and endpoint being the same"); - return; + if let Some(rect) = try_into_bounding_rect(pos1, pos2) { + server.send(Cargo::AddRoom(Room::new(rect.into()))); + self.unfinished_rect = None; } - - server.send(Cargo::AddRoom(Room::new( - Rect::bounding_rect(pos1, pos2).into(), - ))); - self.unfinished_rect = None; } } diff --git a/src/math/rect.rs b/src/math/rect.rs index a8326bc..288c19d 100644 --- a/src/math/rect.rs +++ b/src/math/rect.rs @@ -3,6 +3,7 @@ use super::{ExactSurface, LineSegment, Polygon, Vec2}; //use alga::general::{Additive, Identity}; use nalgebra::{RealField, Scalar}; +use num_traits::sign::{self, Signed}; use num_traits::{NumCast, ToPrimitive, Zero}; use serde::{Deserialize, Serialize}; use std::ops::{Add, AddAssign, Sub}; @@ -147,6 +148,14 @@ impl Rect { Vec2::new(T::zero(), move_y) } } + + /// Calculate the area of the rectangle. + pub fn area(&self) -> T + where + T: Signed, + { + sign::abs(self.w) * sign::abs(self.h) + } } impl ExactSurface for Rect -- cgit v1.2.3-70-g09d2