async_ecs/entity/
builder.rs

1use crate::{access::WriteStorage, component::Component, system::SystemData, world::World};
2
3use super::Entity;
4
5/// A common trait for `EntityBuilder` and `LazyBuilder`, allowing either to be
6/// used. Entity is definitely alive, but the components may or may not exist
7/// before a call to `World::maintain`.
8pub trait Builder {
9    /// Appends a component and associates it with the entity.
10    ///
11    /// If a component was already associated with the entity, it should
12    /// overwrite the previous component.
13    ///
14    /// # Panics
15    ///
16    /// Panics if the component hasn't been `register()`ed in the
17    /// `World`.
18    fn with<C: Component + Send + Sync>(self, component: C) -> Self;
19
20    /// Finishes the building and returns the entity.
21    fn build(self) -> Entity;
22}
23
24/// The entity builder, allowing to
25/// build an entity together with its components.
26///
27/// ## Examples
28///
29/// ```
30/// use async_ecs::*;
31///
32/// struct Health(f32);
33///
34/// impl Component for Health {
35///     type Storage = HashMapStorage<Self>;
36/// }
37///
38/// struct Pos {
39///     x: f32,
40///     y: f32,
41/// }
42///
43/// impl Component for Pos {
44///     type Storage = DenseVecStorage<Self>;
45/// }
46///
47/// let mut world = World::default();
48/// world.register_component::<Health>();
49/// world.register_component::<Pos>();
50///
51/// let entity = world
52///     .create_entity() // This call returns `EntityBuilder`
53///     .with(Health(4.0))
54///     .with(Pos { x: 1.0, y: 3.0 })
55///     .build(); // Returns the `Entity`
56/// ```
57///
58/// ### Distinguishing Mandatory Components from Optional Components
59///
60/// ```
61/// use async_ecs::*;
62///
63/// struct MandatoryHealth(f32);
64///
65/// impl Component for MandatoryHealth {
66///     type Storage = HashMapStorage<Self>;
67/// }
68///
69/// struct OptionalPos {
70///     x: f32,
71///     y: f32,
72/// }
73///
74/// impl Component for OptionalPos {
75///     type Storage = DenseVecStorage<Self>;
76/// }
77///
78/// let mut world = World::default();
79/// world.register_component::<MandatoryHealth>();
80/// world.register_component::<OptionalPos>();
81///
82/// let mut entitybuilder = world.create_entity().with(MandatoryHealth(4.0));
83///
84/// // something trivial to serve as our conditional
85/// let include_optional = true;
86///
87/// if include_optional == true {
88///     entitybuilder = entitybuilder.with(OptionalPos { x: 1.0, y: 3.0 })
89/// }
90///
91/// let entity = entitybuilder.build();
92/// ```
93pub struct EntityBuilder<'a> {
94    world: &'a World,
95    entity: Entity,
96    built: bool,
97}
98
99impl<'a> EntityBuilder<'a> {
100    /// Create new entity builder.
101    pub fn new(world: &'a World) -> Self {
102        let entity = world.entities_mut().allocate();
103
104        Self {
105            world,
106            entity,
107            built: false,
108        }
109    }
110}
111
112impl<'a> Builder for EntityBuilder<'a> {
113    /// Inserts a component for this entity.
114    ///
115    /// If a component was already associated with the entity, it will
116    /// overwrite the previous component.
117    #[inline]
118    fn with<T: Component>(self, c: T) -> Self {
119        {
120            let mut storage = WriteStorage::<T>::fetch(&self.world);
121
122            storage.insert(self.entity, c).unwrap();
123        }
124
125        self
126    }
127
128    /// Finishes the building and returns the entity. As opposed to
129    /// `LazyBuilder`, the components are available immediately.
130    #[inline]
131    fn build(mut self) -> Entity {
132        self.built = true;
133
134        self.entity
135    }
136}
137
138impl Drop for EntityBuilder<'_> {
139    fn drop(&mut self) {
140        if !self.built {
141            self.world.entities_mut().delete(self.entity).unwrap();
142        }
143    }
144}