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