@@ -17,7 +17,7 @@ use crate::{
17
17
entity:: { AllocAtWithoutReplacement , Entities , Entity , EntityLocation } ,
18
18
event:: { Event , Events } ,
19
19
ptr:: UnsafeCellDeref ,
20
- query:: { QueryState , ReadOnlyWorldQuery , WorldQuery } ,
20
+ query:: { DebugCheckedUnwrap , QueryState , ReadOnlyWorldQuery , WorldQuery } ,
21
21
storage:: { ResourceData , SparseSet , Storages } ,
22
22
system:: Resource ,
23
23
} ;
@@ -767,9 +767,20 @@ impl World {
767
767
/// and those default values will be here instead.
768
768
#[ inline]
769
769
pub fn init_resource < R : Resource + FromWorld > ( & mut self ) {
770
- if !self . contains_resource :: < R > ( ) {
771
- let resource = R :: from_world ( self ) ;
772
- self . insert_resource ( resource) ;
770
+ let component_id = self . components . init_resource :: < R > ( ) ;
771
+ if self
772
+ . storages
773
+ . resources
774
+ . get ( component_id)
775
+ . map_or ( true , |data| !data. is_present ( ) )
776
+ {
777
+ let value = R :: from_world ( self ) ;
778
+ OwningPtr :: make ( value, |ptr| {
779
+ // SAFETY: component_id was just initialized and corresponds to resource of type R.
780
+ unsafe {
781
+ self . insert_resource_by_id ( component_id, ptr) ;
782
+ }
783
+ } ) ;
773
784
}
774
785
}
775
786
@@ -782,7 +793,7 @@ impl World {
782
793
pub fn insert_resource < R : Resource > ( & mut self , value : R ) {
783
794
let component_id = self . components . init_resource :: < R > ( ) ;
784
795
OwningPtr :: make ( value, |ptr| {
785
- // SAFETY: component_id was just initialized and corresponds to resource of type R
796
+ // SAFETY: component_id was just initialized and corresponds to resource of type R.
786
797
unsafe {
787
798
self . insert_resource_by_id ( component_id, ptr) ;
788
799
}
@@ -802,9 +813,20 @@ impl World {
802
813
/// Panics if called from a thread other than the main thread.
803
814
#[ inline]
804
815
pub fn init_non_send_resource < R : ' static + FromWorld > ( & mut self ) {
805
- if !self . contains_non_send :: < R > ( ) {
806
- let resource = R :: from_world ( self ) ;
807
- self . insert_non_send_resource ( resource) ;
816
+ let component_id = self . components . init_non_send :: < R > ( ) ;
817
+ if self
818
+ . storages
819
+ . resources
820
+ . get ( component_id)
821
+ . map_or ( true , |data| !data. is_present ( ) )
822
+ {
823
+ let value = R :: from_world ( self ) ;
824
+ OwningPtr :: make ( value, |ptr| {
825
+ // SAFETY: component_id was just initialized and corresponds to resource of type R.
826
+ unsafe {
827
+ self . insert_non_send_by_id ( component_id, ptr) ;
828
+ }
829
+ } ) ;
808
830
}
809
831
}
810
832
@@ -821,7 +843,7 @@ impl World {
821
843
pub fn insert_non_send_resource < R : ' static > ( & mut self , value : R ) {
822
844
let component_id = self . components . init_non_send :: < R > ( ) ;
823
845
OwningPtr :: make ( value, |ptr| {
824
- // SAFETY: component_id was just initialized and corresponds to resource of type R
846
+ // SAFETY: component_id was just initialized and corresponds to resource of type R.
825
847
unsafe {
826
848
self . insert_non_send_by_id ( component_id, ptr) ;
827
849
}
@@ -959,18 +981,34 @@ impl World {
959
981
unsafe { self . get_resource_unchecked_mut ( ) }
960
982
}
961
983
962
- // PERF: optimize this to avoid redundant lookups
963
984
/// Gets a mutable reference to the resource of type `T` if it exists,
964
985
/// otherwise inserts the resource using the result of calling `func`.
965
986
#[ inline]
966
987
pub fn get_resource_or_insert_with < R : Resource > (
967
988
& mut self ,
968
989
func : impl FnOnce ( ) -> R ,
969
990
) -> Mut < ' _ , R > {
970
- if !self . contains_resource :: < R > ( ) {
971
- self . insert_resource ( func ( ) ) ;
991
+ let change_tick = self . change_tick ( ) ;
992
+ let last_change_tick = self . last_change_tick ( ) ;
993
+
994
+ let component_id = self . components . init_resource :: < R > ( ) ;
995
+ let data = self . initialize_resource_internal ( component_id) ;
996
+ if !data. is_present ( ) {
997
+ OwningPtr :: make ( func ( ) , |ptr| {
998
+ // SAFETY: component_id was just initialized and corresponds to resource of type R.
999
+ unsafe {
1000
+ data. insert ( ptr, change_tick) ;
1001
+ }
1002
+ } ) ;
972
1003
}
973
- self . resource_mut ( )
1004
+
1005
+ // SAFETY: The resource must be present, as we would have inserted it if it was empty.
1006
+ let data = unsafe {
1007
+ data. get_mut ( last_change_tick, change_tick)
1008
+ . debug_checked_unwrap ( )
1009
+ } ;
1010
+ // SAFETY: The underlying type of the resource is `R`.
1011
+ unsafe { data. with_type :: < R > ( ) }
974
1012
}
975
1013
976
1014
/// Gets a mutable reference to the resource of the given type, if it exists
0 commit comments