1pub use bevy_ecs_macros::Bundle;
6
7use crate::{
8 archetype::{
9 AddBundle, Archetype, ArchetypeId, Archetypes, BundleComponentStatus, ComponentStatus,
10 SpawnBundleStatus,
11 },
12 component::{
13 Component, ComponentId, Components, RequiredComponentConstructor, RequiredComponents,
14 StorageType, Tick,
15 },
16 entity::{Entities, Entity, EntityLocation},
17 observer::Observers,
18 prelude::World,
19 query::DebugCheckedUnwrap,
20 storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
21 world::{unsafe_world_cell::UnsafeWorldCell, ON_ADD, ON_INSERT, ON_REPLACE},
22};
23use bevy_ptr::{ConstNonNull, OwningPtr};
24use bevy_utils::{all_tuples, HashMap, HashSet, TypeIdMap};
25#[cfg(feature = "track_change_detection")]
26use core::panic::Location;
27use core::{any::TypeId, ptr::NonNull};
28
29#[diagnostic::on_unimplemented(
144 message = "`{Self}` is not a `Bundle`",
145 label = "invalid `Bundle`",
146 note = "consider annotating `{Self}` with `#[derive(Component)]` or `#[derive(Bundle)]`"
147)]
148pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static {
149 #[doc(hidden)]
151 fn component_ids(
152 components: &mut Components,
153 storages: &mut Storages,
154 ids: &mut impl FnMut(ComponentId),
155 );
156
157 fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>));
159
160 #[doc(hidden)]
167 unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
168 where
169 F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
171 Self: Sized;
172
173 fn register_required_components(
175 _components: &mut Components,
176 _storages: &mut Storages,
177 _required_components: &mut RequiredComponents,
178 );
179}
180
181pub trait DynamicBundle {
183 #[doc(hidden)]
190 fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>));
191}
192
193unsafe impl<C: Component> Bundle for C {
198 fn component_ids(
199 components: &mut Components,
200 storages: &mut Storages,
201 ids: &mut impl FnMut(ComponentId),
202 ) {
203 ids(components.register_component::<C>(storages));
204 }
205
206 unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
207 where
208 F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
210 Self: Sized,
211 {
212 let ptr = func(ctx);
213 unsafe { ptr.read() }
215 }
216
217 fn register_required_components(
218 components: &mut Components,
219 storages: &mut Storages,
220 required_components: &mut RequiredComponents,
221 ) {
222 let component_id = components.register_component::<C>(storages);
223 <C as Component>::register_required_components(
224 component_id,
225 components,
226 storages,
227 required_components,
228 0,
229 );
230 }
231
232 fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)) {
233 ids(components.get_id(TypeId::of::<C>()));
234 }
235}
236
237impl<C: Component> DynamicBundle for C {
238 #[inline]
239 fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) {
240 OwningPtr::make(self, |ptr| func(C::STORAGE_TYPE, ptr));
241 }
242}
243
244macro_rules! tuple_impl {
245 ($(#[$meta:meta])* $($name: ident),*) => {
246 $(#[$meta])*
247 unsafe impl<$($name: Bundle),*> Bundle for ($($name,)*) {
254 #[allow(unused_variables)]
255 fn component_ids(components: &mut Components, storages: &mut Storages, ids: &mut impl FnMut(ComponentId)){
256 $(<$name as Bundle>::component_ids(components, storages, ids);)*
257 }
258
259 #[allow(unused_variables)]
260 fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)){
261 $(<$name as Bundle>::get_component_ids(components, ids);)*
262 }
263
264 #[allow(unused_variables, unused_mut)]
265 #[allow(clippy::unused_unit)]
266 unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
267 where
268 F: FnMut(&mut T) -> OwningPtr<'_>
269 {
270 #[allow(unused_unsafe)]
271 unsafe { ($(<$name as Bundle>::from_components(ctx, func),)*) }
274 }
275
276 fn register_required_components(
277 _components: &mut Components,
278 _storages: &mut Storages,
279 _required_components: &mut RequiredComponents,
280 ) {
281 $(<$name as Bundle>::register_required_components(_components, _storages, _required_components);)*
282 }
283 }
284
285 $(#[$meta])*
286 impl<$($name: Bundle),*> DynamicBundle for ($($name,)*) {
287 #[allow(unused_variables, unused_mut)]
288 #[inline(always)]
289 fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) {
290 #[allow(non_snake_case)]
291 let ($(mut $name,)*) = self;
292 $(
293 $name.get_components(&mut *func);
294 )*
295 }
296 }
297 }
298}
299
300all_tuples!(
301 #[doc(fake_variadic)]
302 tuple_impl,
303 0,
304 15,
305 B
306);
307
308#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
312pub struct BundleId(usize);
313
314impl BundleId {
315 #[inline]
319 pub fn index(self) -> usize {
320 self.0
321 }
322}
323
324impl SparseSetIndex for BundleId {
325 #[inline]
326 fn sparse_set_index(&self) -> usize {
327 self.index()
328 }
329
330 #[inline]
331 fn get_sparse_set_index(value: usize) -> Self {
332 Self(value)
333 }
334}
335
336#[derive(Clone, Copy, Eq, PartialEq)]
338pub(crate) enum InsertMode {
339 Replace,
341 Keep,
343}
344
345pub struct BundleInfo {
349 id: BundleId,
350 component_ids: Vec<ComponentId>,
359 required_components: Vec<RequiredComponentConstructor>,
360 explicit_components_len: usize,
361}
362
363impl BundleInfo {
364 unsafe fn new(
372 bundle_type_name: &'static str,
373 components: &Components,
374 mut component_ids: Vec<ComponentId>,
375 id: BundleId,
376 ) -> BundleInfo {
377 let mut deduped = component_ids.clone();
378 deduped.sort_unstable();
379 deduped.dedup();
380
381 if deduped.len() != component_ids.len() {
382 let mut seen = HashSet::new();
384 let mut dups = Vec::new();
385 for id in component_ids {
386 if !seen.insert(id) {
387 dups.push(id);
388 }
389 }
390
391 let names = dups
392 .into_iter()
393 .map(|id| {
394 unsafe { components.get_info_unchecked(id).name() }
396 })
397 .collect::<Vec<_>>()
398 .join(", ");
399
400 panic!("Bundle {bundle_type_name} has duplicate components: {names}");
401 }
402
403 let explicit_components_len = component_ids.len();
404 let mut required_components = RequiredComponents::default();
405 for component_id in component_ids.iter().copied() {
406 let info = unsafe { components.get_info_unchecked(component_id) };
408 required_components.merge(info.required_components());
409 }
410 required_components.remove_explicit_components(&component_ids);
411 let required_components = required_components
412 .0
413 .into_iter()
414 .map(|(component_id, v)| {
415 component_ids.push(component_id);
418 v.constructor
419 })
420 .collect();
421
422 BundleInfo {
427 id,
428 component_ids,
429 required_components,
430 explicit_components_len,
431 }
432 }
433
434 #[inline]
436 pub const fn id(&self) -> BundleId {
437 self.id
438 }
439
440 #[inline]
444 pub fn explicit_components(&self) -> &[ComponentId] {
445 &self.component_ids[0..self.explicit_components_len]
446 }
447
448 #[inline]
451 pub fn required_components(&self) -> &[ComponentId] {
452 &self.component_ids[self.explicit_components_len..]
453 }
454
455 #[inline]
459 pub fn contributed_components(&self) -> &[ComponentId] {
460 &self.component_ids
461 }
462
463 #[inline]
466 pub fn iter_explicit_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
467 self.explicit_components().iter().copied()
468 }
469
470 #[inline]
474 pub fn iter_contributed_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
475 self.component_ids.iter().copied()
476 }
477
478 pub fn iter_required_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
481 self.required_components().iter().copied()
482 }
483
484 #[inline]
501 #[allow(clippy::too_many_arguments)]
502 unsafe fn write_components<'a, T: DynamicBundle, S: BundleComponentStatus>(
503 &self,
504 table: &mut Table,
505 sparse_sets: &mut SparseSets,
506 bundle_component_status: &S,
507 required_components: impl Iterator<Item = &'a RequiredComponentConstructor>,
508 entity: Entity,
509 table_row: TableRow,
510 change_tick: Tick,
511 bundle: T,
512 insert_mode: InsertMode,
513 #[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
514 ) {
515 let mut bundle_component = 0;
518 bundle.get_components(&mut |storage_type, component_ptr| {
519 let component_id = *self.component_ids.get_unchecked(bundle_component);
520 match storage_type {
521 StorageType::Table => {
522 let status = unsafe { bundle_component_status.get_status(bundle_component) };
524 let column = table.get_column_mut(component_id).debug_checked_unwrap();
527 match (status, insert_mode) {
528 (ComponentStatus::Added, _) => column.initialize(
529 table_row,
530 component_ptr,
531 change_tick,
532 #[cfg(feature = "track_change_detection")]
533 caller,
534 ),
535 (ComponentStatus::Existing, InsertMode::Replace) => column.replace(
536 table_row,
537 component_ptr,
538 change_tick,
539 #[cfg(feature = "track_change_detection")]
540 caller,
541 ),
542 (ComponentStatus::Existing, InsertMode::Keep) => {
543 if let Some(drop_fn) = table.get_drop_for(component_id) {
544 drop_fn(component_ptr);
545 }
546 }
547 }
548 }
549 StorageType::SparseSet => {
550 let sparse_set =
551 unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
554 sparse_set.insert(
555 entity,
556 component_ptr,
557 change_tick,
558 #[cfg(feature = "track_change_detection")]
559 caller,
560 );
561 }
562 }
563 bundle_component += 1;
564 });
565
566 for required_component in required_components {
567 required_component.initialize(
568 table,
569 sparse_sets,
570 change_tick,
571 table_row,
572 entity,
573 #[cfg(feature = "track_change_detection")]
574 caller,
575 );
576 }
577 }
578
579 #[allow(clippy::too_many_arguments)]
592 pub(crate) unsafe fn initialize_required_component(
593 table: &mut Table,
594 sparse_sets: &mut SparseSets,
595 change_tick: Tick,
596 table_row: TableRow,
597 entity: Entity,
598 component_id: ComponentId,
599 storage_type: StorageType,
600 component_ptr: OwningPtr,
601 #[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
602 ) {
603 {
604 match storage_type {
605 StorageType::Table => {
606 let column =
607 unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
610 column.initialize(
611 table_row,
612 component_ptr,
613 change_tick,
614 #[cfg(feature = "track_change_detection")]
615 caller,
616 );
617 }
618 StorageType::SparseSet => {
619 let sparse_set =
620 unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
623 sparse_set.insert(
624 entity,
625 component_ptr,
626 change_tick,
627 #[cfg(feature = "track_change_detection")]
628 caller,
629 );
630 }
631 }
632 }
633 }
634
635 pub(crate) unsafe fn add_bundle_to_archetype(
641 &self,
642 archetypes: &mut Archetypes,
643 storages: &mut Storages,
644 components: &Components,
645 observers: &Observers,
646 archetype_id: ArchetypeId,
647 ) -> ArchetypeId {
648 if let Some(add_bundle_id) = archetypes[archetype_id].edges().get_add_bundle(self.id) {
649 return add_bundle_id;
650 }
651 let mut new_table_components = Vec::new();
652 let mut new_sparse_set_components = Vec::new();
653 let mut bundle_status = Vec::with_capacity(self.explicit_components_len);
654 let mut added_required_components = Vec::new();
655 let mut added = Vec::new();
656 let mut existing = Vec::new();
657
658 let current_archetype = &mut archetypes[archetype_id];
659 for component_id in self.iter_explicit_components() {
660 if current_archetype.contains(component_id) {
661 bundle_status.push(ComponentStatus::Existing);
662 existing.push(component_id);
663 } else {
664 bundle_status.push(ComponentStatus::Added);
665 added.push(component_id);
666 let component_info = unsafe { components.get_info_unchecked(component_id) };
668 match component_info.storage_type() {
669 StorageType::Table => new_table_components.push(component_id),
670 StorageType::SparseSet => new_sparse_set_components.push(component_id),
671 }
672 }
673 }
674
675 for (index, component_id) in self.iter_required_components().enumerate() {
676 if !current_archetype.contains(component_id) {
677 added_required_components.push(self.required_components[index].clone());
678 added.push(component_id);
679 let component_info = unsafe { components.get_info_unchecked(component_id) };
681 match component_info.storage_type() {
682 StorageType::Table => {
683 new_table_components.push(component_id);
684 }
685 StorageType::SparseSet => {
686 new_sparse_set_components.push(component_id);
687 }
688 }
689 }
690 }
691
692 if new_table_components.is_empty() && new_sparse_set_components.is_empty() {
693 let edges = current_archetype.edges_mut();
694 edges.insert_add_bundle(
696 self.id,
697 archetype_id,
698 bundle_status,
699 added_required_components,
700 added,
701 existing,
702 );
703 archetype_id
704 } else {
705 let table_id;
706 let table_components;
707 let sparse_set_components;
708 {
710 let current_archetype = &archetypes[archetype_id];
711 table_components = if new_table_components.is_empty() {
712 table_id = current_archetype.table_id();
714 current_archetype.table_components().collect()
715 } else {
716 new_table_components.extend(current_archetype.table_components());
717 new_table_components.sort_unstable();
719 table_id = unsafe {
721 storages
722 .tables
723 .get_id_or_insert(&new_table_components, components)
724 };
725
726 new_table_components
727 };
728
729 sparse_set_components = if new_sparse_set_components.is_empty() {
730 current_archetype.sparse_set_components().collect()
731 } else {
732 new_sparse_set_components.extend(current_archetype.sparse_set_components());
733 new_sparse_set_components.sort_unstable();
735 new_sparse_set_components
736 };
737 };
738 let new_archetype_id = archetypes.get_id_or_insert(
740 components,
741 observers,
742 table_id,
743 table_components,
744 sparse_set_components,
745 );
746 archetypes[archetype_id].edges_mut().insert_add_bundle(
748 self.id,
749 new_archetype_id,
750 bundle_status,
751 added_required_components,
752 added,
753 existing,
754 );
755 new_archetype_id
756 }
757 }
758}
759
760pub(crate) struct BundleInserter<'w> {
762 world: UnsafeWorldCell<'w>,
763 bundle_info: ConstNonNull<BundleInfo>,
764 add_bundle: ConstNonNull<AddBundle>,
765 table: NonNull<Table>,
766 archetype: NonNull<Archetype>,
767 result: InsertBundleResult,
768 change_tick: Tick,
769}
770
771pub(crate) enum InsertBundleResult {
772 SameArchetype,
773 NewArchetypeSameTable {
774 new_archetype: NonNull<Archetype>,
775 },
776 NewArchetypeNewTable {
777 new_archetype: NonNull<Archetype>,
778 new_table: NonNull<Table>,
779 },
780}
781
782impl<'w> BundleInserter<'w> {
783 #[inline]
784 pub(crate) fn new<T: Bundle>(
785 world: &'w mut World,
786 archetype_id: ArchetypeId,
787 change_tick: Tick,
788 ) -> Self {
789 let bundle_id = world
790 .bundles
791 .register_info::<T>(&mut world.components, &mut world.storages);
792 unsafe { Self::new_with_id(world, archetype_id, bundle_id, change_tick) }
794 }
795
796 #[inline]
801 pub(crate) unsafe fn new_with_id(
802 world: &'w mut World,
803 archetype_id: ArchetypeId,
804 bundle_id: BundleId,
805 change_tick: Tick,
806 ) -> Self {
807 let bundle_info = world.bundles.get_unchecked(bundle_id);
809 let bundle_id = bundle_info.id();
810 let new_archetype_id = bundle_info.add_bundle_to_archetype(
811 &mut world.archetypes,
812 &mut world.storages,
813 &world.components,
814 &world.observers,
815 archetype_id,
816 );
817 if new_archetype_id == archetype_id {
818 let archetype = &mut world.archetypes[archetype_id];
819 let add_bundle = unsafe {
821 archetype
822 .edges()
823 .get_add_bundle_internal(bundle_id)
824 .debug_checked_unwrap()
825 };
826 let table_id = archetype.table_id();
827 let table = &mut world.storages.tables[table_id];
828 Self {
829 add_bundle: add_bundle.into(),
830 archetype: archetype.into(),
831 bundle_info: bundle_info.into(),
832 table: table.into(),
833 result: InsertBundleResult::SameArchetype,
834 change_tick,
835 world: world.as_unsafe_world_cell(),
836 }
837 } else {
838 let (archetype, new_archetype) =
839 world.archetypes.get_2_mut(archetype_id, new_archetype_id);
840 let add_bundle = unsafe {
842 archetype
843 .edges()
844 .get_add_bundle_internal(bundle_id)
845 .debug_checked_unwrap()
846 };
847 let table_id = archetype.table_id();
848 let new_table_id = new_archetype.table_id();
849 if table_id == new_table_id {
850 let table = &mut world.storages.tables[table_id];
851 Self {
852 add_bundle: add_bundle.into(),
853 archetype: archetype.into(),
854 bundle_info: bundle_info.into(),
855 table: table.into(),
856 result: InsertBundleResult::NewArchetypeSameTable {
857 new_archetype: new_archetype.into(),
858 },
859 change_tick,
860 world: world.as_unsafe_world_cell(),
861 }
862 } else {
863 let (table, new_table) = world.storages.tables.get_2_mut(table_id, new_table_id);
864 Self {
865 add_bundle: add_bundle.into(),
866 archetype: archetype.into(),
867 bundle_info: bundle_info.into(),
868 table: table.into(),
869 result: InsertBundleResult::NewArchetypeNewTable {
870 new_archetype: new_archetype.into(),
871 new_table: new_table.into(),
872 },
873 change_tick,
874 world: world.as_unsafe_world_cell(),
875 }
876 }
877 }
878 }
879
880 #[inline]
884 pub(crate) unsafe fn insert<T: DynamicBundle>(
885 &mut self,
886 entity: Entity,
887 location: EntityLocation,
888 bundle: T,
889 insert_mode: InsertMode,
890 #[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
891 ) -> EntityLocation {
892 let bundle_info = self.bundle_info.as_ref();
893 let add_bundle = self.add_bundle.as_ref();
894 let table = self.table.as_mut();
895 let archetype = self.archetype.as_ref();
896
897 unsafe {
900 let mut deferred_world = self.world.into_deferred();
902
903 if insert_mode == InsertMode::Replace {
904 deferred_world.trigger_on_replace(archetype, entity, add_bundle.iter_existing());
905 if archetype.has_replace_observer() {
906 deferred_world.trigger_observers(
907 ON_REPLACE,
908 entity,
909 add_bundle.iter_existing(),
910 );
911 }
912 }
913 }
914
915 let archetype = self.archetype.as_mut();
918
919 let (new_archetype, new_location) = match &mut self.result {
920 InsertBundleResult::SameArchetype => {
921 let sparse_sets = {
923 let world = self.world.world_mut();
924 &mut world.storages.sparse_sets
925 };
926
927 bundle_info.write_components(
928 table,
929 sparse_sets,
930 add_bundle,
931 add_bundle.required_components.iter(),
932 entity,
933 location.table_row,
934 self.change_tick,
935 bundle,
936 insert_mode,
937 #[cfg(feature = "track_change_detection")]
938 caller,
939 );
940
941 (archetype, location)
942 }
943 InsertBundleResult::NewArchetypeSameTable { new_archetype } => {
944 let new_archetype = new_archetype.as_mut();
945
946 let (sparse_sets, entities) = {
948 let world = self.world.world_mut();
949 (&mut world.storages.sparse_sets, &mut world.entities)
950 };
951
952 let result = archetype.swap_remove(location.archetype_row);
953 if let Some(swapped_entity) = result.swapped_entity {
954 let swapped_location =
955 unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
957 entities.set(
958 swapped_entity.index(),
959 EntityLocation {
960 archetype_id: swapped_location.archetype_id,
961 archetype_row: location.archetype_row,
962 table_id: swapped_location.table_id,
963 table_row: swapped_location.table_row,
964 },
965 );
966 }
967 let new_location = new_archetype.allocate(entity, result.table_row);
968 entities.set(entity.index(), new_location);
969 bundle_info.write_components(
970 table,
971 sparse_sets,
972 add_bundle,
973 add_bundle.required_components.iter(),
974 entity,
975 result.table_row,
976 self.change_tick,
977 bundle,
978 insert_mode,
979 #[cfg(feature = "track_change_detection")]
980 caller,
981 );
982
983 (new_archetype, new_location)
984 }
985 InsertBundleResult::NewArchetypeNewTable {
986 new_archetype,
987 new_table,
988 } => {
989 let new_table = new_table.as_mut();
990 let new_archetype = new_archetype.as_mut();
991
992 let (archetypes_ptr, sparse_sets, entities) = {
994 let world = self.world.world_mut();
995 let archetype_ptr: *mut Archetype = world.archetypes.archetypes.as_mut_ptr();
996 (
997 archetype_ptr,
998 &mut world.storages.sparse_sets,
999 &mut world.entities,
1000 )
1001 };
1002 let result = archetype.swap_remove(location.archetype_row);
1003 if let Some(swapped_entity) = result.swapped_entity {
1004 let swapped_location =
1005 unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1007 entities.set(
1008 swapped_entity.index(),
1009 EntityLocation {
1010 archetype_id: swapped_location.archetype_id,
1011 archetype_row: location.archetype_row,
1012 table_id: swapped_location.table_id,
1013 table_row: swapped_location.table_row,
1014 },
1015 );
1016 }
1017 let move_result = table.move_to_superset_unchecked(result.table_row, new_table);
1020 let new_location = new_archetype.allocate(entity, move_result.new_row);
1021 entities.set(entity.index(), new_location);
1022
1023 if let Some(swapped_entity) = move_result.swapped_entity {
1025 let swapped_location =
1026 unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1028
1029 entities.set(
1030 swapped_entity.index(),
1031 EntityLocation {
1032 archetype_id: swapped_location.archetype_id,
1033 archetype_row: swapped_location.archetype_row,
1034 table_id: swapped_location.table_id,
1035 table_row: result.table_row,
1036 },
1037 );
1038
1039 if archetype.id() == swapped_location.archetype_id {
1040 archetype
1041 .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1042 } else if new_archetype.id() == swapped_location.archetype_id {
1043 new_archetype
1044 .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1045 } else {
1046 (*archetypes_ptr.add(swapped_location.archetype_id.index()))
1048 .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1049 }
1050 }
1051
1052 bundle_info.write_components(
1053 new_table,
1054 sparse_sets,
1055 add_bundle,
1056 add_bundle.required_components.iter(),
1057 entity,
1058 move_result.new_row,
1059 self.change_tick,
1060 bundle,
1061 insert_mode,
1062 #[cfg(feature = "track_change_detection")]
1063 caller,
1064 );
1065
1066 (new_archetype, new_location)
1067 }
1068 };
1069
1070 let new_archetype = &*new_archetype;
1071 let mut deferred_world = unsafe { self.world.into_deferred() };
1073
1074 unsafe {
1077 deferred_world.trigger_on_add(new_archetype, entity, add_bundle.iter_added());
1078 if new_archetype.has_add_observer() {
1079 deferred_world.trigger_observers(ON_ADD, entity, add_bundle.iter_added());
1080 }
1081 match insert_mode {
1082 InsertMode::Replace => {
1083 deferred_world.trigger_on_insert(
1085 new_archetype,
1086 entity,
1087 add_bundle.iter_inserted(),
1088 );
1089 if new_archetype.has_insert_observer() {
1090 deferred_world.trigger_observers(
1091 ON_INSERT,
1092 entity,
1093 add_bundle.iter_inserted(),
1094 );
1095 }
1096 }
1097 InsertMode::Keep => {
1098 deferred_world.trigger_on_insert(
1101 new_archetype,
1102 entity,
1103 add_bundle.iter_added(),
1104 );
1105 if new_archetype.has_insert_observer() {
1106 deferred_world.trigger_observers(
1107 ON_INSERT,
1108 entity,
1109 add_bundle.iter_added(),
1110 );
1111 }
1112 }
1113 }
1114 }
1115
1116 new_location
1117 }
1118
1119 #[inline]
1120 pub(crate) fn entities(&mut self) -> &mut Entities {
1121 unsafe { &mut self.world.world_mut().entities }
1123 }
1124}
1125
1126pub(crate) struct BundleSpawner<'w> {
1128 world: UnsafeWorldCell<'w>,
1129 bundle_info: ConstNonNull<BundleInfo>,
1130 table: NonNull<Table>,
1131 archetype: NonNull<Archetype>,
1132 change_tick: Tick,
1133}
1134
1135impl<'w> BundleSpawner<'w> {
1136 #[inline]
1137 pub fn new<T: Bundle>(world: &'w mut World, change_tick: Tick) -> Self {
1138 let bundle_id = world
1139 .bundles
1140 .register_info::<T>(&mut world.components, &mut world.storages);
1141 unsafe { Self::new_with_id(world, bundle_id, change_tick) }
1143 }
1144
1145 #[inline]
1150 pub(crate) unsafe fn new_with_id(
1151 world: &'w mut World,
1152 bundle_id: BundleId,
1153 change_tick: Tick,
1154 ) -> Self {
1155 let bundle_info = world.bundles.get_unchecked(bundle_id);
1156 let new_archetype_id = bundle_info.add_bundle_to_archetype(
1157 &mut world.archetypes,
1158 &mut world.storages,
1159 &world.components,
1160 &world.observers,
1161 ArchetypeId::EMPTY,
1162 );
1163 let archetype = &mut world.archetypes[new_archetype_id];
1164 let table = &mut world.storages.tables[archetype.table_id()];
1165 Self {
1166 bundle_info: bundle_info.into(),
1167 table: table.into(),
1168 archetype: archetype.into(),
1169 change_tick,
1170 world: world.as_unsafe_world_cell(),
1171 }
1172 }
1173
1174 #[inline]
1175 pub fn reserve_storage(&mut self, additional: usize) {
1176 let (archetype, table) = unsafe { (self.archetype.as_mut(), self.table.as_mut()) };
1178 archetype.reserve(additional);
1179 table.reserve(additional);
1180 }
1181
1182 #[inline]
1185 pub unsafe fn spawn_non_existent<T: DynamicBundle>(
1186 &mut self,
1187 entity: Entity,
1188 bundle: T,
1189 #[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
1190 ) -> EntityLocation {
1191 let bundle_info = self.bundle_info.as_ref();
1193 let location = {
1194 let table = self.table.as_mut();
1195 let archetype = self.archetype.as_mut();
1196
1197 let (sparse_sets, entities) = {
1199 let world = self.world.world_mut();
1200 (&mut world.storages.sparse_sets, &mut world.entities)
1201 };
1202 let table_row = table.allocate(entity);
1203 let location = archetype.allocate(entity, table_row);
1204 bundle_info.write_components(
1205 table,
1206 sparse_sets,
1207 &SpawnBundleStatus,
1208 bundle_info.required_components.iter(),
1209 entity,
1210 table_row,
1211 self.change_tick,
1212 bundle,
1213 InsertMode::Replace,
1214 #[cfg(feature = "track_change_detection")]
1215 caller,
1216 );
1217 entities.set(entity.index(), location);
1218 location
1219 };
1220
1221 let mut deferred_world = unsafe { self.world.into_deferred() };
1223 let archetype = self.archetype.as_ref();
1225 unsafe {
1228 deferred_world.trigger_on_add(
1229 archetype,
1230 entity,
1231 bundle_info.iter_contributed_components(),
1232 );
1233 if archetype.has_add_observer() {
1234 deferred_world.trigger_observers(
1235 ON_ADD,
1236 entity,
1237 bundle_info.iter_contributed_components(),
1238 );
1239 }
1240 deferred_world.trigger_on_insert(
1241 archetype,
1242 entity,
1243 bundle_info.iter_contributed_components(),
1244 );
1245 if archetype.has_insert_observer() {
1246 deferred_world.trigger_observers(
1247 ON_INSERT,
1248 entity,
1249 bundle_info.iter_contributed_components(),
1250 );
1251 }
1252 };
1253
1254 location
1255 }
1256
1257 #[inline]
1260 pub unsafe fn spawn<T: Bundle>(
1261 &mut self,
1262 bundle: T,
1263 #[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
1264 ) -> Entity {
1265 let entity = self.entities().alloc();
1266 unsafe {
1268 self.spawn_non_existent(
1269 entity,
1270 bundle,
1271 #[cfg(feature = "track_change_detection")]
1272 caller,
1273 );
1274 }
1275 entity
1276 }
1277
1278 #[inline]
1279 pub(crate) fn entities(&mut self) -> &mut Entities {
1280 unsafe { &mut self.world.world_mut().entities }
1282 }
1283
1284 #[inline]
1287 pub(crate) unsafe fn flush_commands(&mut self) {
1288 self.world.world_mut().flush();
1290 }
1291}
1292
1293#[derive(Default)]
1295pub struct Bundles {
1296 bundle_infos: Vec<BundleInfo>,
1297 bundle_ids: TypeIdMap<BundleId>,
1299 contributed_bundle_ids: TypeIdMap<BundleId>,
1301 dynamic_bundle_ids: HashMap<Box<[ComponentId]>, BundleId>,
1303 dynamic_bundle_storages: HashMap<BundleId, Vec<StorageType>>,
1304 dynamic_component_bundle_ids: HashMap<ComponentId, BundleId>,
1306 dynamic_component_storages: HashMap<BundleId, StorageType>,
1307}
1308
1309impl Bundles {
1310 #[inline]
1313 pub fn get(&self, bundle_id: BundleId) -> Option<&BundleInfo> {
1314 self.bundle_infos.get(bundle_id.index())
1315 }
1316
1317 #[inline]
1321 pub fn get_id(&self, type_id: TypeId) -> Option<BundleId> {
1322 self.bundle_ids.get(&type_id).cloned()
1323 }
1324
1325 pub(crate) fn register_info<T: Bundle>(
1329 &mut self,
1330 components: &mut Components,
1331 storages: &mut Storages,
1332 ) -> BundleId {
1333 let bundle_infos = &mut self.bundle_infos;
1334 let id = *self.bundle_ids.entry(TypeId::of::<T>()).or_insert_with(|| {
1335 let mut component_ids= Vec::new();
1336 T::component_ids(components, storages, &mut |id| component_ids.push(id));
1337 let id = BundleId(bundle_infos.len());
1338 let bundle_info =
1339 unsafe { BundleInfo::new(core::any::type_name::<T>(), components, component_ids, id) };
1344 bundle_infos.push(bundle_info);
1345 id
1346 });
1347 id
1348 }
1349
1350 pub(crate) fn register_contributed_bundle_info<T: Bundle>(
1354 &mut self,
1355 components: &mut Components,
1356 storages: &mut Storages,
1357 ) -> BundleId {
1358 if let Some(id) = self.contributed_bundle_ids.get(&TypeId::of::<T>()).cloned() {
1359 id
1360 } else {
1361 let explicit_bundle_id = self.register_info::<T>(components, storages);
1362 let id = unsafe {
1364 let (ptr, len) = {
1365 let contributed = self
1367 .get_unchecked(explicit_bundle_id)
1368 .contributed_components();
1369 (contributed.as_ptr(), contributed.len())
1370 };
1371 self.init_dynamic_info(components, core::slice::from_raw_parts(ptr, len))
1374 };
1375 self.contributed_bundle_ids.insert(TypeId::of::<T>(), id);
1376 id
1377 }
1378 }
1379
1380 pub(crate) unsafe fn get_unchecked(&self, id: BundleId) -> &BundleInfo {
1383 self.bundle_infos.get_unchecked(id.0)
1384 }
1385
1386 pub(crate) unsafe fn get_storage_unchecked(&self, id: BundleId) -> StorageType {
1389 *self
1390 .dynamic_component_storages
1391 .get(&id)
1392 .debug_checked_unwrap()
1393 }
1394
1395 pub(crate) unsafe fn get_storages_unchecked(&mut self, id: BundleId) -> &mut Vec<StorageType> {
1398 self.dynamic_bundle_storages
1399 .get_mut(&id)
1400 .debug_checked_unwrap()
1401 }
1402
1403 pub(crate) fn init_dynamic_info(
1410 &mut self,
1411 components: &Components,
1412 component_ids: &[ComponentId],
1413 ) -> BundleId {
1414 let bundle_infos = &mut self.bundle_infos;
1415
1416 let (_, bundle_id) = self
1418 .dynamic_bundle_ids
1419 .raw_entry_mut()
1420 .from_key(component_ids)
1421 .or_insert_with(|| {
1422 let (id, storages) =
1423 initialize_dynamic_bundle(bundle_infos, components, Vec::from(component_ids));
1424 self.dynamic_bundle_storages
1425 .insert_unique_unchecked(id, storages);
1426 (component_ids.into(), id)
1427 });
1428 *bundle_id
1429 }
1430
1431 pub(crate) fn init_component_info(
1437 &mut self,
1438 components: &Components,
1439 component_id: ComponentId,
1440 ) -> BundleId {
1441 let bundle_infos = &mut self.bundle_infos;
1442 let bundle_id = self
1443 .dynamic_component_bundle_ids
1444 .entry(component_id)
1445 .or_insert_with(|| {
1446 let (id, storage_type) =
1447 initialize_dynamic_bundle(bundle_infos, components, vec![component_id]);
1448 self.dynamic_component_storages.insert(id, storage_type[0]);
1449 id
1450 });
1451 *bundle_id
1452 }
1453}
1454
1455fn initialize_dynamic_bundle(
1458 bundle_infos: &mut Vec<BundleInfo>,
1459 components: &Components,
1460 component_ids: Vec<ComponentId>,
1461) -> (BundleId, Vec<StorageType>) {
1462 let storage_types = component_ids.iter().map(|&id| {
1464 components.get_info(id).unwrap_or_else(|| {
1465 panic!(
1466 "init_dynamic_info called with component id {id:?} which doesn't exist in this world"
1467 )
1468 }).storage_type()
1469 }).collect();
1470
1471 let id = BundleId(bundle_infos.len());
1472 let bundle_info =
1473 unsafe { BundleInfo::new("<dynamic bundle>", components, component_ids, id) };
1475 bundle_infos.push(bundle_info);
1476
1477 (id, storage_types)
1478}
1479
1480#[cfg(test)]
1481mod tests {
1482 use crate as bevy_ecs;
1483 use crate::{component::ComponentId, prelude::*, world::DeferredWorld};
1484
1485 #[derive(Component)]
1486 struct A;
1487
1488 #[derive(Component)]
1489 #[component(on_add = a_on_add, on_insert = a_on_insert, on_replace = a_on_replace, on_remove = a_on_remove)]
1490 struct AMacroHooks;
1491
1492 fn a_on_add(mut world: DeferredWorld, _: Entity, _: ComponentId) {
1493 world.resource_mut::<R>().assert_order(0);
1494 }
1495
1496 fn a_on_insert<T1, T2>(mut world: DeferredWorld, _: T1, _: T2) {
1497 world.resource_mut::<R>().assert_order(1);
1498 }
1499
1500 fn a_on_replace<T1, T2>(mut world: DeferredWorld, _: T1, _: T2) {
1501 world.resource_mut::<R>().assert_order(2);
1502 }
1503
1504 fn a_on_remove<T1, T2>(mut world: DeferredWorld, _: T1, _: T2) {
1505 world.resource_mut::<R>().assert_order(3);
1506 }
1507
1508 #[derive(Component)]
1509 struct B;
1510
1511 #[derive(Component)]
1512 struct C;
1513
1514 #[derive(Component)]
1515 struct D;
1516
1517 #[derive(Component, Eq, PartialEq, Debug)]
1518 struct V(&'static str); #[derive(Resource, Default)]
1521 struct R(usize);
1522
1523 impl R {
1524 #[track_caller]
1525 fn assert_order(&mut self, count: usize) {
1526 assert_eq!(count, self.0);
1527 self.0 += 1;
1528 }
1529 }
1530
1531 #[test]
1532 fn component_hook_order_spawn_despawn() {
1533 let mut world = World::new();
1534 world.init_resource::<R>();
1535 world
1536 .register_component_hooks::<A>()
1537 .on_add(|mut world, _, _| world.resource_mut::<R>().assert_order(0))
1538 .on_insert(|mut world, _, _| world.resource_mut::<R>().assert_order(1))
1539 .on_replace(|mut world, _, _| world.resource_mut::<R>().assert_order(2))
1540 .on_remove(|mut world, _, _| world.resource_mut::<R>().assert_order(3));
1541
1542 let entity = world.spawn(A).id();
1543 world.despawn(entity);
1544 assert_eq!(4, world.resource::<R>().0);
1545 }
1546
1547 #[test]
1548 fn component_hook_order_spawn_despawn_with_macro_hooks() {
1549 let mut world = World::new();
1550 world.init_resource::<R>();
1551
1552 let entity = world.spawn(AMacroHooks).id();
1553 world.despawn(entity);
1554
1555 assert_eq!(4, world.resource::<R>().0);
1556 }
1557
1558 #[test]
1559 fn component_hook_order_insert_remove() {
1560 let mut world = World::new();
1561 world.init_resource::<R>();
1562 world
1563 .register_component_hooks::<A>()
1564 .on_add(|mut world, _, _| world.resource_mut::<R>().assert_order(0))
1565 .on_insert(|mut world, _, _| world.resource_mut::<R>().assert_order(1))
1566 .on_replace(|mut world, _, _| world.resource_mut::<R>().assert_order(2))
1567 .on_remove(|mut world, _, _| world.resource_mut::<R>().assert_order(3));
1568
1569 let mut entity = world.spawn_empty();
1570 entity.insert(A);
1571 entity.remove::<A>();
1572 entity.flush();
1573 assert_eq!(4, world.resource::<R>().0);
1574 }
1575
1576 #[test]
1577 fn component_hook_order_replace() {
1578 let mut world = World::new();
1579 world
1580 .register_component_hooks::<A>()
1581 .on_replace(|mut world, _, _| world.resource_mut::<R>().assert_order(0))
1582 .on_insert(|mut world, _, _| {
1583 if let Some(mut r) = world.get_resource_mut::<R>() {
1584 r.assert_order(1);
1585 }
1586 });
1587
1588 let entity = world.spawn(A).id();
1589 world.init_resource::<R>();
1590 let mut entity = world.entity_mut(entity);
1591 entity.insert(A);
1592 entity.insert_if_new(A); entity.flush();
1594 assert_eq!(2, world.resource::<R>().0);
1595 }
1596
1597 #[test]
1598 fn component_hook_order_recursive() {
1599 let mut world = World::new();
1600 world.init_resource::<R>();
1601 world
1602 .register_component_hooks::<A>()
1603 .on_add(|mut world, entity, _| {
1604 world.resource_mut::<R>().assert_order(0);
1605 world.commands().entity(entity).insert(B);
1606 })
1607 .on_remove(|mut world, entity, _| {
1608 world.resource_mut::<R>().assert_order(2);
1609 world.commands().entity(entity).remove::<B>();
1610 });
1611
1612 world
1613 .register_component_hooks::<B>()
1614 .on_add(|mut world, entity, _| {
1615 world.resource_mut::<R>().assert_order(1);
1616 world.commands().entity(entity).remove::<A>();
1617 })
1618 .on_remove(|mut world, _, _| {
1619 world.resource_mut::<R>().assert_order(3);
1620 });
1621
1622 let entity = world.spawn(A).flush();
1623 let entity = world.get_entity(entity).unwrap();
1624 assert!(!entity.contains::<A>());
1625 assert!(!entity.contains::<B>());
1626 assert_eq!(4, world.resource::<R>().0);
1627 }
1628
1629 #[test]
1630 fn component_hook_order_recursive_multiple() {
1631 let mut world = World::new();
1632 world.init_resource::<R>();
1633 world
1634 .register_component_hooks::<A>()
1635 .on_add(|mut world, entity, _| {
1636 world.resource_mut::<R>().assert_order(0);
1637 world.commands().entity(entity).insert(B).insert(C);
1638 });
1639
1640 world
1641 .register_component_hooks::<B>()
1642 .on_add(|mut world, entity, _| {
1643 world.resource_mut::<R>().assert_order(1);
1644 world.commands().entity(entity).insert(D);
1645 });
1646
1647 world
1648 .register_component_hooks::<C>()
1649 .on_add(|mut world, _, _| {
1650 world.resource_mut::<R>().assert_order(3);
1651 });
1652
1653 world
1654 .register_component_hooks::<D>()
1655 .on_add(|mut world, _, _| {
1656 world.resource_mut::<R>().assert_order(2);
1657 });
1658
1659 world.spawn(A).flush();
1660 assert_eq!(4, world.resource::<R>().0);
1661 }
1662
1663 #[test]
1664 fn insert_if_new() {
1665 let mut world = World::new();
1666 let id = world.spawn(V("one")).id();
1667 let mut entity = world.entity_mut(id);
1668 entity.insert_if_new(V("two"));
1669 entity.insert_if_new((A, V("three")));
1670 entity.flush();
1671 let entity = world.entity(id);
1673 assert!(entity.contains::<A>());
1674 assert_eq!(entity.get(), Some(&V("one")));
1675 }
1676}