use bevy_ecs::prelude::*;
#[derive(Resource)]
pub struct Pool {
available: Vec<Entity>,
}
impl Pool {
pub fn new<B: Bundle, F: FnMut() -> B>(
world: &mut World,
capacity: usize,
mut seed: F,
) -> Self {
let available = (0..capacity).map(|_| world.spawn(seed()).id()).collect();
Self { available }
}
#[must_use]
pub fn empty() -> Self {
Self {
available: Vec::new(),
}
}
pub fn acquire(&mut self, world: &mut World) -> Entity {
self.available
.pop()
.unwrap_or_else(|| world.spawn_empty().id())
}
pub fn release(&mut self, entity: Entity) {
self.available.push(entity);
}
#[must_use]
pub fn available(&self) -> usize {
self.available.len()
}
pub fn grow<B: Bundle, F: FnMut() -> B>(
&mut self,
world: &mut World,
count: usize,
mut seed: F,
) {
for _ in 0..count {
let entity = world.spawn(seed()).id();
self.available.push(entity);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn acquire_returns_unique_entities() {
let mut world = World::new();
let mut pool = Pool::new(&mut world, 3, || ());
let a = pool.acquire(&mut world);
let b = pool.acquire(&mut world);
let c = pool.acquire(&mut world);
assert_ne!(a, b);
assert_ne!(b, c);
assert_ne!(a, c);
}
#[test]
fn release_returns_entity_to_pool() {
let mut world = World::new();
let mut pool = Pool::new(&mut world, 2, || ());
let entity = pool.acquire(&mut world);
assert_eq!(pool.available(), 1);
pool.release(entity);
assert_eq!(pool.available(), 2);
}
#[test]
fn acquire_from_empty_pool_spawns_new() {
let mut world = World::new();
let mut pool = Pool::empty();
assert_eq!(pool.available(), 0);
let entity = pool.acquire(&mut world);
assert!(world.get_entity(entity).is_ok());
assert_eq!(pool.available(), 0);
}
#[test]
fn acquire_release_acquire_reuses_entity() {
let mut world = World::new();
let mut pool = Pool::new(&mut world, 1, || ());
let first = pool.acquire(&mut world);
pool.release(first);
let second = pool.acquire(&mut world);
assert_eq!(first, second);
}
#[test]
fn grow_increases_available_count() {
let mut world = World::new();
let mut pool = Pool::empty();
pool.grow(&mut world, 5, || ());
assert_eq!(pool.available(), 5);
}
}