bevy_ecs/world/
spawn_batch.rs1use bevy_ptr::move_as_ptr;
2
3use crate::{
4    bundle::{Bundle, BundleSpawner, NoBundleEffect},
5    change_detection::MaybeLocation,
6    entity::{Entity, EntitySetIterator},
7    world::World,
8};
9use core::iter::FusedIterator;
10
11pub struct SpawnBatchIter<'w, I>
16where
17    I: Iterator,
18    I::Item: Bundle<Effect: NoBundleEffect>,
19{
20    inner: I,
21    spawner: BundleSpawner<'w>,
22    caller: MaybeLocation,
23}
24
25impl<'w, I> SpawnBatchIter<'w, I>
26where
27    I: Iterator,
28    I::Item: Bundle<Effect: NoBundleEffect>,
29{
30    #[inline]
31    #[track_caller]
32    pub(crate) fn new(world: &'w mut World, iter: I, caller: MaybeLocation) -> Self {
33        world.flush();
36
37        let change_tick = world.change_tick();
38
39        let (lower, upper) = iter.size_hint();
40        let length = upper.unwrap_or(lower);
41        world.entities.reserve(length as u32);
42
43        let mut spawner = BundleSpawner::new::<I::Item>(world, change_tick);
44        spawner.reserve_storage(length);
45
46        Self {
47            inner: iter,
48            spawner,
49            caller,
50        }
51    }
52}
53
54impl<I> Drop for SpawnBatchIter<'_, I>
55where
56    I: Iterator,
57    I::Item: Bundle<Effect: NoBundleEffect>,
58{
59    fn drop(&mut self) {
60        for _ in &mut *self {}
62        unsafe { self.spawner.flush_commands() };
65    }
66}
67
68impl<I> Iterator for SpawnBatchIter<'_, I>
69where
70    I: Iterator,
71    I::Item: Bundle<Effect: NoBundleEffect>,
72{
73    type Item = Entity;
74
75    fn next(&mut self) -> Option<Entity> {
76        let bundle = self.inner.next()?;
77        move_as_ptr!(bundle);
78        unsafe { Some(self.spawner.spawn::<I::Item>(bundle, self.caller)) }
83    }
84
85    fn size_hint(&self) -> (usize, Option<usize>) {
86        self.inner.size_hint()
87    }
88}
89
90impl<I, T> ExactSizeIterator for SpawnBatchIter<'_, I>
91where
92    I: ExactSizeIterator<Item = T>,
93    T: Bundle<Effect: NoBundleEffect>,
94{
95    fn len(&self) -> usize {
96        self.inner.len()
97    }
98}
99
100impl<I, T> FusedIterator for SpawnBatchIter<'_, I>
101where
102    I: FusedIterator<Item = T>,
103    T: Bundle<Effect: NoBundleEffect>,
104{
105}
106
107unsafe impl<I: Iterator, T> EntitySetIterator for SpawnBatchIter<'_, I>
109where
110    I: FusedIterator<Item = T>,
111    T: Bundle<Effect: NoBundleEffect>,
112{
113}