veloren_common/figure/
cell.rs

1use std::num::NonZeroU8;
2
3use crate::vol::FilledVox;
4use vek::*;
5
6const GLOWY: u8 = 1 << 1;
7const SHINY: u8 = 1 << 2;
8const HOLLOW: u8 = 1 << 3;
9const NOT_OVERRIDABLE: u8 = 1 << 4;
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq)]
12// 1 = glowy, 2 = shiny, 3 = hollow, 4 = not overridable
13pub struct CellAttr(NonZeroU8);
14
15impl CellAttr {
16    pub fn new(glowy: bool, shiny: bool, hollow: bool, ignore_hollow: bool) -> Self {
17        Self(
18            NonZeroU8::new(
19                1 + glowy as u8 * GLOWY
20                    + shiny as u8 * SHINY
21                    + hollow as u8 * HOLLOW
22                    + ignore_hollow as u8 * NOT_OVERRIDABLE,
23            )
24            .expect("At least 1"),
25        )
26    }
27
28    pub fn from_index(index: u8) -> CellAttr {
29        Self::new(
30            (13..16).contains(&index), // Glow
31            (8..13).contains(&index),  // Shiny
32            index == 16,               // Hollow
33            (17..22).contains(&index), // Not overridable
34        )
35    }
36
37    pub fn empty() -> Self { Self(NonZeroU8::new(1).expect("Not zero")) }
38
39    pub fn is_glowy(&self) -> bool { self.0.get() & GLOWY != 0 }
40
41    pub fn is_shiny(&self) -> bool { self.0.get() & SHINY != 0 }
42
43    pub fn is_hollow(&self) -> bool { self.0.get() & HOLLOW != 0 }
44
45    pub fn is_not_overridable(&self) -> bool { self.0.get() & NOT_OVERRIDABLE != 0 }
46}
47
48#[derive(Copy, Clone, Debug, PartialEq, Eq)]
49pub struct CellData {
50    pub col: Rgb<u8>,
51    pub attr: CellAttr,
52}
53
54impl CellData {
55    pub(super) fn new(col: Rgb<u8>, attr: CellAttr) -> Self { CellData { col, attr } }
56}
57
58impl Default for CellData {
59    fn default() -> Self { Self::new(Rgb::broadcast(255), CellAttr::empty()) }
60}
61
62/// A type representing a single voxel in a figure.
63#[derive(Copy, Clone, Debug, PartialEq, Eq)]
64pub enum Cell {
65    Filled(CellData),
66    Empty,
67}
68
69impl Cell {
70    pub fn new(col: Rgb<u8>, attr: CellAttr) -> Self { Cell::Filled(CellData::new(col, attr)) }
71
72    pub fn get_color(&self) -> Option<Rgb<u8>> {
73        match self {
74            Cell::Filled(data) => Some(data.col),
75            Cell::Empty => None,
76        }
77    }
78
79    pub fn attr(&self) -> CellAttr {
80        match self {
81            Cell::Filled(data) => data.attr,
82            Cell::Empty => CellAttr::empty(),
83        }
84    }
85}
86
87impl FilledVox for Cell {
88    fn default_non_filled() -> Self { Cell::Empty }
89
90    fn is_filled(&self) -> bool { matches!(self, Cell::Filled(_)) }
91}
92
93#[cfg(test)]
94mod test {
95    use super::*;
96
97    #[test]
98    fn cell_size() {
99        assert_eq!(4, std::mem::size_of::<Cell>());
100        assert_eq!(1, std::mem::align_of::<Cell>());
101    }
102}