pub(crate) mod entity;
mod layer;
pub(crate) mod mesh;
pub mod raw_tile;
pub(crate) mod render;
pub(crate) mod system;
use crate::{lib::*, tile::Tile};
pub use layer::LayerKind;
use layer::{DenseLayer, LayerKindInner, SparseLayer, SpriteLayer};
pub use raw_tile::RawTile;
type SpriteLayers = Vec<Option<SpriteLayer>>;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug)]
pub(crate) struct Chunk {
point: Point2,
z_layers: Vec<SpriteLayers>,
user_data: u128,
#[cfg_attr(feature = "serde", serde(skip))]
mesh: Option<Handle<Mesh>>,
entity: Option<Entity>,
}
impl Chunk {
pub(crate) fn new(
point: Point2,
sprite_layers: &[Option<LayerKind>],
dimensions: Dimension3,
) -> Chunk {
let mut chunk = Chunk {
point,
z_layers: vec![vec![None; sprite_layers.len()]; dimensions.depth as usize],
user_data: 0,
mesh: None,
entity: None,
};
for (sprite_order, kind) in sprite_layers.iter().enumerate() {
if let Some(kind) = kind {
chunk.add_sprite_layer(kind, sprite_order, dimensions)
}
}
chunk
}
pub(crate) fn add_sprite_layer(
&mut self,
kind: &LayerKind,
sprite_order: usize,
dimensions: Dimension3,
) {
for z in 0..dimensions.depth as usize {
match kind {
LayerKind::Dense => {
let tiles = vec![
RawTile {
index: 0,
color: Color::rgba(0.0, 0.0, 0.0, 0.0)
};
(dimensions.width * dimensions.height) as usize
];
if let Some(z_layer) = self.z_layers.get_mut(z) {
if let Some(sprite_order_layer) = z_layer.get_mut(sprite_order) {
if !sprite_order_layer.is_some() {
*sprite_order_layer = Some(SpriteLayer {
inner: LayerKindInner::Dense(DenseLayer::new(tiles)),
});
}
} else {
error!("sprite layer {} could not be added?", sprite_order);
}
} else {
error!("sprite layer {} is out of bounds", sprite_order);
}
}
LayerKind::Sparse => {
if let Some(z_layer) = self.z_layers.get_mut(z) {
if let Some(sprite_order_layer) = z_layer.get_mut(sprite_order) {
if !sprite_order_layer.is_some() {
*sprite_order_layer = Some(SpriteLayer {
inner: LayerKindInner::Sparse(SparseLayer::new(
HashMap::default(),
)),
});
}
} else {
error!("sprite layer {} is out of bounds", sprite_order);
}
} else {
error!("sprite layer {} is out of bounds", sprite_order);
}
}
}
}
}
pub(crate) fn point(&self) -> Point2 {
self.point
}
pub(crate) fn move_sprite_layer(&mut self, from_layer_z: usize, to_layer_z: usize) {
for sprite_layers in &mut self.z_layers {
if let Some(layer) = sprite_layers.get(to_layer_z) {
if layer.is_some() {
error!("sprite layer {} exists and can not be moved", to_layer_z);
return;
}
}
sprite_layers.swap(from_layer_z, to_layer_z);
}
}
pub(crate) fn remove_sprite_layer(&mut self, sprite_layer: usize) {
for z_layer in &mut self.z_layers {
z_layer.remove(sprite_layer);
}
}
pub(crate) fn set_mesh(&mut self, mesh: Handle<Mesh>) {
self.mesh = Some(mesh);
}
pub(crate) fn mesh(&self) -> Option<&Handle<Mesh>> {
self.mesh.as_ref()
}
pub(crate) fn take_mesh(&mut self) -> Option<Handle<Mesh>> {
self.mesh.take()
}
pub(crate) fn set_tile(&mut self, index: usize, tile: Tile<Point3>) {
if let Some(z_depth) = self.z_layers.get_mut(tile.point.z as usize) {
if let Some(layer) = z_depth.get_mut(tile.sprite_order) {
let raw_tile = RawTile {
index: tile.sprite_index,
color: tile.tint,
};
if let Some(layer) = layer {
layer.inner.as_mut().set_tile(index, raw_tile);
} else {
error!("sprite layer {} does not exist", tile.sprite_order);
}
} else {
error!(
"{} exceeded max number of sprite layers: {}",
tile.sprite_order,
z_depth.len()
);
}
} else {
error!("z layer {} does not exist", tile.point.z);
}
}
pub(crate) fn remove_tile(&mut self, index: usize, sprite_layer: usize, z_depth: usize) {
if let Some(layers) = self.z_layers.get_mut(z_depth) {
if let Some(layer) = layers.get_mut(sprite_layer) {
if let Some(layer) = layer {
layer.inner.as_mut().remove_tile(index);
} else {
error!("sprite layer {} does not exist", index);
}
} else {
error!(
"{} exceeded max number of sprite layers: {}",
index,
layers.len()
);
}
} else {
error!("sprite layer {} does not exist", sprite_layer);
}
}
pub(crate) fn set_entity(&mut self, entity: Entity) {
self.entity = Some(entity);
}
pub(crate) fn get_entity(&self) -> Option<Entity> {
self.entity
}
pub(crate) fn take_entity(&mut self) -> Option<Entity> {
self.entity.take()
}
pub(crate) fn get_tile(
&self,
index: usize,
sprite_order: usize,
z_depth: usize,
) -> Option<&RawTile> {
self.z_layers.get(z_depth).and_then(|z_depth| {
z_depth.get(sprite_order).and_then(|layer| {
layer
.as_ref()
.and_then(|layer| layer.inner.as_ref().get_tile(index))
})
})
}
pub(crate) fn get_tile_mut(
&mut self,
index: usize,
sprite_order: usize,
z_depth: usize,
) -> Option<&mut RawTile> {
self.z_layers.get_mut(z_depth).and_then(|z_depth| {
z_depth.get_mut(sprite_order).and_then(|layer| {
layer
.as_mut()
.and_then(|layer| layer.inner.as_mut().get_tile_mut(index))
})
})
}
pub(crate) fn clear_layer(&mut self, layer: usize) {
if let Some(sprite_layer) = self.z_layers.get_mut(layer) {
for layer in sprite_layer.iter_mut().flatten() {
layer.inner.as_mut().clear();
}
}
}
pub(crate) fn tiles_to_renderer_parts(
&self,
dimensions: Dimension3,
) -> (Vec<f32>, Vec<[f32; 4]>) {
let mut tile_indices = Vec::new();
let mut tile_colors = Vec::new();
for depth in &self.z_layers {
for layer in depth.iter().flatten() {
let (mut indices, mut colors) =
layer.inner.as_ref().tiles_to_attributes(dimensions);
tile_indices.append(&mut indices);
tile_colors.append(&mut colors);
}
}
(tile_indices, tile_colors)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_layer() {
let point = Point2::new(0, 0);
let layers = vec![
Some(LayerKind::Dense),
Some(LayerKind::Sparse),
None,
Some(LayerKind::Sparse),
None,
];
let dimensions = Dimension3::new(5, 5, 3);
let mut chunk = Chunk::new(point, &[None, None, None, None, None], dimensions);
for (x, layer) in layers.iter().enumerate() {
if let Some(layer) = layer {
chunk.add_sprite_layer(&layer, x, dimensions);
}
}
assert_eq!(chunk.z_layers.len(), 3);
for layer in &chunk.z_layers {
assert_eq!(layer.len(), 5);
}
chunk.move_sprite_layer(1, 2);
let sprite_layers = chunk.z_layers.get(0).unwrap();
assert_eq!(sprite_layers.get(1).unwrap().as_ref(), None);
assert!(sprite_layers.get(0).unwrap().as_ref().is_some());
chunk.remove_sprite_layer(0);
assert_eq!(chunk.z_layers.len(), 3);
for layer in &chunk.z_layers {
assert_eq!(layer.len(), 4);
}
}
}