use crate::{chunk::raw_tile::RawTile, lib::*};
pub(super) trait Layer: 'static {
fn set_tile(&mut self, index: usize, tile: RawTile);
fn remove_tile(&mut self, index: usize);
fn get_tile(&self, index: usize) -> Option<&RawTile>;
fn get_tile_mut(&mut self, index: usize) -> Option<&mut RawTile>;
fn get_tile_indices(&self) -> Vec<usize>;
fn clear(&mut self);
fn tiles_to_attributes(&self, dimension: Dimension3) -> (Vec<f32>, Vec<[f32; 4]>);
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub(super) struct DenseLayer {
tiles: Vec<RawTile>,
tile_count: usize,
}
impl Layer for DenseLayer {
fn set_tile(&mut self, index: usize, tile: RawTile) {
if let Some(inner_tile) = self.tiles.get_mut(index) {
self.tile_count += 1;
*inner_tile = tile;
} else {
warn!(
"tile is out of bounds at index {} and can not be set",
index
);
}
}
fn remove_tile(&mut self, index: usize) {
if let Some(tile) = self.tiles.get_mut(index) {
if self.tile_count != 0 {
self.tile_count -= 1;
tile.color.set_a(0.0);
}
}
}
fn get_tile(&self, index: usize) -> Option<&RawTile> {
self.tiles.get(index).and_then(|tile| {
if tile.color.a() == 0.0 {
None
} else {
Some(tile)
}
})
}
fn get_tile_mut(&mut self, index: usize) -> Option<&mut RawTile> {
self.tiles.get_mut(index).and_then(|tile| {
if tile.color.a() == 0.0 {
None
} else {
Some(tile)
}
})
}
fn get_tile_indices(&self) -> Vec<usize> {
let mut indices = Vec::with_capacity(self.tiles.len());
for (index, tile) in self.tiles.iter().enumerate() {
if tile.color.a() != 0.0 {
indices.push(index);
}
}
indices.shrink_to_fit();
indices
}
fn clear(&mut self) {
self.tiles.clear();
}
fn tiles_to_attributes(&self, _dimension: Dimension3) -> (Vec<f32>, Vec<[f32; 4]>) {
crate::chunk::raw_tile::dense_tiles_to_attributes(&self.tiles)
}
}
impl DenseLayer {
pub fn new(tiles: Vec<RawTile>) -> DenseLayer {
DenseLayer {
tiles,
tile_count: 0,
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Debug)]
pub(super) struct SparseLayer {
tiles: HashMap<usize, RawTile>,
}
impl Layer for SparseLayer {
fn set_tile(&mut self, index: usize, tile: RawTile) {
if tile.color.a() == 0.0 {
self.tiles.remove(&index);
}
self.tiles.insert(index, tile);
}
fn remove_tile(&mut self, index: usize) {
self.tiles.remove(&index);
}
fn get_tile(&self, index: usize) -> Option<&RawTile> {
self.tiles.get(&index)
}
fn get_tile_mut(&mut self, index: usize) -> Option<&mut RawTile> {
self.tiles.get_mut(&index)
}
fn get_tile_indices(&self) -> Vec<usize> {
let mut indices = Vec::with_capacity(self.tiles.len());
for index in self.tiles.keys() {
indices.push(*index);
}
indices
}
fn clear(&mut self) {
self.tiles.clear();
}
fn tiles_to_attributes(&self, dimension: Dimension3) -> (Vec<f32>, Vec<[f32; 4]>) {
crate::chunk::raw_tile::sparse_tiles_to_attributes(dimension, &self.tiles)
}
}
impl SparseLayer {
pub fn new(tiles: HashMap<usize, RawTile>) -> SparseLayer {
SparseLayer { tiles }
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum LayerKind {
Dense,
Sparse,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Debug)]
pub(super) enum LayerKindInner {
Dense(DenseLayer),
Sparse(SparseLayer),
}
impl AsRef<dyn Layer> for LayerKindInner {
fn as_ref(&self) -> &dyn Layer {
match self {
LayerKindInner::Dense(s) => s,
LayerKindInner::Sparse(s) => s,
}
}
}
impl AsMut<dyn Layer> for LayerKindInner {
fn as_mut(&mut self) -> &mut dyn Layer {
match self {
LayerKindInner::Dense(s) => s,
LayerKindInner::Sparse(s) => s,
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Debug)]
pub(super) struct SpriteLayer {
pub inner: LayerKindInner,
}