use crate::prelude::*;
use bevy_ecs::{prelude::*, relationship::RelatedSpawnerCommands};
use bevy_transform::prelude::*;
use smallvec::SmallVec;
pub trait BigSpaceCommands {
fn spawn_big_space(&mut self, root_grid: Grid, child_builder: impl FnOnce(&mut GridCommands));
fn spawn_big_space_default(&mut self, child_builder: impl FnOnce(&mut GridCommands));
fn grid(&mut self, entity: Entity, grid: Grid) -> GridCommands<'_>;
}
impl BigSpaceCommands for Commands<'_, '_> {
fn spawn_big_space(&mut self, grid: Grid, root_grid: impl FnOnce(&mut GridCommands)) {
let mut entity_commands = self.spawn(BigSpaceRootBundle::default());
let mut cmd = GridCommands {
entity: entity_commands.id(),
commands: entity_commands.commands(),
grid,
children: Default::default(),
};
root_grid(&mut cmd);
}
fn spawn_big_space_default(&mut self, child_builder: impl FnOnce(&mut GridCommands)) {
self.spawn_big_space(Grid::default(), child_builder);
}
fn grid(&mut self, entity: Entity, grid: Grid) -> GridCommands<'_> {
GridCommands {
entity,
commands: self.reborrow(),
grid,
children: Default::default(),
}
}
}
pub struct GridCommands<'a> {
entity: Entity,
commands: Commands<'a, 'a>,
grid: Grid,
children: SmallVec<[Entity; 8]>,
}
impl<'a> GridCommands<'a> {
pub fn grid(&mut self) -> &Grid {
&self.grid
}
pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
self.commands.entity(self.entity).insert(bundle);
self
}
#[inline]
pub fn spawn(&mut self, bundle: impl Bundle) -> SpatialEntityCommands<'_> {
let entity = self.commands.spawn(bundle).id();
self.children.push(entity);
SpatialEntityCommands {
entity,
commands: self.commands.reborrow(),
}
}
#[inline]
pub fn spawn_spatial(&mut self, bundle: impl Bundle) -> SpatialEntityCommands<'_> {
let entity = self
.spawn((
#[cfg(feature = "bevy_camera")]
bevy_camera::visibility::Visibility::default(),
Transform::default(),
CellCoord::default(),
))
.insert(bundle)
.id();
SpatialEntityCommands {
entity,
commands: self.commands.reborrow(),
}
}
#[inline]
pub fn id(&self) -> Entity {
self.entity
}
#[inline]
pub fn with_spatial(&mut self, spatial: impl FnOnce(&mut SpatialEntityCommands)) -> &mut Self {
spatial(&mut self.spawn_spatial(()));
self
}
#[inline]
pub fn with_grid(
&mut self,
new_grid: Grid,
builder: impl FnOnce(&mut GridCommands),
) -> &mut Self {
builder(&mut self.spawn_grid(new_grid, ()));
self
}
#[inline]
pub fn with_grid_default(&mut self, builder: impl FnOnce(&mut GridCommands)) -> &mut Self {
self.with_grid(Grid::default(), builder)
}
#[inline]
pub fn spawn_grid(&mut self, new_grid: Grid, bundle: impl Bundle) -> GridCommands<'_> {
let entity = self
.spawn((
#[cfg(feature = "bevy_camera")]
bevy_camera::visibility::Visibility::default(),
Transform::default(),
CellCoord::default(),
Grid::default(),
))
.insert(bundle)
.id();
GridCommands {
entity,
commands: self.commands.reborrow(),
grid: new_grid,
children: Default::default(),
}
}
pub fn spawn_grid_default(&mut self, bundle: impl Bundle) -> GridCommands<'_> {
self.spawn_grid(Grid::default(), bundle)
}
#[inline]
pub fn commands(&mut self) -> &mut Commands<'a, 'a> {
&mut self.commands
}
#[inline]
pub fn with_child<B: Bundle>(&mut self, bundle: B) -> &mut Self {
self.commands.entity(self.entity).with_child(bundle);
self
}
}
impl Drop for GridCommands<'_> {
fn drop(&mut self) {
let entity = self.entity;
self.commands
.entity(entity)
.insert(core::mem::take(&mut self.grid))
.add_children(&self.children);
}
}
pub struct SpatialEntityCommands<'a> {
entity: Entity,
commands: Commands<'a, 'a>,
}
impl<'a> SpatialEntityCommands<'a> {
pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
self.commands.entity(self.entity).insert(bundle);
self
}
pub fn remove<T>(&mut self) -> &mut Self
where
T: Bundle,
{
self.commands.entity(self.entity).remove::<T>();
self
}
pub fn with_children(
&mut self,
spawn_children: impl FnOnce(&mut RelatedSpawnerCommands<'_, ChildOf>),
) -> &mut Self {
self.commands
.entity(self.entity)
.with_children(|child_builder| spawn_children(child_builder));
self
}
pub fn with_child<B: Bundle>(&mut self, bundle: B) -> &mut Self {
self.commands.entity(self.entity).with_child(bundle);
self
}
pub fn id(&self) -> Entity {
self.entity
}
pub fn commands(&mut self) -> &mut Commands<'a, 'a> {
&mut self.commands
}
}