1use core::{any::TypeId, iter::FusedIterator};
2
3use alloc::collections::VecDeque;
4use smallvec::SmallVec;
5
6use crate::{
7 bundle::{Bundle, ComponentBundle, DynamicBundle, DynamicComponentBundle},
8 component::{Component, ComponentInfo, ComponentRegistry},
9 entity::{Entity, EntityId, EntityLoc, EntitySet},
10 relation::Relation,
11 type_id,
12 world::{iter_reserve_hint, World},
13};
14
15use super::{buffer::LocalActionBuffer, ActionBuffer, ActionFn, LocalActionFn};
16
17pub struct ActionEncoder<'a> {
26 actions: &'a mut VecDeque<ActionFn<'static>>,
27 entities: &'a EntitySet,
28}
29
30impl<'a> ActionEncoder<'a> {
31 #[inline(always)]
33 pub(crate) fn new(buffer: &'a mut ActionBuffer, entities: &'a EntitySet) -> Self {
34 ActionEncoder {
35 actions: buffer.actions(),
36 entities,
37 }
38 }
39
40 #[inline(always)]
43 pub fn is_empty(&self) -> bool {
44 self.actions.is_empty()
45 }
46
47 #[inline(always)]
49 pub fn allocate(&self) -> EntityLoc<'_> {
50 self.entities.alloc()
51 }
52
53 #[inline(always)]
55 pub fn spawn_one<T>(&mut self, component: T) -> EntityLoc<'_>
56 where
57 T: Component + Send + 'static,
58 {
59 let entity = self.entities.alloc();
60 self.insert(entity, component);
61 entity
62 }
63
64 #[inline(always)]
66 pub fn spawn<B>(&mut self, bundle: B) -> EntityLoc<'_>
67 where
68 B: DynamicComponentBundle + Send + 'static,
69 {
70 let entity = self.entities.alloc();
71 self.insert_bundle(entity, bundle);
72 entity
73 }
74
75 #[inline(always)]
77 pub fn spawn_external<B>(&mut self, bundle: B) -> EntityLoc<'_>
78 where
79 B: DynamicBundle + Send + 'static,
80 {
81 let entity = self.entities.alloc();
82 self.insert_external_bundle(entity, bundle);
83 entity
84 }
85
86 #[inline(always)]
89 pub fn spawn_batch<I>(&mut self, bundles: I) -> SpawnBatch<I>
90 where
91 I: IntoIterator,
92 I::Item: ComponentBundle + Send + 'static,
93 {
94 self.push_fn(|world| {
95 world.ensure_bundle_registered::<I::Item>();
96 });
97
98 SpawnBatch {
99 bundles,
100 encoder: self.reborrow(),
101 }
102 }
103
104 #[inline(always)]
107 pub fn spawn_external_batch<I>(&mut self, bundles: I) -> SpawnBatch<I>
108 where
109 I: IntoIterator,
110 I::Item: Bundle + Send + 'static,
111 {
112 SpawnBatch {
113 bundles,
114 encoder: self.reborrow(),
115 }
116 }
117
118 #[inline(always)]
120 pub fn despawn(&mut self, entity: impl Entity) {
121 let id = entity.id();
122 self.push_fn(move |world| {
123 let _ = world.despawn(id);
124 })
125 }
126
127 #[inline(always)]
129 pub fn despawn_batch(&mut self, entities: impl IntoIterator<Item = EntityId>) {
130 let entities = entities.into_iter();
131
132 match entities.size_hint() {
133 (_, Some(upper)) if upper <= 8 => {
134 let entities = entities.into_iter().collect::<SmallVec<[_; 8]>>();
135 self.push_fn(move |world| {
136 let _ = world.despawn_batch(entities);
137 });
138 }
139 (_, Some(upper)) if upper <= 16 => {
140 let entities = entities.into_iter().collect::<SmallVec<[_; 16]>>();
141 self.push_fn(move |world| {
142 let _ = world.despawn_batch(entities);
143 });
144 }
145 (_, Some(upper)) if upper <= 32 => {
146 let entities = entities.into_iter().collect::<SmallVec<[_; 32]>>();
147 self.push_fn(move |world| {
148 let _ = world.despawn_batch(entities);
149 });
150 }
151 _ => {
152 let entities = entities.into_iter().collect::<SmallVec<[_; 64]>>();
153 self.push_fn(move |world| {
154 let _ = world.despawn_batch(entities);
155 });
156 }
157 }
158 }
159
160 #[inline(always)]
162 pub fn insert<T>(&mut self, entity: impl Entity, component: T)
163 where
164 T: Component + Send,
165 {
166 let id = entity.id();
167 self.push_fn(move |world| {
168 let _ = world.insert(id, component);
169 });
170 }
171
172 #[inline(always)]
174 pub fn insert_external<T>(&mut self, entity: impl Entity, component: T)
175 where
176 T: Send + 'static,
177 {
178 let id = entity.id();
179 self.push_fn(move |world| {
180 let _ = world.insert_external(id, component);
181 });
182 }
183
184 #[inline(always)]
186 pub fn with<F, T>(&mut self, entity: impl Entity, f: F)
187 where
188 F: FnOnce() -> T + Send + 'static,
189 T: Component,
190 {
191 let id = entity.id();
192 self.push_fn(move |world| {
193 let _ = world.with(id, f);
194 });
195 }
196
197 #[inline(always)]
199 pub fn with_external<F, T>(&mut self, entity: impl Entity, f: F)
200 where
201 F: FnOnce() -> T + Send + 'static,
202 T: 'static,
203 {
204 let id = entity.id();
205 self.push_fn(move |world| {
206 let _ = world.with_external(id, f);
207 });
208 }
209
210 #[inline(always)]
212 pub fn insert_bundle<B>(&mut self, entity: impl Entity, bundle: B)
213 where
214 B: DynamicComponentBundle + Send + 'static,
215 {
216 let id = entity.id();
217 self.push_fn(move |world| {
218 let _ = world.insert_bundle(id, bundle);
219 });
220 }
221
222 #[inline(always)]
224 pub fn insert_external_bundle<B>(&mut self, entity: impl Entity, bundle: B)
225 where
226 B: DynamicBundle + Send + 'static,
227 {
228 let id = entity.id();
229 self.push_fn(move |world| {
230 let _ = world.insert_external_bundle(id, bundle);
231 });
232 }
233
234 #[inline(always)]
236 pub fn with_bundle<B>(&mut self, entity: impl Entity, bundle: B)
237 where
238 B: DynamicComponentBundle + Send + 'static,
239 {
240 let id = entity.id();
241 self.push_fn(move |world| {
242 let _ = world.with_bundle(id, bundle);
243 });
244 }
245
246 #[inline(always)]
248 pub fn with_external_bundle<B>(&mut self, entity: impl Entity, bundle: B)
249 where
250 B: DynamicBundle + Send + 'static,
251 {
252 let id = entity.id();
253 self.push_fn(move |world| {
254 let _ = world.with_external_bundle(id, bundle);
255 });
256 }
257
258 #[inline(always)]
260 pub fn drop<T>(&mut self, entity: impl Entity)
261 where
262 T: 'static,
263 {
264 self.drop_erased(entity, type_id::<T>())
265 }
266
267 #[inline(always)]
269 pub fn drop_batch<T>(&mut self, entities: impl IntoIterator<Item = EntityId>)
270 where
271 T: 'static,
272 {
273 self.drop_erased_batch(entities, type_id::<T>())
274 }
275
276 #[inline(always)]
278 pub fn drop_erased(&mut self, entity: impl Entity, ty: TypeId) {
279 let id = entity.id();
280 self.push_fn(move |world| {
281 let _ = world.drop_erased(id, ty);
282 })
283 }
284
285 #[inline(always)]
287 pub fn drop_erased_batch(&mut self, entities: impl IntoIterator<Item = EntityId>, ty: TypeId) {
288 let entities = entities.into_iter();
289
290 match entities.size_hint() {
291 (_, Some(upper)) if upper <= 8 => {
292 let entities = entities.into_iter().collect::<SmallVec<[_; 8]>>();
293 self.push_fn(move |world| {
294 let _ = world.drop_erased_batch(entities, ty);
295 });
296 }
297 (_, Some(upper)) if upper <= 16 => {
298 let entities = entities.into_iter().collect::<SmallVec<[_; 16]>>();
299 self.push_fn(move |world| {
300 let _ = world.drop_erased_batch(entities, ty);
301 });
302 }
303 (_, Some(upper)) if upper <= 32 => {
304 let entities = entities.into_iter().collect::<SmallVec<[_; 32]>>();
305 self.push_fn(move |world| {
306 let _ = world.drop_erased_batch(entities, ty);
307 });
308 }
309 _ => {
310 let entities = entities.into_iter().collect::<SmallVec<[_; 64]>>();
311 self.push_fn(move |world| {
312 let _ = world.drop_erased_batch(entities, ty);
313 });
314 }
315 }
316 }
317
318 #[inline(always)]
320 pub fn drop_bundle<B>(&mut self, entity: impl Entity)
321 where
322 B: Bundle,
323 {
324 let id = entity.id();
325 self.push_fn(move |world| {
326 let _ = world.drop_bundle::<B>(id);
327 });
328 }
329
330 #[inline(always)]
332 pub fn insert_relation<R>(&mut self, origin: impl Entity, relation: R, target: impl Entity)
333 where
334 R: Relation + Send,
335 {
336 let origin = origin.id();
337 let target = target.id();
338 self.push_fn(move |world| {
339 let _ = world.insert_relation(origin, relation, target);
340 });
341 }
342
343 #[inline(always)]
345 pub fn drop_relation<R>(&mut self, origin: EntityId, target: EntityId)
346 where
347 R: Relation,
348 {
349 self.push_fn(move |world| {
350 let _ = world.remove_relation::<R>(origin, target);
351 });
352 }
353
354 #[inline(always)]
356 pub fn is_alive(&self, entity: impl Entity) -> bool {
357 entity.is_alive(self.entities)
358 }
359
360 #[inline(always)]
362 pub fn insert_resource<T>(&mut self, resource: T)
363 where
364 T: Send + 'static,
365 {
366 self.push_fn(move |world| {
367 world.insert_resource(resource);
368 });
369 }
370
371 #[inline(always)]
373 pub fn drop_resource<T: 'static>(&mut self) {
374 self.push_fn(move |world| {
375 world.remove_resource::<T>();
376 });
377 }
378
379 #[inline(always)]
382 pub fn closure(&mut self, fun: impl FnOnce(&mut World) + Send + 'static) {
383 self.push_fn(fun);
384 }
385
386 #[inline(always)]
389 pub fn reborrow(&mut self) -> ActionEncoder {
390 ActionEncoder {
391 actions: self.actions,
392 entities: self.entities,
393 }
394 }
395
396 #[inline(always)]
398 fn push_fn(&mut self, fun: impl FnOnce(&mut World) + Send + 'static) {
399 self.actions.push_back(ActionFn::new(fun));
400 }
401}
402
403pub struct SpawnBatch<'a, I> {
405 bundles: I,
406 encoder: ActionEncoder<'a>,
407}
408
409impl<B, I> SpawnBatch<'_, I>
410where
411 I: Iterator<Item = B>,
412 B: Bundle + Send + 'static,
413{
414 #[inline(always)]
416 pub fn spawn_all(self) {
417 self.for_each(|_| {});
418 }
419}
420
421impl<'a, B, I> Iterator for SpawnBatch<'a, I>
422where
423 I: Iterator<Item = B>,
424 B: Bundle + Send + 'static,
425{
426 type Item = EntityId;
427
428 #[inline(always)]
429 fn next(&mut self) -> Option<EntityId> {
430 let bundle = self.bundles.next()?;
431 Some(self.encoder.spawn_external(bundle).id())
432 }
433
434 #[inline(always)]
435 fn nth(&mut self, n: usize) -> Option<EntityId> {
436 let bundle = self.bundles.nth(n)?;
438 Some(self.encoder.spawn_external(bundle).id())
439 }
440
441 #[inline(always)]
442 fn size_hint(&self) -> (usize, Option<usize>) {
443 self.bundles.size_hint()
444 }
445
446 #[inline(always)]
447 fn fold<T, F>(mut self, init: T, mut f: F) -> T
448 where
449 F: FnMut(T, EntityId) -> T,
450 {
451 let additional = iter_reserve_hint(&self.bundles);
452 self.encoder.push_fn(move |world| {
453 world.spawn_reserve::<B>(additional);
454 });
455
456 self.bundles.fold(init, |acc, bundle| {
457 f(acc, self.encoder.spawn_external(bundle).id())
458 })
459 }
460
461 #[inline(always)]
462 fn collect<T>(mut self) -> T
463 where
464 T: FromIterator<EntityId>,
465 {
466 let additional = iter_reserve_hint(&self.bundles);
472 self.encoder.push_fn(move |world| {
473 world.spawn_reserve::<B>(additional);
474 });
475
476 FromIterator::from_iter(self)
477 }
478}
479
480impl<B, I> ExactSizeIterator for SpawnBatch<'_, I>
481where
482 I: ExactSizeIterator<Item = B>,
483 B: Bundle + Send + 'static,
484{
485 #[inline(always)]
486 fn len(&self) -> usize {
487 self.bundles.len()
488 }
489}
490
491impl<'a, B, I> DoubleEndedIterator for SpawnBatch<'a, I>
492where
493 I: DoubleEndedIterator<Item = B>,
494 B: Bundle + Send + 'static,
495{
496 #[inline(always)]
497 fn next_back(&mut self) -> Option<EntityId> {
498 let bundle = self.bundles.next_back()?;
499 Some(self.encoder.spawn_external(bundle).id())
500 }
501
502 #[inline(always)]
503 fn nth_back(&mut self, n: usize) -> Option<EntityId> {
504 let bundle = self.bundles.nth_back(n)?;
506 Some(self.encoder.spawn_external(bundle).id())
507 }
508
509 #[inline(always)]
510 fn rfold<T, F>(mut self, init: T, mut f: F) -> T
511 where
512 Self: Sized,
513 F: FnMut(T, EntityId) -> T,
514 {
515 let additional = iter_reserve_hint(&self.bundles);
516 self.encoder.push_fn(move |world| {
517 world.spawn_reserve::<B>(additional);
518 });
519
520 self.bundles.rfold(init, |acc, bundle| {
521 f(acc, self.encoder.spawn_external(bundle).id())
522 })
523 }
524}
525
526impl<B, I> FusedIterator for SpawnBatch<'_, I>
527where
528 I: FusedIterator<Item = B>,
529 B: Bundle + Send + 'static,
530{
531}
532
533pub struct LocalActionEncoder<'a> {
542 actions: &'a mut VecDeque<LocalActionFn<'static>>,
543 entities: &'a EntitySet,
544}
545
546impl<'a> LocalActionEncoder<'a> {
547 #[inline(always)]
549 pub(crate) fn new(buffer: &'a mut LocalActionBuffer, entities: &'a EntitySet) -> Self {
550 LocalActionEncoder {
551 actions: buffer.actions(),
552 entities,
553 }
554 }
555
556 #[inline(always)]
559 pub fn is_empty(&self) -> bool {
560 self.actions.is_empty()
561 }
562
563 #[inline(always)]
565 pub fn allocate(&self) -> EntityLoc<'_> {
566 self.entities.alloc()
567 }
568
569 #[inline(always)]
571 pub fn spawn_one<T>(&mut self, component: T) -> EntityLoc<'_>
572 where
573 T: Component + 'static,
574 {
575 let entity = self.entities.alloc();
576 self.insert(entity, component);
577 entity
578 }
579
580 #[inline(always)]
582 pub fn spawn<B>(&mut self, bundle: B) -> EntityLoc<'_>
583 where
584 B: DynamicComponentBundle + 'static,
585 {
586 let entity = self.entities.alloc();
587 self.insert_bundle(entity, bundle);
588 entity
589 }
590
591 #[inline(always)]
593 pub fn spawn_external<B>(&mut self, bundle: B) -> EntityLoc<'_>
594 where
595 B: DynamicBundle + 'static,
596 {
597 let entity = self.entities.alloc();
598 self.insert_external_bundle(entity, bundle);
599 entity
600 }
601
602 #[inline(always)]
605 pub fn spawn_batch<I>(&mut self, bundles: I) -> LocalSpawnBatch<I>
606 where
607 I: IntoIterator,
608 I::Item: ComponentBundle + 'static,
609 {
610 self.push_fn(|world| {
611 world.ensure_bundle_registered::<I::Item>();
612 });
613
614 LocalSpawnBatch {
615 bundles,
616 encoder: self.reborrow(),
617 }
618 }
619
620 #[inline(always)]
623 pub fn spawn_external_batch<I>(&mut self, bundles: I) -> LocalSpawnBatch<I>
624 where
625 I: IntoIterator,
626 I::Item: Bundle + 'static,
627 {
628 LocalSpawnBatch {
629 bundles,
630 encoder: self.reborrow(),
631 }
632 }
633
634 #[inline(always)]
636 pub fn despawn(&mut self, entity: impl Entity) {
637 let id = entity.id();
638 self.push_fn(move |world| {
639 let _ = world.despawn(id);
640 })
641 }
642
643 #[inline(always)]
645 pub fn despawn_batch(&mut self, entities: impl IntoIterator<Item = EntityId>) {
646 let entities = entities.into_iter();
647
648 match entities.size_hint() {
649 (_, Some(upper)) if upper <= 8 => {
650 let entities = entities.into_iter().collect::<SmallVec<[_; 8]>>();
651 self.push_fn(move |world| {
652 let _ = world.despawn_batch(entities);
653 });
654 }
655 (_, Some(upper)) if upper <= 16 => {
656 let entities = entities.into_iter().collect::<SmallVec<[_; 16]>>();
657 self.push_fn(move |world| {
658 let _ = world.despawn_batch(entities);
659 });
660 }
661 (_, Some(upper)) if upper <= 32 => {
662 let entities = entities.into_iter().collect::<SmallVec<[_; 32]>>();
663 self.push_fn(move |world| {
664 let _ = world.despawn_batch(entities);
665 });
666 }
667 _ => {
668 let entities = entities.into_iter().collect::<SmallVec<[_; 64]>>();
669 self.push_fn(move |world| {
670 let _ = world.despawn_batch(entities);
671 });
672 }
673 }
674 }
675
676 #[inline(always)]
678 pub fn insert<T>(&mut self, entity: impl Entity, component: T)
679 where
680 T: Component,
681 {
682 let id = entity.id();
683 self.push_fn(move |world| {
684 let _ = world.insert(id, component);
685 });
686 }
687
688 #[inline(always)]
690 pub fn insert_external<T>(&mut self, entity: impl Entity, component: T)
691 where
692 T: 'static,
693 {
694 let id = entity.id();
695 self.push_fn(move |world| {
696 let _ = world.insert_external(id, component);
697 });
698 }
699
700 #[inline(always)]
702 pub fn with<T>(&mut self, entity: impl Entity, f: impl FnOnce() -> T + 'static)
703 where
704 T: Component,
705 {
706 let id = entity.id();
707 self.push_fn(move |world| {
708 let _ = world.with(id, f);
709 });
710 }
711
712 #[inline(always)]
714 pub fn with_external<T>(&mut self, entity: impl Entity, f: impl FnOnce() -> T + 'static)
715 where
716 T: 'static,
717 {
718 let id = entity.id();
719 self.push_fn(move |world| {
720 let _ = world.with_external(id, f);
721 });
722 }
723
724 #[inline(always)]
726 pub(crate) fn _with<F, T>(
727 &mut self,
728 entity: impl Entity,
729 f: impl FnOnce() -> T + 'static,
730 replace: bool,
731 get_or_register: F,
732 ) where
733 F: FnOnce(&mut ComponentRegistry) -> &ComponentInfo + 'static,
734 T: 'static,
735 {
736 let id = entity.id();
737 self.push_fn(move |world| {
738 let _ = world._with(id, f, replace, get_or_register);
739 });
740 }
741
742 #[inline(always)]
744 pub fn insert_bundle<B>(&mut self, entity: impl Entity, bundle: B)
745 where
746 B: DynamicComponentBundle + 'static,
747 {
748 let id = entity.id();
749 self.push_fn(move |world| {
750 let _ = world.insert_bundle(id, bundle);
751 });
752 }
753
754 #[inline(always)]
756 pub fn insert_external_bundle<B>(&mut self, entity: impl Entity, bundle: B)
757 where
758 B: DynamicBundle + 'static,
759 {
760 let id = entity.id();
761 self.push_fn(move |world| {
762 let _ = world.insert_external_bundle(id, bundle);
763 });
764 }
765
766 #[inline(always)]
768 pub fn with_bundle<B>(&mut self, entity: impl Entity, bundle: B)
769 where
770 B: DynamicComponentBundle + 'static,
771 {
772 let id = entity.id();
773 self.push_fn(move |world| {
774 let _ = world.with_bundle(id, bundle);
775 });
776 }
777
778 #[inline(always)]
780 pub fn with_external_bundle<B>(&mut self, entity: impl Entity, bundle: B)
781 where
782 B: DynamicBundle + 'static,
783 {
784 let id = entity.id();
785 self.push_fn(move |world| {
786 let _ = world.with_external_bundle(id, bundle);
787 });
788 }
789
790 #[inline(always)]
792 pub fn drop<T>(&mut self, entity: impl Entity)
793 where
794 T: 'static,
795 {
796 self.drop_erased(entity, type_id::<T>())
797 }
798
799 #[inline(always)]
801 pub fn drop_batch<T>(&mut self, entities: impl IntoIterator<Item = EntityId>)
802 where
803 T: 'static,
804 {
805 self.drop_erased_batch(entities, type_id::<T>())
806 }
807
808 #[inline(always)]
810 pub fn drop_erased(&mut self, entity: impl Entity, ty: TypeId) {
811 let id = entity.id();
812 self.push_fn(move |world| {
813 let _ = world.drop_erased(id, ty);
814 })
815 }
816
817 #[inline(always)]
819 pub fn drop_erased_batch(&mut self, entities: impl IntoIterator<Item = EntityId>, ty: TypeId) {
820 let entities = entities.into_iter();
821
822 match entities.size_hint() {
823 (_, Some(upper)) if upper <= 8 => {
824 let entities = entities.into_iter().collect::<SmallVec<[_; 8]>>();
825 self.push_fn(move |world| {
826 let _ = world.drop_erased_batch(entities, ty);
827 });
828 }
829 (_, Some(upper)) if upper <= 16 => {
830 let entities = entities.into_iter().collect::<SmallVec<[_; 16]>>();
831 self.push_fn(move |world| {
832 let _ = world.drop_erased_batch(entities, ty);
833 });
834 }
835 (_, Some(upper)) if upper <= 32 => {
836 let entities = entities.into_iter().collect::<SmallVec<[_; 32]>>();
837 self.push_fn(move |world| {
838 let _ = world.drop_erased_batch(entities, ty);
839 });
840 }
841 _ => {
842 let entities = entities.into_iter().collect::<SmallVec<[_; 64]>>();
843 self.push_fn(move |world| {
844 let _ = world.drop_erased_batch(entities, ty);
845 });
846 }
847 }
848 }
849
850 #[inline(always)]
852 pub fn drop_bundle<B>(&mut self, entity: impl Entity)
853 where
854 B: Bundle,
855 {
856 let id = entity.id();
857 self.push_fn(move |world| {
858 let _ = world.drop_bundle::<B>(id);
859 });
860 }
861
862 #[inline(always)]
864 pub fn insert_relation<R>(&mut self, origin: impl Entity, relation: R, target: impl Entity)
865 where
866 R: Relation,
867 {
868 let origin = origin.id();
869 let target = target.id();
870 self.push_fn(move |world| {
871 let _ = world.insert_relation(origin, relation, target);
872 });
873 }
874
875 #[inline(always)]
877 pub fn drop_relation<R>(&mut self, origin: EntityId, target: EntityId)
878 where
879 R: Relation,
880 {
881 self.push_fn(move |world| {
882 let _ = world.remove_relation::<R>(origin, target);
883 });
884 }
885
886 #[inline(always)]
888 pub fn is_alive(&self, entity: impl Entity) -> bool {
889 entity.is_alive(self.entities)
890 }
891
892 #[inline(always)]
894 pub fn insert_resource<T>(&mut self, resource: T)
895 where
896 T: 'static,
897 {
898 self.push_fn(move |world| {
899 world.insert_resource(resource);
900 });
901 }
902
903 #[inline(always)]
905 pub fn drop_resource<T: 'static>(&mut self) {
906 self.push_fn(move |world| {
907 world.remove_resource::<T>();
908 });
909 }
910
911 #[inline(always)]
914 pub fn closure(&mut self, fun: impl FnOnce(&mut World) + 'static) {
915 self.push_fn(fun);
916 }
917
918 #[inline(always)]
921 pub fn reborrow(&mut self) -> LocalActionEncoder {
922 LocalActionEncoder {
923 actions: self.actions,
924 entities: self.entities,
925 }
926 }
927
928 #[inline(always)]
930 fn push_fn(&mut self, fun: impl FnOnce(&mut World) + 'static) {
931 self.actions.push_back(LocalActionFn::new(fun));
932 }
933}
934
935pub struct LocalSpawnBatch<'a, I> {
937 bundles: I,
938 encoder: LocalActionEncoder<'a>,
939}
940
941impl<B, I> LocalSpawnBatch<'_, I>
942where
943 I: Iterator<Item = B>,
944 B: Bundle + Send + 'static,
945{
946 #[inline(always)]
948 pub fn spawn_all(self) {
949 self.for_each(|_| {});
950 }
951}
952
953impl<'a, B, I> Iterator for LocalSpawnBatch<'a, I>
954where
955 I: Iterator<Item = B>,
956 B: Bundle + Send + 'static,
957{
958 type Item = EntityId;
959
960 #[inline(always)]
961 fn next(&mut self) -> Option<EntityId> {
962 let bundle = self.bundles.next()?;
963 Some(self.encoder.spawn_external(bundle).id())
964 }
965
966 #[inline(always)]
967 fn nth(&mut self, n: usize) -> Option<EntityId> {
968 let bundle = self.bundles.nth(n)?;
970 Some(self.encoder.spawn_external(bundle).id())
971 }
972
973 #[inline(always)]
974 fn size_hint(&self) -> (usize, Option<usize>) {
975 self.bundles.size_hint()
976 }
977
978 #[inline(always)]
979 fn fold<T, F>(mut self, init: T, mut f: F) -> T
980 where
981 F: FnMut(T, EntityId) -> T,
982 {
983 let additional = iter_reserve_hint(&self.bundles);
984 self.encoder.push_fn(move |world| {
985 world.spawn_reserve::<B>(additional);
986 });
987
988 self.bundles.fold(init, |acc, bundle| {
989 f(acc, self.encoder.spawn_external(bundle).id())
990 })
991 }
992
993 #[inline(always)]
994 fn collect<T>(mut self) -> T
995 where
996 T: FromIterator<EntityId>,
997 {
998 let additional = iter_reserve_hint(&self.bundles);
1004 self.encoder.push_fn(move |world| {
1005 world.spawn_reserve::<B>(additional);
1006 });
1007
1008 FromIterator::from_iter(self)
1009 }
1010}
1011
1012impl<B, I> ExactSizeIterator for LocalSpawnBatch<'_, I>
1013where
1014 I: ExactSizeIterator<Item = B>,
1015 B: Bundle + Send + 'static,
1016{
1017 #[inline(always)]
1018 fn len(&self) -> usize {
1019 self.bundles.len()
1020 }
1021}
1022
1023impl<'a, B, I> DoubleEndedIterator for LocalSpawnBatch<'a, I>
1024where
1025 I: DoubleEndedIterator<Item = B>,
1026 B: Bundle + Send + 'static,
1027{
1028 #[inline(always)]
1029 fn next_back(&mut self) -> Option<EntityId> {
1030 let bundle = self.bundles.next_back()?;
1031 Some(self.encoder.spawn_external(bundle).id())
1032 }
1033
1034 #[inline(always)]
1035 fn nth_back(&mut self, n: usize) -> Option<EntityId> {
1036 let bundle = self.bundles.nth_back(n)?;
1038 Some(self.encoder.spawn_external(bundle).id())
1039 }
1040
1041 #[inline(always)]
1042 fn rfold<T, F>(mut self, init: T, mut f: F) -> T
1043 where
1044 Self: Sized,
1045 F: FnMut(T, EntityId) -> T,
1046 {
1047 let additional = iter_reserve_hint(&self.bundles);
1048 self.encoder.push_fn(move |world| {
1049 world.spawn_reserve::<B>(additional);
1050 });
1051
1052 self.bundles.rfold(init, |acc, bundle| {
1053 f(acc, self.encoder.spawn_external(bundle).id())
1054 })
1055 }
1056}
1057
1058impl<B, I> FusedIterator for LocalSpawnBatch<'_, I>
1059where
1060 I: FusedIterator<Item = B>,
1061 B: Bundle + Send + 'static,
1062{
1063}