Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/world/spawn_batch.rs
6604 views
1
use crate::{
2
bundle::{Bundle, BundleSpawner, NoBundleEffect},
3
change_detection::MaybeLocation,
4
entity::{Entity, EntitySetIterator},
5
world::World,
6
};
7
use core::iter::FusedIterator;
8
9
/// An iterator that spawns a series of entities and returns the [ID](Entity) of
10
/// each spawned entity.
11
///
12
/// If this iterator is not fully exhausted, any remaining entities will be spawned when this type is dropped.
13
pub struct SpawnBatchIter<'w, I>
14
where
15
I: Iterator,
16
I::Item: Bundle,
17
{
18
inner: I,
19
spawner: BundleSpawner<'w>,
20
caller: MaybeLocation,
21
}
22
23
impl<'w, I> SpawnBatchIter<'w, I>
24
where
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
// Ensure all entity allocations are accounted for so `self.entities` can realloc if
32
// necessary
33
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
52
impl<I> Drop for SpawnBatchIter<'_, I>
53
where
54
I: Iterator,
55
I::Item: Bundle,
56
{
57
fn drop(&mut self) {
58
// Iterate through self in order to spawn remaining bundles.
59
for _ in &mut *self {}
60
// Apply any commands from those operations.
61
// SAFETY: `self.spawner` will be dropped immediately after this call.
62
unsafe { self.spawner.flush_commands() };
63
}
64
}
65
66
impl<I> Iterator for SpawnBatchIter<'_, I>
67
where
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
// SAFETY: bundle matches spawner type
76
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
84
impl<I, T> ExactSizeIterator for SpawnBatchIter<'_, I>
85
where
86
I: ExactSizeIterator<Item = T>,
87
T: Bundle,
88
{
89
fn len(&self) -> usize {
90
self.inner.len()
91
}
92
}
93
94
impl<I, T> FusedIterator for SpawnBatchIter<'_, I>
95
where
96
I: FusedIterator<Item = T>,
97
T: Bundle,
98
{
99
}
100
101
// SAFETY: Newly spawned entities are unique.
102
unsafe impl<I: Iterator, T> EntitySetIterator for SpawnBatchIter<'_, I>
103
where
104
I: FusedIterator<Item = T>,
105
T: Bundle,
106
{
107
}
108
109