//! Polygon rooms are the standard rooms in graf karto. They can take the form of anything that a //! [Polygon](crate::math::Polygon) can have. use super::Mappable; use crate::colours::DEFAULT_COLOURS; use crate::math::{self, Polygon, Rect, Triangle}; use crate::transform::Transform; use crate::transformable::NonRigidTransformable; use crate::FLOAT_MARGIN; use nalgebra::{Matrix3, Point2}; use raylib::drawing::{RaylibDraw, RaylibDrawHandle}; /// Data type for the Polygon room. pub type PolygonRoomData = Polygon; /// A polygon room, which can be placed and modified in the world. pub struct PolygonRoom { data: PolygonRoomData, // The polygon shape, but in triangles, so the polygon does not have to be triangulated every frame. triangulated: Vec>, selected: bool, } impl PolygonRoom { /// Create a room from the given polygon data. pub fn from_data(data: PolygonRoomData) -> Self { Self { data: data.clone(), triangulated: math::triangulate(data, FLOAT_MARGIN), selected: false, } } // When the internal polygon changes, it must be retriangulated to be drawn on the screen // properly, so this function must be called any time that happens. fn retriangulate(&mut self) { self.triangulated = math::triangulate(self.data.clone(), FLOAT_MARGIN); } } impl Mappable for PolygonRoom { fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) { for triangle in &self.triangulated { rld.draw_triangle( transform.point_m_to_px(&triangle.corners()[0]), transform.point_m_to_px(&triangle.corners()[1]), transform.point_m_to_px(&triangle.corners()[2]), if self.selected() { DEFAULT_COLOURS.room_selected } else { DEFAULT_COLOURS.room_normal }, ) } } fn set_selected(&mut self, selected: bool) { self.selected = selected; } fn selected(&self) -> bool { self.selected } fn bounding_rect(&self) -> Rect { Rect::bounding_rect_n(&self.data.corners()) } 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) } } impl NonRigidTransformable for PolygonRoom { fn apply_matrix(&mut self, matrix: &Matrix3) { for corner in self.data.corners_mut() { *corner = matrix .transform_point(&Point2::new(corner.x, corner.y)) .into(); } self.retriangulate(); } }