@@ -6,8 +6,8 @@ pub use bevy_ecs_macros::Bundle;
6
6
7
7
use crate :: {
8
8
archetype:: {
9
- Archetype , ArchetypeAfterBundleInsert , ArchetypeId , Archetypes , BundleComponentStatus ,
10
- ComponentStatus , SpawnBundleStatus ,
9
+ Archetype , ArchetypeAfterBundleInsert , ArchetypeCreated , ArchetypeId , Archetypes ,
10
+ BundleComponentStatus , ComponentStatus , SpawnBundleStatus ,
11
11
} ,
12
12
change_detection:: MaybeLocation ,
13
13
component:: {
@@ -732,7 +732,7 @@ impl BundleInfo {
732
732
}
733
733
}
734
734
735
- /// Inserts a bundle into the given archetype and returns the resulting archetype.
735
+ /// Inserts a bundle into the given archetype and returns the resulting archetype and whether a new archetype was created .
736
736
/// This could be the same [`ArchetypeId`], in the event that inserting the given bundle
737
737
/// does not result in an [`Archetype`] change.
738
738
///
@@ -747,12 +747,12 @@ impl BundleInfo {
747
747
components : & Components ,
748
748
observers : & Observers ,
749
749
archetype_id : ArchetypeId ,
750
- ) -> ArchetypeId {
750
+ ) -> ( ArchetypeId , bool ) {
751
751
if let Some ( archetype_after_insert_id) = archetypes[ archetype_id]
752
752
. edges ( )
753
753
. get_archetype_after_bundle_insert ( self . id )
754
754
{
755
- return archetype_after_insert_id;
755
+ return ( archetype_after_insert_id, false ) ;
756
756
}
757
757
let mut new_table_components = Vec :: new ( ) ;
758
758
let mut new_sparse_set_components = Vec :: new ( ) ;
@@ -806,7 +806,7 @@ impl BundleInfo {
806
806
added,
807
807
existing,
808
808
) ;
809
- archetype_id
809
+ ( archetype_id, false )
810
810
} else {
811
811
let table_id;
812
812
let table_components;
@@ -842,13 +842,14 @@ impl BundleInfo {
842
842
} ;
843
843
} ;
844
844
// SAFETY: ids in self must be valid
845
- let new_archetype_id = archetypes. get_id_or_insert (
845
+ let ( new_archetype_id, is_new_created ) = archetypes. get_id_or_insert (
846
846
components,
847
847
observers,
848
848
table_id,
849
849
table_components,
850
850
sparse_set_components,
851
851
) ;
852
+
852
853
// Add an edge from the old archetype to the new archetype.
853
854
archetypes[ archetype_id]
854
855
. edges_mut ( )
@@ -860,11 +861,11 @@ impl BundleInfo {
860
861
added,
861
862
existing,
862
863
) ;
863
- new_archetype_id
864
+ ( new_archetype_id, is_new_created )
864
865
}
865
866
}
866
867
867
- /// Removes a bundle from the given archetype and returns the resulting archetype
868
+ /// Removes a bundle from the given archetype and returns the resulting archetype and whether a new archetype was created.
868
869
/// (or `None` if the removal was invalid).
869
870
/// This could be the same [`ArchetypeId`], in the event that removing the given bundle
870
871
/// does not result in an [`Archetype`] change.
@@ -887,7 +888,7 @@ impl BundleInfo {
887
888
observers : & Observers ,
888
889
archetype_id : ArchetypeId ,
889
890
intersection : bool ,
890
- ) -> Option < ArchetypeId > {
891
+ ) -> ( Option < ArchetypeId > , bool ) {
891
892
// Check the archetype graph to see if the bundle has been
892
893
// removed from this archetype in the past.
893
894
let archetype_after_remove_result = {
@@ -898,9 +899,9 @@ impl BundleInfo {
898
899
edges. get_archetype_after_bundle_take ( self . id ( ) )
899
900
}
900
901
} ;
901
- let result = if let Some ( result) = archetype_after_remove_result {
902
+ let ( result, is_new_created ) = if let Some ( result) = archetype_after_remove_result {
902
903
// This bundle removal result is cached. Just return that!
903
- result
904
+ ( result, false )
904
905
} else {
905
906
let mut next_table_components;
906
907
let mut next_sparse_set_components;
@@ -925,7 +926,7 @@ impl BundleInfo {
925
926
current_archetype
926
927
. edges_mut ( )
927
928
. cache_archetype_after_bundle_take ( self . id ( ) , None ) ;
928
- return None ;
929
+ return ( None , false ) ;
929
930
}
930
931
}
931
932
@@ -953,14 +954,14 @@ impl BundleInfo {
953
954
} ;
954
955
}
955
956
956
- let new_archetype_id = archetypes. get_id_or_insert (
957
+ let ( new_archetype_id, is_new_created ) = archetypes. get_id_or_insert (
957
958
components,
958
959
observers,
959
960
next_table_id,
960
961
next_table_components,
961
962
next_sparse_set_components,
962
963
) ;
963
- Some ( new_archetype_id)
964
+ ( Some ( new_archetype_id) , is_new_created )
964
965
} ;
965
966
let current_archetype = & mut archetypes[ archetype_id] ;
966
967
// Cache the result in an edge.
@@ -973,7 +974,7 @@ impl BundleInfo {
973
974
. edges_mut ( )
974
975
. cache_archetype_after_bundle_take ( self . id ( ) , result) ;
975
976
}
976
- result
977
+ ( result, is_new_created )
977
978
}
978
979
}
979
980
@@ -1034,15 +1035,21 @@ impl<'w> BundleInserter<'w> {
1034
1035
change_tick : Tick ,
1035
1036
) -> Self {
1036
1037
// SAFETY: We will not make any accesses to the command queue, component or resource data of this world
1037
- let bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1038
+ let mut bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1038
1039
let bundle_id = bundle_info. id ( ) ;
1039
- let new_archetype_id = bundle_info. insert_bundle_into_archetype (
1040
+ let ( new_archetype_id, is_new_created ) = bundle_info. insert_bundle_into_archetype (
1040
1041
& mut world. archetypes ,
1041
1042
& mut world. storages ,
1042
1043
& world. components ,
1043
1044
& world. observers ,
1044
1045
archetype_id,
1045
1046
) ;
1047
+
1048
+ if is_new_created {
1049
+ world. trigger ( ArchetypeCreated ( new_archetype_id) ) ;
1050
+ bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1051
+ }
1052
+
1046
1053
if new_archetype_id == archetype_id {
1047
1054
let archetype = & mut world. archetypes [ archetype_id] ;
1048
1055
// SAFETY: The edge is assured to be initialized when we called insert_bundle_into_archetype
@@ -1419,21 +1426,29 @@ impl<'w> BundleRemover<'w> {
1419
1426
bundle_id : BundleId ,
1420
1427
require_all : bool ,
1421
1428
) -> Option < Self > {
1422
- let bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1429
+ let mut bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1423
1430
// SAFETY: Caller ensures archetype and bundle ids are correct.
1424
- let new_archetype_id = unsafe {
1431
+ let ( new_archetype_id, is_new_created ) = unsafe {
1425
1432
bundle_info. remove_bundle_from_archetype (
1426
1433
& mut world. archetypes ,
1427
1434
& mut world. storages ,
1428
1435
& world. components ,
1429
1436
& world. observers ,
1430
1437
archetype_id,
1431
1438
!require_all,
1432
- ) ?
1439
+ )
1433
1440
} ;
1441
+ let new_archetype_id = new_archetype_id?;
1442
+
1434
1443
if new_archetype_id == archetype_id {
1435
1444
return None ;
1436
1445
}
1446
+
1447
+ if is_new_created {
1448
+ world. trigger ( ArchetypeCreated ( new_archetype_id) ) ;
1449
+ bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1450
+ }
1451
+
1437
1452
let ( old_archetype, new_archetype) =
1438
1453
world. archetypes . get_2_mut ( archetype_id, new_archetype_id) ;
1439
1454
@@ -1674,14 +1689,20 @@ impl<'w> BundleSpawner<'w> {
1674
1689
bundle_id : BundleId ,
1675
1690
change_tick : Tick ,
1676
1691
) -> Self {
1677
- let bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1678
- let new_archetype_id = bundle_info. insert_bundle_into_archetype (
1692
+ let mut bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1693
+ let ( new_archetype_id, is_new_created ) = bundle_info. insert_bundle_into_archetype (
1679
1694
& mut world. archetypes ,
1680
1695
& mut world. storages ,
1681
1696
& world. components ,
1682
1697
& world. observers ,
1683
1698
ArchetypeId :: EMPTY ,
1684
1699
) ;
1700
+
1701
+ if is_new_created {
1702
+ world. trigger ( ArchetypeCreated ( new_archetype_id) ) ;
1703
+ bundle_info = world. bundles . get_unchecked ( bundle_id) ;
1704
+ }
1705
+
1685
1706
let archetype = & mut world. archetypes [ new_archetype_id] ;
1686
1707
let table = & mut world. storages . tables [ archetype. table_id ( ) ] ;
1687
1708
Self {
@@ -2043,7 +2064,9 @@ fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
2043
2064
2044
2065
#[ cfg( test) ]
2045
2066
mod tests {
2046
- use crate :: { component:: HookContext , prelude:: * , world:: DeferredWorld } ;
2067
+ use crate :: {
2068
+ archetype:: ArchetypeCreated , component:: HookContext , prelude:: * , world:: DeferredWorld ,
2069
+ } ;
2047
2070
use alloc:: vec;
2048
2071
2049
2072
#[ derive( Component ) ]
@@ -2280,4 +2303,23 @@ mod tests {
2280
2303
2281
2304
assert_eq ! ( a, vec![ 1 ] ) ;
2282
2305
}
2306
+
2307
+ #[ test]
2308
+ fn new_archetype_creadted ( ) {
2309
+ let mut world = World :: new ( ) ;
2310
+ #[ derive( Resource , Default ) ]
2311
+ struct Count ( u32 ) ;
2312
+ world. init_resource :: < Count > ( ) ;
2313
+ world. add_observer ( |_t : Trigger < ArchetypeCreated > , mut count : ResMut < Count > | {
2314
+ count. 0 += 1 ;
2315
+ } ) ;
2316
+
2317
+ let mut e = world. spawn ( ( A , B ) ) ;
2318
+ e. insert ( C ) ;
2319
+ e. remove :: < A > ( ) ;
2320
+ e. insert ( A ) ;
2321
+ e. insert ( A ) ;
2322
+
2323
+ assert_eq ! ( world. resource:: <Count >( ) . 0 , 3 ) ;
2324
+ }
2283
2325
}
0 commit comments