aboutsummaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorArne Dußin2021-01-27 14:01:50 +0100
committerArne Dußin2021-02-02 22:16:15 +0100
commitf92e9f6f07b1e3834c2ca58ce3510734819d08e4 (patch)
tree20e3d3afce342a56ae98f6c20491482ccd2b5c6b /src/map
parentc60a6d07efb120724b308e29e8e70f27c87c952d (diff)
downloadgraf_karto-f92e9f6f07b1e3834c2ca58ce3510734819d08e4.tar.gz
graf_karto-f92e9f6f07b1e3834c2ca58ce3510734819d08e4.zip
Rework graf karto to fit the client/server structure
Diffstat (limited to 'src/map')
-rw-r--r--src/map/data.rs87
-rw-r--r--src/map/icon.rs102
-rw-r--r--src/map/icon_renderer.rs91
-rw-r--r--src/map/mappable.rs35
-rw-r--r--src/map/mod.rs171
-rw-r--r--src/map/room.rs98
-rw-r--r--src/map/wall.rs125
7 files changed, 0 insertions, 709 deletions
diff --git a/src/map/data.rs b/src/map/data.rs
deleted file mode 100644
index 20f193d..0000000
--- a/src/map/data.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-//! Module containing the raw map data version of the map.
-
-use super::{IconData, Map, RoomData, WallData};
-use ron::de::from_reader;
-use ron::ser::{to_string_pretty, PrettyConfig};
-use serde::{Deserialize, Serialize};
-use std::fs::File;
-use std::io::{self, Write};
-use std::path::Path;
-
-/// The serialisable and deserialisable parts of the map. This can be created to get a version of the
-/// map which is persistifiable or sendable/receivable without data overhead or data that might make
-/// it easily corruptable.
-#[derive(Serialize, Deserialize)]
-pub struct MapData {
- pub(super) rooms: Vec<RoomData>,
- pub(super) walls: Vec<WallData>,
- pub(super) icons: Vec<IconData>,
-}
-
-impl MapData {
- /// Create a serialisable map data type from the data elements contained in a map.
- pub fn new(rooms: Vec<RoomData>, walls: Vec<WallData>, icons: Vec<IconData>) -> Self {
- Self {
- rooms,
- walls,
- icons,
- }
- }
-
- /// Creates a data struct from the Map. It is important to note, that this data element is not
- /// bound to the Map in any way after this, so changing anything won't change anything in the map.
- /// It is useful however to for instance serialize this map without extra rendering information
- /// included.
- pub fn extract_data(map: &Map) -> Self {
- Self {
- rooms: map
- .rooms()
- .iter()
- .map(|p| (p as &RoomData).clone())
- .collect(),
- walls: map
- .walls()
- .iter()
- .map(|w| (w as &WallData).clone())
- .collect(),
- icons: map
- .icons()
- .iter()
- .map(|i| (i as &IconData).clone())
- .collect(),
- }
- }
-
- /// Load the map data from a file. Fails if the file does not exist or cannot be correctly parsed.
- pub fn load_from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
- let file = File::open(&path)?;
- let data: Self = match from_reader(file) {
- Ok(data) => data,
- Err(err) => {
- return Err(io::Error::new(io::ErrorKind::InvalidData, err));
- }
- };
-
- Ok(data)
- }
-
- /// Write the map data to the file located at `path`. If the file already exists, it will be
- /// overwritten. If the write fails, an IO-Error is returned.
- pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
- let mut file = File::create(&path)?;
-
- let pretty_conf = PrettyConfig::new()
- .with_depth_limit(4)
- .with_decimal_floats(true)
- .with_separate_tuple_members(true)
- .with_indentor("\t".to_owned());
- let string = match to_string_pretty(&self, pretty_conf) {
- Ok(string) => string,
- Err(err) => {
- return Err(io::Error::new(io::ErrorKind::InvalidInput, err));
- }
- };
-
- file.write_all(&string.as_bytes())
- }
-}
diff --git a/src/map/icon.rs b/src/map/icon.rs
deleted file mode 100644
index 2e45486..0000000
--- a/src/map/icon.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//! Icons are map elements that have a specific size and cannot be stretched. They are usually used
-//! as markers for specific places in the world.
-
-use super::icon_renderer::IconRenderer;
-use crate::colours::DEFAULT_COLOURS;
-use crate::map::Mappable;
-use crate::math::{Rect, Vec2};
-use crate::transform::Transform;
-use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle};
-use serde::{Deserialize, Serialize};
-use std::ops::{Deref, DerefMut};
-use std::rc::Rc;
-
-/// The icon data necessary to create an Icon again.
-#[derive(Clone, Serialize, Deserialize)]
-pub struct IconData {
- /// The id of the icon is the icons position in the currently loaded icon_data vector.
- pub id: usize,
- /// The position of the icon on the map, given by the vector in meters.
- pub position: Vec2<f64>,
- /// Rotation of the icon texture in degrees.
- pub rotation: f64,
-}
-
-/// Describes an icon in the world and can be drawn.
-#[derive(Clone)]
-pub struct Icon {
- data: IconData,
- selected: bool,
- renderer: Rc<IconRenderer>,
-}
-
-impl Icon {
- /// Create a new icon. Requires the icon renderer that is used to render this icon, as well as all
- /// the information necessary to describe the icon itself.
- pub fn new(id: usize, position: Vec2<f64>, rotation: f64, renderer: Rc<IconRenderer>) -> Self {
- Self::from_data(
- IconData {
- id,
- position,
- rotation,
- },
- renderer,
- )
- }
-
- /// Like `new()`, but with the icon data bundled into the icon data type.
- pub fn from_data(data: IconData, renderer: Rc<IconRenderer>) -> Self {
- Self {
- data,
- selected: false,
- renderer,
- }
- }
-}
-
-impl Mappable for Icon {
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- let (texture, info) = self.renderer.get(self.id);
- // Round the position to whole pixels to fix rotation problems.
- let mut position_px =
- transform.point_m_to_px(&(self.position - (info.anchor / info.pixels_per_m)));
- position_px.x = position_px.x.floor();
- position_px.y = position_px.y.floor();
- rld.draw_texture_ex(
- texture,
- position_px,
- self.rotation as f32,
- (transform.pixels_per_m() / info.pixels_per_m) as f32,
- if self.selected() {
- DEFAULT_COLOURS.icon_selected
- } else {
- DEFAULT_COLOURS.icon_normal
- },
- );
- }
-
- fn set_selected(&mut self, selected: bool) {
- self.selected = selected;
- }
-
- fn selected(&self) -> bool {
- self.selected
- }
-
- fn bounding_rect(&self) -> Rect<f64> {
- Rect::new(self.data.position.x, self.data.position.y, 0., 0.)
- }
-}
-
-impl Deref for Icon {
- type Target = IconData;
-
- fn deref(&self) -> &Self::Target {
- &self.data
- }
-}
-impl DerefMut for Icon {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.data
- }
-}
diff --git a/src/map/icon_renderer.rs b/src/map/icon_renderer.rs
deleted file mode 100644
index eef053d..0000000
--- a/src/map/icon_renderer.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-//! Since the same icon may be used very often on a map, it becomes impracticalto let every icon have
-//! it's own texture data saved, which is why a texture manager type of struct is used for it instead.
-
-use crate::math::Vec2;
-use raylib::core::texture::Texture2D;
-use raylib::{RaylibHandle, RaylibThread};
-use ron::de::from_reader;
-use serde::Deserialize;
-use std::fs::{self, File};
-
-/// The directory containing all files related to icons.
-pub const ICON_DIR: &str = "assets/icons";
-
-#[derive(Deserialize)]
-pub(super) struct IconFileInfo {
- /// The position the icon should be anchored in pixels. This is the Vector it will be moved by
- /// relative to the mouse pointer (to the left and up).
- pub anchor: Vec2<f64>,
- /// The scale of the icon as expressed in image pixels per real meter.
- pub pixels_per_m: f64,
-}
-
-/// Manager for all icon texture or rendering data.
-pub struct IconRenderer {
- texture_data: Vec<(Texture2D, IconFileInfo)>,
-}
-
-impl IconRenderer {
- /// Create a new icon renderer. This loads all textures and information for icons that is needed
- /// to draw them to the screen. Usually, there should be only one IconRenderer, or at least one
- /// renderer per directory and program instance.
- pub fn new(rl: &mut RaylibHandle, rlt: &RaylibThread) -> Self {
- /* Read all available icons from the icon directory. SVGs do not need any special scale
- * file, but pixel-based file formats require a RON-file declaring what the scale of the
- * picture is right beside them.
- */
- let mut image_files = Vec::new();
- for entry in fs::read_dir(ICON_DIR).expect("Could not open icon directory") {
- let entry = entry.expect("Failed to read file from icon directory");
-
- // Ignore the RON-files for now and put the image files into the vec
- if entry
- .path()
- .extension()
- .expect("Entry does not have a file extension")
- != "ron"
- {
- image_files.push(entry);
- }
- }
-
- // Read the RON-files where it is necessary.
- let mut texture_data = Vec::with_capacity(image_files.len());
- for file in image_files {
- // TODO: Handle svg
-
- let texture = rl
- .load_texture(
- rlt,
- file.path()
- .to_str()
- .expect("Unable to convert path to string."),
- )
- .expect("Could not read image file");
-
- let mut file = file.path();
- file.set_extension("ron");
- let ron = File::open(file).expect("Could not read ron file for icon information.");
- let icon_info: IconFileInfo =
- from_reader(ron).expect("Could not parse icon info from reader.");
-
- texture_data.push((texture, icon_info));
- }
-
- Self { texture_data }
- }
-
- /// Get the data needed to render an icon of type `icon_id`.
- ///
- /// # Panics
- /// If the `icon_id` does not describe a valid icon (is out of bounds), there is no data to be
- /// accessed and the function panics.
- pub(super) fn get(&self, icon_id: usize) -> &(Texture2D, IconFileInfo) {
- &self.texture_data[icon_id]
- }
-
- /// The number of icons registered in this icon-renderer.
- pub fn num_icons(&self) -> usize {
- self.texture_data.len()
- }
-}
diff --git a/src/map/mappable.rs b/src/map/mappable.rs
deleted file mode 100644
index 7978f50..0000000
--- a/src/map/mappable.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-//! Something that's mappable can be placed on the map and drawn at a specific position. It has a
-//! dimension on the map and may be transformable in various ways.
-
-use crate::math::Rect;
-use crate::transform::Transform;
-use crate::transformable::NonRigidTransformable;
-use raylib::drawing::RaylibDrawHandle;
-
-/// Anything that can be added to the map or world must implement this trait.
-pub trait Mappable {
- /// Draw this to `rld` with the transform. An item that cannot be drawn is not mappable, so
- /// this must always be implemented.
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform);
-
- /// Set the selection status of this item. If it is selected, actions that concern all selected
- /// items will be applied to this item as well.
- fn set_selected(&mut self, selected: bool);
-
- /// Get if this item is currently selected.
- fn selected(&self) -> bool;
-
- /// Get the rectangle that contains the mappable object in its entirety without excess.
- fn bounding_rect(&self) -> Rect<f64>;
-
- /// If this mappable item can be transformed in a non-rigid way, a dynamic reference is returned,
- /// otherwise none.
- fn as_non_rigid(&self) -> Option<&dyn NonRigidTransformable> {
- None
- }
-
- /// The same as `as_non_rigid`, but mutably.
- fn as_non_rigid_mut(&mut self) -> Option<&mut dyn NonRigidTransformable> {
- None
- }
-}
diff --git a/src/map/mod.rs b/src/map/mod.rs
deleted file mode 100644
index e1def09..0000000
--- a/src/map/mod.rs
+++ /dev/null
@@ -1,171 +0,0 @@
-//! The map contains all the items that make up the world.
-//!
-//! There are two main structs to look out for, the first being [Map]. This is the interaction point
-//! for most parts of the program. It contains the actual elements that are drawn on the screen. and
-//! can be changed by the user.
-//! The second is [MapData] and it contains the data that can be saved/loaded and distributed. Every
-//! map item has an internal item that it can be dereferenced to and can be used to construct this
-//! exact item in the same world elsewhere or at a different time. This is often different from the
-//! item that is being drawn. An example would be the [PolygonRoom], which contains a triangulated
-//! version of itself, so it can be drawn without always having to compute the triangles every frame.
-//! It's data type however [PolygonRoomData] contains only the raw polygon data, not the triangulated
-//! version, since that is enough to create the same [PolygonRoom] again.
-
-pub mod data;
-pub mod icon;
-pub mod icon_renderer;
-pub mod mappable;
-pub mod room;
-pub mod wall;
-
-pub use data::MapData;
-pub use icon::*;
-pub use mappable::Mappable;
-pub use room::*;
-pub use wall::*;
-
-use crate::transform::Transform;
-use icon_renderer::IconRenderer;
-use raylib::drawing::RaylibDrawHandle;
-use raylib::{RaylibHandle, RaylibThread};
-use std::rc::Rc;
-
-/// The map containing all map elements that are seen on the screen.
-pub struct Map {
- rooms: Vec<Room>,
- walls: Vec<Wall>,
- icons: Vec<Icon>,
- icon_renderer: Rc<IconRenderer>,
-}
-
-impl Map {
- /// Create a new, empty map/world.
- pub fn new(rl: &mut RaylibHandle, rlt: &RaylibThread) -> Self {
- Self {
- rooms: Vec::new(),
- walls: Vec::new(),
- icons: Vec::new(),
- icon_renderer: Rc::new(IconRenderer::new(rl, rlt)),
- }
- }
-
- /// Add a room to the map. Currently, holes are not supported in the polygon, but this might
- /// change later.
- pub fn push_room(&mut self, room_data: RoomData) {
- self.rooms.push(Room::from_data(room_data));
- }
-
- /// Add a wall to the world.
- pub fn push_wall(&mut self, wall_data: WallData) {
- /* Check for intersections with any wall that was arleady created so the wall ends can be
- * rendered properly.
- */
- let mut start_intersects = false;
- let mut end_intersects = false;
- for wall in &self.walls {
- if wall.data().contains_collinear(wall_data.start) {
- start_intersects = true;
- }
- if wall.data().contains_collinear(wall_data.end) {
- end_intersects = true;
- }
-
- // Currently, additional intersections can be ignored, since it is just a yes-no-question
- if start_intersects && end_intersects {
- break;
- }
- }
-
- self.walls
- .push(Wall::from_data(wall_data, start_intersects, end_intersects));
- }
-
- /// Add an icon to the world.
- pub fn push_icon(&mut self, icon: Icon) {
- self.icons.push(icon);
- }
-
- /// Draw all elements of the map to the screen. This should be called after the background of the
- /// map has already been drawn.
- pub fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- for element in self.elements() {
- element.draw(rld, transform);
- }
- }
-
- /// Get the icon-renderer that is currently used to render the icons.
- pub fn icon_renderer(&self) -> Rc<IconRenderer> {
- self.icon_renderer.clone()
- }
-
- /// Retain all map elements that fulfill the given predicate, removing everything else.
- pub fn retain<F>(&mut self, mut f: F)
- where
- F: FnMut(&dyn Mappable) -> bool,
- {
- // Call retain on all vectors containing the maps actual types.
- self.rooms.retain(|p| f(p as &dyn Mappable));
- self.walls.retain(|w| f(w as &dyn Mappable));
- self.icons.retain(|i| f(i as &dyn Mappable));
- }
-
- /// Iterator over all elements as objects when an operation needs to go over all elements of the
- /// map.
- pub fn elements(&self) -> impl Iterator<Item = &dyn Mappable> {
- self.rooms
- .iter()
- .map(|p| p as &dyn Mappable)
- .chain(self.walls.iter().map(|w| w as &dyn Mappable))
- .chain(self.icons.iter().map(|i| i as &dyn Mappable))
- }
-
- /// Iterator over all elements, but the individual elements can be mutated. It is however
- /// impossible to add or remove elements in this way. For that, use the dedicated functions.
- pub fn elements_mut(&mut self) -> impl Iterator<Item = &mut dyn Mappable> {
- self.rooms
- .iter_mut()
- .map(|p| p as &mut dyn Mappable)
- .chain(self.walls.iter_mut().map(|w| w as &mut dyn Mappable))
- .chain(self.icons.iter_mut().map(|i| i as &mut dyn Mappable))
- }
-
- /// Get the rooms of this map.
- pub fn rooms(&self) -> &Vec<Room> {
- &self.rooms
- }
-
- /// Get the walls of this map.
- pub fn walls(&self) -> &Vec<Wall> {
- &self.walls
- }
-
- /// Get the icons of this map.
- pub fn icons(&self) -> &Vec<Icon> {
- &self.icons
- }
-
- /// Replace the internal map data with the data provided. (Load and replace)
- pub fn set_data(&mut self, data: MapData) {
- // Remove all data.
- self.icons.clear();
- self.rooms.clear();
- self.walls.clear();
-
- // Add all data from the map data.
- self.add_data(data);
- }
-
- /// Add the data provided to the current data on the map. All elements will remain, with the
- /// additional elements being pushed also.
- pub fn add_data(&mut self, data: MapData) {
- for i in data.icons {
- self.push_icon(Icon::from_data(i, self.icon_renderer.clone()))
- }
- for p in data.rooms {
- self.push_room(p);
- }
- for w in data.walls {
- self.push_wall(w);
- }
- }
-}
diff --git a/src/map/room.rs b/src/map/room.rs
deleted file mode 100644
index 3050763..0000000
--- a/src/map/room.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-//! 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<f64>;
-
-/// 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<Triangle<f64>>,
- 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<f64> {
- 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<f64>) {
- 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
- }
-}
diff --git a/src/map/wall.rs b/src/map/wall.rs
deleted file mode 100644
index f1748bb..0000000
--- a/src/map/wall.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-//! Walls, solid barriers that are generally unscaleable.
-//!
-//! This interpretation is generally up to the GM to decide, but generally speaking, a wall cannot be
-//! crossed by a player. If special conditions apply (for instance, when the player wants to scale the
-//! wall), a check is necessary. If a check is not necessary, then maybe you were not thinking about
-//! a wall.
-
-use super::Mappable;
-use crate::colours::DEFAULT_COLOURS;
-use crate::math::{LineSegment, Rect, Vec2};
-use crate::transform::Transform;
-use crate::transformable::NonRigidTransformable;
-use nalgebra::Matrix3;
-use raylib::drawing::{RaylibDraw, RaylibDrawHandle};
-use std::ops::{Deref, DerefMut};
-
-/// The data which defines a wall segment completely for serialisation.
-pub type WallData = LineSegment<f64>;
-
-/// A solid wall a player cannot go through, except if special conditions apply.
-pub struct Wall {
- data: WallData,
- selected: bool,
- round_start: bool,
- round_end: bool,
-}
-
-impl Wall {
- /// Create a new wall from the deserialised data and information known from internal sources.
- pub fn from_data(data: WallData, round_start: bool, round_end: bool) -> Self {
- Self {
- data,
- selected: false,
- round_start,
- round_end,
- }
- }
-
- /// Get the internal data for serialisation
- pub fn data(&self) -> &WallData {
- &self.data
- }
-}
-
-fn draw_round_corner(
- rld: &mut RaylibDrawHandle,
- pos_px: Vec2<f64>,
- transform: &Transform,
- selected: bool,
-) {
- rld.draw_circle_v(
- pos_px,
- transform.length_m_to_px(0.05) as f32,
- if selected {
- DEFAULT_COLOURS.wall_selected
- } else {
- DEFAULT_COLOURS.wall_normal
- },
- );
-}
-
-impl Mappable for Wall {
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- let start_px = transform.point_m_to_px(&self.data.start);
- let end_px = transform.point_m_to_px(&self.data.end);
- rld.draw_line_ex(
- start_px,
- end_px,
- transform.length_m_to_px(0.1) as f32,
- if self.selected() {
- DEFAULT_COLOURS.wall_selected
- } else {
- DEFAULT_COLOURS.wall_normal
- },
- );
-
- if self.round_start {
- draw_round_corner(rld, start_px, transform, self.selected());
- }
- if self.round_end {
- draw_round_corner(rld, end_px, transform, self.selected());
- }
- }
-
- fn set_selected(&mut self, selected: bool) {
- self.selected = selected;
- }
-
- fn selected(&self) -> bool {
- self.selected
- }
-
- fn bounding_rect(&self) -> Rect<f64> {
- Rect::bounding_rect(self.data.start, self.data.end)
- }
-
- 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 Wall {
- fn apply_matrix(&mut self, matrix: &Matrix3<f64>) {
- self.data.start = matrix.transform_point(&self.data.start.into()).into();
- self.data.end = matrix.transform_point(&self.data.end.into()).into();
- }
-}
-
-impl Deref for Wall {
- type Target = WallData;
-
- fn deref(&self) -> &Self::Target {
- &self.data
- }
-}
-
-impl DerefMut for Wall {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.data
- }
-}