@@ -24,6 +24,7 @@ use bevy::{
2424} ;
2525use std:: {
2626 any:: TypeId ,
27+ cell:: RefCell ,
2728 fmt:: Debug ,
2829 sync:: { Arc , Weak } ,
2930 time:: Duration ,
@@ -946,6 +947,51 @@ impl WorldAccessGuard<'_> {
946947 }
947948}
948949
950+ /// Utility type for accessing the world in a callback
951+ pub trait WorldContainer {
952+ type Error : Debug ;
953+ /// Sets the world to the given value
954+ fn set_world ( & mut self , world : WorldCallbackAccess ) -> Result < ( ) , Self :: Error > ;
955+
956+ /// Gets the world, use [`WorldContainer::try_get_world`] if you want to handle errors with retrieving the world
957+ /// # Panics
958+ /// - if the world has not been set
959+ /// - if the world has been dropped
960+ fn get_world ( & self ) -> WorldGuard < ' static > {
961+ self . try_get_world ( ) . expect ( "World not set, or expired" )
962+ }
963+
964+ /// Tries to get the world
965+ fn try_get_world ( & self ) -> Result < Arc < WorldAccessGuard < ' static > > , Self :: Error > ;
966+ }
967+
968+ /// A world container that stores the world in a thread local
969+ pub struct ThreadWorldContainer ;
970+
971+ thread_local ! {
972+ static WORLD_CALLBACK_ACCESS : RefCell <Option <WorldCallbackAccess >> = const { RefCell :: new( None ) } ;
973+ }
974+
975+ impl WorldContainer for ThreadWorldContainer {
976+ type Error = InteropError ;
977+
978+ fn set_world ( & mut self , world : WorldCallbackAccess ) -> Result < ( ) , Self :: Error > {
979+ WORLD_CALLBACK_ACCESS . with ( |w| {
980+ w. replace ( Some ( world) ) ;
981+ } ) ;
982+ Ok ( ( ) )
983+ }
984+
985+ fn try_get_world ( & self ) -> Result < Arc < WorldAccessGuard < ' static > > , Self :: Error > {
986+ WORLD_CALLBACK_ACCESS . with ( |w| {
987+ w. borrow ( )
988+ . as_ref ( )
989+ . map ( |w| w. try_read ( ) )
990+ . ok_or_else ( InteropError :: missing_world)
991+ } ) ?
992+ }
993+ }
994+
949995// #[cfg(test)]
950996// mod test {
951997// use crate::bindings::ScriptTypeRegistration;
0 commit comments