use bevy::{
ecs::{
entity::{EntityMapper, MapEntities},
reflect::ReflectMapEntities,
},
prelude::*,
};
use crate::map::TilemapSize;
use super::TilePos;
#[derive(Component, Reflect, Default, Debug, Clone)]
#[reflect(Component, MapEntities)]
pub struct TileStorage {
tiles: Vec<Option<Entity>>,
pub size: TilemapSize,
}
impl MapEntities for TileStorage {
fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
for entity in self.tiles.iter_mut().flatten() {
*entity = entity_mapper.get_mapped(*entity);
}
}
}
impl TileStorage {
pub fn empty(size: TilemapSize) -> Self {
Self {
tiles: vec![None; size.count()],
size,
}
}
pub fn get(&self, tile_pos: &TilePos) -> Option<Entity> {
self.tiles[tile_pos.to_index(&self.size)]
}
pub fn checked_get(&self, tile_pos: &TilePos) -> Option<Entity> {
if tile_pos.within_map_bounds(&self.size) {
self.tiles[tile_pos.to_index(&self.size)]
} else {
None
}
}
pub fn set(&mut self, tile_pos: &TilePos, tile_entity: Entity) {
self.tiles[tile_pos.to_index(&self.size)].replace(tile_entity);
}
pub fn checked_set(&mut self, tile_pos: &TilePos, tile_entity: Entity) {
if tile_pos.within_map_bounds(&self.size) {
self.tiles[tile_pos.to_index(&self.size)].replace(tile_entity);
}
}
pub fn iter(&self) -> impl Iterator<Item = &Option<Entity>> {
self.tiles.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Option<Entity>> {
self.tiles.iter_mut()
}
pub fn remove(&mut self, tile_pos: &TilePos) -> Option<Entity> {
self.tiles[tile_pos.to_index(&self.size)].take()
}
pub fn checked_remove(&mut self, tile_pos: &TilePos) -> Option<Entity> {
self.tiles.get_mut(tile_pos.to_index(&self.size))?.take()
}
pub fn drain(&mut self) -> impl Iterator<Item = Entity> + use<'_> {
self.tiles.iter_mut().filter_map(|opt| opt.take())
}
}