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