use serde::{Deserialize, Serialize}; use std::ops::{Index, IndexMut}; use vek::*; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Grid { cells: Vec, size: Vec2, // TODO: use u32 } impl Grid { pub fn from_raw(size: Vec2, raw: impl Into>) -> Self { let cells = raw.into(); assert_eq!(size.product() as usize, cells.len()); Self { cells, size } } pub fn populate_from(size: Vec2, mut f: impl FnMut(Vec2) -> T) -> Self { Self { cells: (0..size.y) .map(|y| (0..size.x).map(move |x| Vec2::new(x, y))) .flatten() .map(&mut f) .collect(), size, } } pub fn new(size: Vec2, default_cell: T) -> Self where T: Clone, { Self { cells: vec![default_cell; size.product() as usize], size, } } fn idx(&self, pos: Vec2) -> Option { if pos.map2(self.size, |e, sz| e >= 0 && e < sz).reduce_and() { Some((pos.y * self.size.x + pos.x) as usize) } else { None } } pub fn size(&self) -> Vec2 { self.size } pub fn get(&self, pos: Vec2) -> Option<&T> { self.cells.get(self.idx(pos)?) } pub fn get_mut(&mut self, pos: Vec2) -> Option<&mut T> { let idx = self.idx(pos)?; self.cells.get_mut(idx) } pub fn set(&mut self, pos: Vec2, cell: T) -> Option { let idx = self.idx(pos)?; self.cells.get_mut(idx).map(|c| core::mem::replace(c, cell)) } pub fn iter(&self) -> impl Iterator, &T)> + '_ { let w = self.size.x; self.cells .iter() .enumerate() .map(move |(i, cell)| (Vec2::new(i as i32 % w, i as i32 / w), cell)) } pub fn iter_mut(&mut self) -> impl Iterator, &mut T)> + '_ { let w = self.size.x; self.cells .iter_mut() .enumerate() .map(move |(i, cell)| (Vec2::new(i as i32 % w, i as i32 / w), cell)) } pub fn iter_area( &self, pos: Vec2, size: Vec2, ) -> impl Iterator, &T)>> + '_ { (0..size.x) .map(move |x| { (0..size.y).map(move |y| { Some(( pos + Vec2::new(x, y), &self.cells[self.idx(pos + Vec2::new(x, y))?], )) }) }) .flatten() } pub fn raw(&self) -> &[T] { &self.cells } } impl Index> for Grid { type Output = T; fn index(&self, index: Vec2) -> &Self::Output { self.get(index).unwrap_or_else(|| { panic!( "Attempted to index grid of size {:?} with index {:?}", self.size(), index ) }) } } impl IndexMut> for Grid { fn index_mut(&mut self, index: Vec2) -> &mut Self::Output { let size = self.size(); self.get_mut(index).unwrap_or_else(|| { panic!( "Attempted to index grid of size {:?} with index {:?}", size, index ) }) } }