@@ -13,7 +13,7 @@ use std::{
1313use crate :: {
1414 query:: Query ,
1515 scheduler:: { Scheduler , SysId } ,
16- sparse_set:: { RemoveType , SparseSets } ,
16+ sparse_set:: SparseSets ,
1717} ;
1818
1919/// An opaque id for an entity.
@@ -56,7 +56,13 @@ impl Default for EntityCounter {
5656pub struct World {
5757 entities : EntityCounter ,
5858 #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
59- dead_entities : RefCell < BTreeMap < Entity , ( & ' static Location < ' static > , String ) > > ,
59+ dead_entity_locations : RefCell < BTreeMap < Entity , & ' static Location < ' static > > > ,
60+ #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
61+ dead_entity_components : RefCell < BTreeMap < Entity , String > > ,
62+ /// Entities that are being despawned.
63+ /// As we cannot mutate the sparse sets to remove all components while queries are running, we instead do
64+ /// so whenever a system finishes
65+ despawning : RefCell < Vec < Entity > > ,
6066 pub ( crate ) sparse_sets : SparseSets ,
6167 scheduler : Scheduler < ' static , ( ) > ,
6268}
@@ -65,7 +71,8 @@ impl World {
6571 #[ track_caller]
6672 fn insert < C : Any > ( & self , entity : Entity , component : C ) {
6773 #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
68- if let Some ( ( loc, components) ) = self . dead_entities . borrow ( ) . get ( & entity) {
74+ if let Some ( components) = self . dead_entity_components . borrow ( ) . get ( & entity) {
75+ let loc = self . dead_entity_locations . borrow ( ) [ & entity] ;
6976 panic ! (
7077 "Attaching `{}` to despawned entity (despawned at {loc}).Components at despawn time: {components}" ,
7178 type_name:: <C >( ) ,
@@ -94,11 +101,29 @@ impl World {
94101 /// Destroy an entity and all its components. Future attempts to use this entity in any way will panic.
95102 #[ track_caller]
96103 pub fn despawn ( & self , entity : Entity ) {
97- let _detach_info = self . detach_all ( entity) ;
104+ self . despawning . borrow_mut ( ) . push ( entity) ;
98105 #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
99- self . dead_entities
106+ self . dead_entity_locations
100107 . borrow_mut ( )
101- . insert ( entity, ( Location :: caller ( ) , _detach_info) ) ;
108+ . insert ( entity, Location :: caller ( ) ) ;
109+ }
110+
111+ /// Ensure all despawned entities actually got removed
112+ #[ track_caller]
113+ pub fn flush_despawned ( & self ) {
114+ for entity in self . despawning . borrow_mut ( ) . drain ( ..) {
115+ #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
116+ let components = self . debug_components ( entity) ;
117+ self . detach_all ( entity) ;
118+ #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
119+ self . dead_entity_components
120+ . borrow_mut ( )
121+ . insert ( entity, components) ;
122+ }
123+ }
124+
125+ pub ( crate ) fn is_despawning ( & self , entity : Entity ) -> bool {
126+ self . despawning . borrow ( ) . contains ( & entity)
102127 }
103128
104129 /// Attach multiple components to an entity at once.
@@ -111,7 +136,8 @@ impl World {
111136 #[ track_caller]
112137 pub fn detach < C : ' static > ( & self , entity : Entity ) -> Option < C > {
113138 #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
114- if let Some ( ( loc, components) ) = self . dead_entities . borrow ( ) . get ( & entity) {
139+ if let Some ( components) = self . dead_entity_components . borrow ( ) . get ( & entity) {
140+ let loc = self . dead_entity_locations . borrow ( ) [ & entity] ;
115141 panic ! (
116142 "Detaching `{}` from despawned entity (despawned at {loc})\n Components at despawn time: {components}" ,
117143 type_name:: <C >( ) ,
@@ -124,16 +150,24 @@ impl World {
124150 /// Detach all components from an entity and drop them.
125151 /// If you want to extract specific components, call [Self::detach] first.
126152 #[ track_caller]
127- pub fn detach_all ( & self , entity : Entity ) -> RemoveType {
153+ pub fn detach_all ( & self , entity : Entity ) {
128154 #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
129- if let Some ( ( loc, components) ) = self . dead_entities . borrow ( ) . get ( & entity) {
155+ if let Some ( components) = self . dead_entity_components . borrow ( ) . get ( & entity) {
156+ let loc = self . dead_entity_locations . borrow ( ) [ & entity] ;
130157 panic ! (
131158 "Detaching all components from despawned entity (despawned at {loc})\n Components at despawn time: {components}"
132159 ) ;
133160 }
134161 self . sparse_sets . remove ( entity)
135162 }
136163
164+ /// Detach all components from an entity and drop them.
165+ /// If you want to extract specific components, call [Self::detach] first.
166+ #[ track_caller]
167+ pub fn debug_components ( & self , entity : Entity ) -> String {
168+ self . sparse_sets . debug ( entity)
169+ }
170+
137171 /// Detach all components of a specific type from all entities and drop them.
138172 ///
139173 /// This method removes all components of type `C` from every entity in the world.
@@ -169,7 +203,8 @@ impl World {
169203 #[ track_caller]
170204 pub fn get < C : ' static > ( & self , entity : Entity ) -> Option < Ref < C > > {
171205 #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
172- if let Some ( ( loc, components) ) = self . dead_entities . borrow ( ) . get ( & entity) {
206+ if let Some ( components) = self . dead_entity_components . borrow ( ) . get ( & entity) {
207+ let loc = self . dead_entity_locations . borrow ( ) [ & entity] ;
173208 panic ! (
174209 "Getting `{}` from despawned entity (despawned at {loc})\n Components at despawn time: {components}" ,
175210 type_name:: <C >( ) ,
@@ -187,7 +222,8 @@ impl World {
187222 #[ track_caller]
188223 pub fn get_mut < C : ' static > ( & self , entity : Entity ) -> Option < RefMut < C > > {
189224 #[ cfg( any( debug_assertions, feature = "track_dead_entities" ) ) ]
190- if let Some ( ( loc, components) ) = self . dead_entities . borrow ( ) . get ( & entity) {
225+ if let Some ( components) = self . dead_entity_components . borrow ( ) . get ( & entity) {
226+ let loc = self . dead_entity_locations . borrow ( ) [ & entity] ;
191227 panic ! (
192228 "Getting `{}` from despawned entity (despawned at {loc})\n Components at despawn time: {components}" ,
193229 type_name:: <C >( ) ,
0 commit comments