hv_ecs/
entity_builder.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::alloc::alloc::{alloc, dealloc, Layout};
9use crate::alloc::vec::Vec;
10use core::any::TypeId;
11use core::ptr::{self, NonNull};
12
13use hashbrown::hash_map::Entry;
14
15use crate::archetype::{TypeIdMap, TypeInfo};
16use crate::{align, Component, DynamicBundle};
17
18/// Helper for incrementally constructing a bundle of components with dynamic component types
19///
20/// Prefer reusing the same builder over creating new ones repeatedly.
21///
22/// ```
23/// # use hecs::*;
24/// let mut world = World::new();
25/// let mut builder = EntityBuilder::new();
26/// builder.add(123).add("abc");
27/// let e = world.spawn(builder.build()); // builder can now be reused
28/// assert_eq!(*world.get::<i32>(e).unwrap(), 123);
29/// assert_eq!(*world.get::<&str>(e).unwrap(), "abc");
30/// ```
31///
32/// `EntityBuilder<()>`s make no assumptions about components types. `EntityBuilder<Cloneable>` can
33/// be used instead to manage groups of components that all implement [`Clone`], allowing the built
34/// entity to be spawned repeatedly by reference.
35///
36/// ```
37/// # use hecs::*;
38/// let mut world = World::new();
39/// let mut builder = EntityBuilder::new_cloneable();
40/// builder.add(123).add("abc");
41/// let bundle = builder.build();
42/// let e = world.spawn(&bundle);
43/// let f = world.spawn(&bundle);
44/// assert_eq!(*world.get::<i32>(e).unwrap(), 123);
45/// assert_eq!(*world.get::<&str>(e).unwrap(), "abc");
46/// assert_eq!(*world.get::<i32>(f).unwrap(), 123);
47/// assert_eq!(*world.get::<&str>(f).unwrap(), "abc");
48/// ```
49pub struct EntityBuilder<M = ()> {
50    storage: NonNull<u8>,
51    layout: Layout,
52    cursor: usize,
53    info: Vec<(TypeInfo, usize, M)>,
54    ids: Vec<TypeId>,
55    indices: TypeIdMap<usize>,
56}
57
58impl<M> EntityBuilder<M> {
59    /// Checks to see if the component of type `T` exists
60    pub fn has<T: Component>(&self) -> bool {
61        self.indices.contains_key(&TypeId::of::<T>())
62    }
63
64    /// Borrow the component of type `T`, if it exists
65    pub fn get<T: Component>(&self) -> Option<&T> {
66        let index = self.indices.get(&TypeId::of::<T>())?;
67        let (_, offset, _) = self.info[*index];
68        unsafe {
69            let storage = self.storage.as_ptr().add(offset).cast::<T>();
70            Some(&*storage)
71        }
72    }
73
74    /// Uniquely borrow the component of type `T`, if it exists
75    pub fn get_mut<T: Component>(&mut self) -> Option<&mut T> {
76        let index = self.indices.get(&TypeId::of::<T>())?;
77        let (_, offset, _) = self.info[*index];
78        unsafe {
79            let storage = self.storage.as_ptr().add(offset).cast::<T>();
80            Some(&mut *storage)
81        }
82    }
83
84    /// Enumerate the types of the entity builder's components
85    pub fn component_types(&self) -> impl Iterator<Item = TypeId> + '_ {
86        self.info.iter().map(|(info, _, _)| info.id())
87    }
88
89    unsafe fn grow(
90        min_size: usize,
91        cursor: usize,
92        align: usize,
93        storage: NonNull<u8>,
94    ) -> (NonNull<u8>, Layout) {
95        let layout = Layout::from_size_align(min_size.next_power_of_two().max(64), align).unwrap();
96        let new_storage = NonNull::new_unchecked(alloc(layout));
97        ptr::copy_nonoverlapping(storage.as_ptr(), new_storage.as_ptr(), cursor);
98        (new_storage, layout)
99    }
100
101    /// Drop previously `add`ed components
102    ///
103    /// The builder is cleared implicitly when an entity is built, so this doesn't usually need to
104    /// be called.
105    pub fn clear(&mut self) {
106        self.ids.clear();
107        self.indices.clear();
108        self.cursor = 0;
109        unsafe {
110            for (ty, offset, _) in self.info.drain(..) {
111                ty.drop(self.storage.as_ptr().add(offset));
112            }
113        }
114    }
115
116    unsafe fn add_inner(&mut self, ptr: *mut u8, ty: TypeInfo, meta: M) {
117        match self.indices.entry(ty.id()) {
118            Entry::Occupied(occupied) => {
119                let index = *occupied.get();
120                let (ty, offset, _) = self.info[index];
121                let storage = self.storage.as_ptr().add(offset);
122
123                // Drop the existing value
124                ty.drop(storage);
125
126                // Overwrite the old value with our new one.
127                ptr::copy_nonoverlapping(ptr, storage, ty.layout().size());
128            }
129            Entry::Vacant(vacant) => {
130                let offset = align(self.cursor, ty.layout().align());
131                let end = offset + ty.layout().size();
132                if end > self.layout.size() || ty.layout().align() > self.layout.align() {
133                    let new_align = self.layout.align().max(ty.layout().align());
134                    let (new_storage, new_layout) =
135                        Self::grow(end, self.cursor, new_align, self.storage);
136                    if self.layout.size() != 0 {
137                        dealloc(self.storage.as_ptr(), self.layout);
138                    }
139                    self.storage = new_storage;
140                    self.layout = new_layout;
141                }
142
143                let addr = self.storage.as_ptr().add(offset);
144                ptr::copy_nonoverlapping(ptr, addr, ty.layout().size());
145
146                vacant.insert(self.info.len());
147                self.info.push((ty, offset, meta));
148                self.cursor = end;
149            }
150        }
151    }
152}
153
154impl EntityBuilder<()> {
155    /// Create a builder representing an entity with no components
156    pub fn new() -> Self {
157        Self::default()
158    }
159
160    /// Add `component` to the entity.
161    ///
162    /// If the bundle already contains a component of type `T`, it will
163    /// be dropped and replaced with the most recently added one.
164    pub fn add<T: Component>(&mut self, component: T) -> &mut Self {
165        self.add_bundle((component,))
166    }
167
168    /// Add all components in `bundle` to the entity.
169    ///
170    /// If the bundle contains any component which matches the type of a component
171    /// already in the `EntityBuilder`, the newly added component from the bundle
172    /// will replace the old component and the old component will be dropped.
173    pub fn add_bundle(&mut self, bundle: impl DynamicBundle) -> &mut Self {
174        unsafe {
175            bundle.put(|ptr, ty| self.add_inner(ptr, ty, ()));
176        }
177        self
178    }
179
180    /// Construct a `Bundle` suitable for spawning
181    pub fn build(&mut self) -> BuiltEntity<'_> {
182        self.info.sort_unstable_by_key(|x| x.0);
183        self.ids.extend(self.info.iter().map(|x| x.0.id()));
184        BuiltEntity { builder: self }
185    }
186}
187
188impl EntityBuilder<Cloneable> {
189    /// Create a builder representing an entity with no components, and which can only accept
190    /// components that implement `Clone`
191    pub fn new_cloneable() -> Self {
192        Self::default()
193    }
194
195    /// Add `component` to the entity.
196    ///
197    /// If the bundle already contains a component of type `T`, it will be dropped and replaced with
198    /// the most recently added one.
199    pub fn add<T: Component + Clone>(&mut self, mut component: T) -> &mut Self {
200        unsafe {
201            self.add_inner(
202                (&mut component as *mut T).cast(),
203                TypeInfo::of::<T>(),
204                Cloneable::new::<T>(),
205            );
206            core::mem::forget(component);
207        }
208        self
209    }
210
211    /// Convert into a value whose shared references are [`DynamicBundle`]s suitable for repeated
212    /// spawning
213    pub fn build(self) -> ReusableBuiltEntity {
214        self.into()
215    }
216}
217
218impl Clone for EntityBuilder<Cloneable> {
219    fn clone(&self) -> Self {
220        unsafe {
221            let result = Self {
222                storage: NonNull::new_unchecked(alloc(self.layout)),
223                layout: self.layout,
224                cursor: self.cursor,
225                info: self.info.clone(),
226                ids: Vec::new(),
227                indices: self.indices.clone(),
228            };
229            for &(_, offset, ref clone) in &self.info {
230                (clone.0)(self.storage.as_ptr().add(offset), &mut |src, ty| {
231                    result
232                        .storage
233                        .as_ptr()
234                        .add(offset)
235                        .copy_from_nonoverlapping(src, ty.layout().size())
236                });
237            }
238            result
239        }
240    }
241}
242
243unsafe impl<M> Send for EntityBuilder<M> {}
244unsafe impl<M> Sync for EntityBuilder<M> {}
245
246impl<M> Drop for EntityBuilder<M> {
247    fn drop(&mut self) {
248        // Ensure buffered components aren't leaked
249        self.clear();
250        if self.layout.size() != 0 {
251            unsafe {
252                dealloc(self.storage.as_ptr(), self.layout);
253            }
254        }
255    }
256}
257
258impl<M> Default for EntityBuilder<M> {
259    /// Create a builder representing an entity with no components
260    fn default() -> Self {
261        Self {
262            storage: NonNull::dangling(),
263            layout: Layout::from_size_align(0, 8).unwrap(),
264            cursor: 0,
265            info: Vec::new(),
266            ids: Vec::new(),
267            indices: Default::default(),
268        }
269    }
270}
271
272/// Type parameter for [`EntityBuilder`]s with cloneable components
273#[derive(Clone)]
274pub struct Cloneable(unsafe fn(*const u8, &mut dyn FnMut(*mut u8, TypeInfo)));
275
276impl Cloneable {
277    fn new<T: Component + Clone>() -> Self {
278        Self(|src, f| unsafe {
279            let mut tmp = (*src.cast::<T>()).clone();
280            f((&mut tmp as *mut T).cast(), TypeInfo::of::<T>());
281            core::mem::forget(tmp);
282        })
283    }
284}
285
286/// The output of an [`EntityBuilder`], suitable for passing to
287/// [`World::spawn`](crate::World::spawn) or [`World::insert`](crate::World::insert)
288pub struct BuiltEntity<'a> {
289    builder: &'a mut EntityBuilder<()>,
290}
291
292unsafe impl DynamicBundle for BuiltEntity<'_> {
293    fn with_ids<T>(&self, f: impl FnOnce(&[TypeId]) -> T) -> T {
294        f(&self.builder.ids)
295    }
296
297    #[doc(hidden)]
298    fn type_info(&self) -> Vec<TypeInfo> {
299        self.builder.info.iter().map(|x| x.0).collect()
300    }
301
302    unsafe fn put(self, mut f: impl FnMut(*mut u8, TypeInfo)) {
303        for (ty, offset, ()) in self.builder.info.drain(..) {
304            let ptr = self.builder.storage.as_ptr().add(offset);
305            f(ptr, ty);
306        }
307    }
308}
309
310impl Drop for BuiltEntity<'_> {
311    fn drop(&mut self) {
312        // Ensures components aren't leaked if `store` was never called, and prepares the builder
313        // for reuse.
314        self.builder.clear();
315    }
316}
317
318/// A collection of components that implement [`Clone`]
319///
320/// Built from, and convertible back into, [`EntityBuilder<Cloneable>`]
321#[derive(Clone)]
322pub struct ReusableBuiltEntity(EntityBuilder<Cloneable>);
323
324unsafe impl DynamicBundle for &'_ ReusableBuiltEntity {
325    fn with_ids<T>(&self, f: impl FnOnce(&[TypeId]) -> T) -> T {
326        f(&self.0.ids)
327    }
328
329    fn type_info(&self) -> Vec<TypeInfo> {
330        self.0.info.iter().map(|x| x.0).collect()
331    }
332
333    unsafe fn put(self, mut f: impl FnMut(*mut u8, TypeInfo)) {
334        for &(_, offset, ref clone) in &self.0.info {
335            let ptr = self.0.storage.as_ptr().add(offset);
336            (clone.0)(ptr, &mut f);
337        }
338    }
339}
340
341impl From<EntityBuilder<Cloneable>> for ReusableBuiltEntity {
342    fn from(mut x: EntityBuilder<Cloneable>) -> Self {
343        x.info.sort_unstable_by_key(|y| y.0);
344        x.ids.extend(x.info.iter().map(|y| y.0.id()));
345        Self(x)
346    }
347}
348
349impl From<ReusableBuiltEntity> for EntityBuilder<Cloneable> {
350    fn from(mut x: ReusableBuiltEntity) -> Self {
351        x.0.ids.clear();
352        x.0
353    }
354}