aboutsummaryrefslogtreecommitdiff
path: root/src/map/mod.rs
blob: ff034745d2f6278cd2b0d03a2bd808791091f2d0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
pub mod data;
pub mod icon;
pub mod icon_renderer;
pub mod mappable;
pub mod polygon_room;
pub mod rect_room;
pub mod wall;

pub use data::MapData;
pub use icon::*;
pub use mappable::Mappable;
pub use polygon_room::*;
pub use rect_room::*;
pub use wall::*;

use crate::transform::Transform;
use icon_renderer::IconRenderer;
use raylib::drawing::RaylibDrawHandle;
use raylib::{RaylibHandle, RaylibThread};
use std::rc::Rc;

pub struct Map {
    rect_rooms: Vec<RectRoom>,
    polygon_rooms: Vec<PolygonRoom>,
    walls: Vec<Wall>,
    icons: Vec<Icon>,
    icon_renderer: Rc<IconRenderer>,
}

impl Map {
    pub fn new(rl: &mut RaylibHandle, rlt: &RaylibThread) -> Self {
        Self {
            rect_rooms: Vec::new(),
            polygon_rooms: Vec::new(),
            walls: Vec::new(),
            icons: Vec::new(),
            icon_renderer: Rc::new(IconRenderer::new(rl, rlt)),
        }
    }

    pub fn push_rect_room(&mut self, room_data: RectRoomData) {
        self.rect_rooms.push(RectRoom::from_data(room_data));
    }

    pub fn push_polygon_room(&mut self, room_data: PolygonRoomData) {
        self.polygon_rooms.push(PolygonRoom::from_data(room_data));
    }

    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));
    }

    pub fn push_icon(&mut self, icon: Icon) {
        self.icons.push(icon);
    }

    pub fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
        for element in self.elements() {
            element.draw(rld, transform);
        }
    }

    pub fn icon_renderer(&self) -> Rc<IconRenderer> {
        self.icon_renderer.clone()
    }

    /// Retain all map elements that fulfill the given predicate.
    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.rect_rooms.retain(|r| f(r as &dyn Mappable));
        self.polygon_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.rect_rooms
            .iter()
            .map(|r| r as &dyn Mappable)
            .chain(self.polygon_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))
    }

    pub fn elements_mut(&mut self) -> impl Iterator<Item = &mut dyn Mappable> {
        self.rect_rooms
            .iter_mut()
            .map(|r| r as &mut dyn Mappable)
            .chain(
                self.polygon_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))
    }
}