//! The rectangle room tool is a specialised tool to create rooms of rectangular shape and with the //! sides of the room parallel to the x and y-axes. This is often useful, when a quick room creation //! is necessary and the shape of the room does not have to be very special. 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. pub struct RectRoomTool { /// 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, Vec2)>, } impl RectRoomTool { /// Create a new room tool where no rooms have been drawn yet. Should be created only once per /// program instance and by the editor. #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { unfinished_rect: None, } } } /* 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; } fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2) { if let Some((_, ref mut pos2)) = &mut self.unfinished_rect { *pos2 = *mouse_pos_m; } } fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) { 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, ); } } fn place_single( &mut self, _map: &mut Map, server: &Connection, mouse_pos_m: &Vec2, ) { // Try to finish the rectangle if it has been started. if let Some((pos1, pos2)) = self.unfinished_rect { if let Some(rect) = try_into_bounding_rect(pos1, pos2) { server.send(Cargo::AddRoom(Room::new(rect.into()))); self.unfinished_rect = None; } } else { self.unfinished_rect = Some((*mouse_pos_m, *mouse_pos_m)); } } fn finish(&mut self, _map: &mut Map, server: &Connection) { if let Some((pos1, pos2)) = self.unfinished_rect { if let Some(rect) = try_into_bounding_rect(pos1, pos2) { server.send(Cargo::AddRoom(Room::new(rect.into()))); self.unfinished_rect = None; } } } fn abort(&mut self) { self.unfinished_rect = None; } }