use crate::resources::{
GlyphGpuData, PointCloudGpuData, PolylineGpuData, SpriteGpuData, StreamtubeGpuData,
TensorGlyphGpuData,
};
macro_rules! curve_store {
($(#[$id_doc:meta])* $id:ident, $store:ident, $data:ty) => {
$(#[$id_doc])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct $id(pub(crate) usize);
impl $id {
pub fn from_index(index: usize) -> Self { Self(index) }
pub fn index(&self) -> usize { self.0 }
}
pub(crate) struct $store {
slots: Vec<Option<$data>>,
free_list: Vec<usize>,
}
impl $store {
pub fn new() -> Self {
Self { slots: Vec::new(), free_list: Vec::new() }
}
pub fn insert(&mut self, data: $data) -> $id {
if let Some(idx) = self.free_list.pop() {
self.slots[idx] = Some(data);
$id(idx)
} else {
let idx = self.slots.len();
self.slots.push(Some(data));
$id(idx)
}
}
pub fn get(&self, id: $id) -> Option<&$data> {
self.slots.get(id.0)?.as_ref()
}
pub fn replace(&mut self, id: $id, data: $data) -> bool {
match self.slots.get_mut(id.0) {
Some(slot) if slot.is_some() => { *slot = Some(data); true }
_ => false,
}
}
pub fn remove(&mut self, id: $id) -> bool {
if let Some(slot) = self.slots.get_mut(id.0) {
if slot.is_some() {
*slot = None;
self.free_list.push(id.0);
return true;
}
}
false
}
pub fn contains(&self, id: $id) -> bool {
self.get(id).is_some()
}
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.slots.iter().filter(|s| s.is_some()).count()
}
}
};
}
curve_store!(
PolylineId,
PolylineStore,
PolylineGpuData
);
curve_store!(
StreamtubeId,
StreamtubeStore,
StreamtubeGpuData
);
curve_store!(
TubeId,
TubeStore,
StreamtubeGpuData
);
curve_store!(
RibbonId,
RibbonStore,
StreamtubeGpuData
);
curve_store!(
PointCloudId,
PointCloudStore,
PointCloudGpuData
);
curve_store!(
GlyphSetId,
GlyphSetStore,
GlyphGpuData
);
curve_store!(
TensorGlyphSetId,
TensorGlyphSetStore,
TensorGlyphGpuData
);
curve_store!(
SpriteSetId,
SpriteSetStore,
SpriteGpuData
);
curve_store!(
SpriteInstanceSetId,
SpriteInstanceSetStore,
SpriteGpuData
);