//! 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}; use std::ops::Deref; /// Data type for the Polygon room. pub type RoomData = Polygon; /// A polygon room, which can be placed and modified in the world. pub struct Room { data: RoomData, // The polygon shape, but in triangles, so the polygon does not have to be triangulated every frame. triangulated: Vec>, selected: bool, } impl Room { /// Create a room from the given polygon data. pub fn from_data(data: RoomData) -> 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 Room { 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 Room { 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(); } } impl Deref for Room { type Target = RoomData; fn deref(&self) -> &Self::Target { &self.data } }