gemini_engine/containers/
pixel_container.rs

1use crate::{
2    core::{CanDraw, Canvas, ColChar, Vec2D},
3    primitives::Pixel,
4};
5
6use super::CanCollide;
7
8/// A `PixelContainer` acts as an intermediary between [Canvas]es and structs implementing [`CanDraw`]. Objects can draw to the `PixelContainer`, which in turn can draw to any other `Canvas` implementing struct
9#[derive(Debug, Clone)]
10pub struct PixelContainer {
11    /// Any pixels plotted to the `PixelContainer` are stored here
12    pub pixels: Vec<Pixel>,
13}
14
15impl Default for PixelContainer {
16    fn default() -> Self {
17        Self::new()
18    }
19}
20
21impl PixelContainer {
22    /// Create a new, empty `PixelContainer`
23    #[must_use]
24    pub const fn new() -> Self {
25        Self { pixels: vec![] }
26    }
27
28    /// Plot a pixel to the `PixelContainer`
29    pub fn plot(&mut self, pos: Vec2D, c: ColChar) {
30        self.pixels.push(Pixel::new(pos, c));
31    }
32
33    /// Moves all the pixels of `other` into `self`, leaving `other` empty
34    pub fn append(&mut self, pixels: &mut Vec<Pixel>) {
35        self.pixels.append(pixels);
36    }
37
38    /// Append a slice of `Vec2D` points which all share a [`ColChar`]
39    pub fn append_points(&mut self, points: &[Vec2D], fill_char: ColChar) {
40        for point in points {
41            self.plot(*point, fill_char);
42        }
43    }
44
45    /// Draw a struct implementing [`CanDraw`] to the `PixelContainer`.
46    pub fn draw(&mut self, element: &impl CanDraw) {
47        element.draw_to(self);
48    }
49}
50
51impl From<&[Pixel]> for PixelContainer {
52    fn from(pixels: &[Pixel]) -> Self {
53        Self {
54            pixels: pixels.to_vec(),
55        }
56    }
57}
58
59impl<E: CanDraw> From<&E> for PixelContainer {
60    /// Create a new `PixelContainer` with the pixels of the passed element
61    fn from(element: &E) -> Self {
62        let mut container = Self::new();
63        container.draw(element);
64        container
65    }
66}
67
68// TODO: Do i need this?
69// impl From<&[(Vec2D, ColChar)]> for PixelContainer {
70//     fn from(pixels: &[(Vec2D, ColChar)]) -> Self {
71//         Self {
72//             pixels: pixels.iter().map(|x| Pixel::from(*x)).collect(),
73//         }
74//     }
75// }
76
77impl From<(&[Vec2D], ColChar)> for PixelContainer {
78    fn from(value: (&[Vec2D], ColChar)) -> Self {
79        Self {
80            pixels: value
81                .0
82                .iter()
83                .map(|pos| Pixel::new(*pos, value.1))
84                .collect(),
85        }
86    }
87}
88
89impl Canvas for PixelContainer {
90    fn plot(&mut self, pos: Vec2D, c: ColChar) {
91        self.plot(pos, c);
92    }
93}
94
95impl CanDraw for PixelContainer {
96    fn draw_to(&self, canvas: &mut impl Canvas) {
97        for pixel in &self.pixels {
98            canvas.plot(pixel.pos, pixel.fill_char);
99        }
100    }
101}
102
103impl CanCollide for PixelContainer {
104    fn collides_with_pos(&self, pos: Vec2D) -> bool {
105        self.pixels.iter().any(|p| p.pos == pos)
106    }
107}