#![allow(missing_docs)]
use std::{
fmt::Debug,
marker::PhantomData,
slice::{Iter, IterMut},
};
use super::coordinate_system::CoordinateSystem;
#[cfg(feature = "bevy")]
use bevy::ecs::component::Component;
#[cfg(feature = "reflect")]
use bevy::{ecs::reflect::ReflectComponent, reflect::Reflect};
pub type GridIndex = usize;
pub trait Grid<C: CoordinateSystem>: Clone {
type Position: Debug;
fn coord_system(&self) -> &C;
fn directions_count(&self) -> usize;
fn total_size(&self) -> usize;
fn get_neighbours_in_all_directions(
&self,
grid_index: GridIndex,
neighbours_buffer: &mut Vec<Option<GridIndex>>,
);
fn index_from_pos(&self, pos: &Self::Position) -> GridIndex;
fn pos_from_index(&self, index: GridIndex) -> Self::Position;
}
#[derive(Clone)]
#[cfg_attr(feature = "bevy", derive(Component, Default))]
#[cfg_attr(feature = "reflect", derive(Reflect), reflect(Component))]
pub struct GridData<C, D, G>
where
C: CoordinateSystem,
G: Grid<C>,
{
grid: G,
data: Vec<D>,
#[cfg_attr(feature = "reflect", reflect(ignore))]
_phantom: PhantomData<C>,
}
impl<C, D, G> GridData<C, D, G>
where
C: CoordinateSystem,
G: Grid<C>,
{
pub fn new(grid: G, data: Vec<D>) -> Self {
Self {
grid,
data,
_phantom: PhantomData,
}
}
#[inline]
pub fn grid(&self) -> &G {
&self.grid
}
#[inline]
pub fn set_raw(&mut self, index: GridIndex, value: D) {
self.data[index] = value;
}
#[inline]
pub fn set<N: NodeRef<C, G>>(&mut self, index_ref: N, value: D) {
let idx = index_ref.to_index(&self.grid);
self.data[idx] = value;
}
#[inline]
pub fn get(&self, index: GridIndex) -> &D {
&self.data[index]
}
#[inline]
pub fn get_mut(&mut self, index: GridIndex) -> &mut D {
&mut self.data[index]
}
#[inline]
pub fn iter(&self) -> Iter<'_, D> {
self.data.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, D> {
self.data.iter_mut()
}
#[inline]
pub fn indexes(&self) -> std::ops::Range<usize> {
0..self.grid.total_size()
}
}
impl<C: CoordinateSystem, D: Clone, G: Grid<C>> GridData<C, D, G> {
pub fn reset(&mut self, value: D) {
for d in &mut self.data {
*d = value.clone();
}
}
}
pub trait NodeRef<C: CoordinateSystem, G: Grid<C>> {
fn to_index(&self, grid: &G) -> GridIndex;
}
impl<C: CoordinateSystem, G: Grid<C>> NodeRef<C, G> for GridIndex {
fn to_index(&self, _grid: &G) -> GridIndex {
*self
}
}