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