7
7
8
8
use super :: {
9
9
access_map:: { AccessCount , AccessMap , ReflectAccessId } ,
10
- function:: script_function:: AppScriptFunctionRegistry ,
10
+ function:: {
11
+ namespace:: Namespace ,
12
+ script_function:: { AppScriptFunctionRegistry , CallerContext , DynamicScriptFunction } ,
13
+ } ,
14
+ script_value:: ScriptValue ,
11
15
AppReflectAllocator , ReflectBase , ReflectBaseType , ReflectReference , ScriptTypeRegistration ,
12
16
} ;
13
17
use crate :: { error:: InteropError , with_access_read, with_access_write, with_global_access} ;
@@ -25,6 +29,7 @@ use bevy::{
25
29
} ;
26
30
use std:: {
27
31
any:: TypeId ,
32
+ borrow:: Cow ,
28
33
cell:: RefCell ,
29
34
fmt:: Debug ,
30
35
sync:: { Arc , Weak } ,
@@ -218,6 +223,36 @@ impl WorldCallbackAccess {
218
223
world. exit ( ) ;
219
224
Ok ( ( ) )
220
225
}
226
+
227
+ /// Tries to call a fitting overload of the function with the given name and in the type id's namespace based on the arguments provided.
228
+ /// Currently does this by repeatedly trying each overload until one succeeds or all fail.
229
+ pub fn try_call_overloads (
230
+ & self ,
231
+ type_id : TypeId ,
232
+ name : impl Into < Cow < ' static , str > > ,
233
+ args : Vec < ScriptValue > ,
234
+ context : CallerContext ,
235
+ ) -> Result < ScriptValue , InteropError > {
236
+ let world = self . try_read ( ) ?;
237
+ let registry = world. script_function_registry ( ) ;
238
+ let registry = registry. read ( ) ;
239
+
240
+ let name = name. into ( ) ;
241
+ let overload_iter = match registry. iter_overloads ( Namespace :: OnType ( type_id) , name) {
242
+ Ok ( iter) => iter,
243
+ Err ( name) => return Err ( InteropError :: missing_function ( type_id, name. to_string ( ) ) ) ,
244
+ } ;
245
+
246
+ let mut last_error = None ;
247
+ for overload in overload_iter {
248
+ match overload. call ( args. clone ( ) , world. clone ( ) , context) {
249
+ Ok ( out) => return Ok ( out) ,
250
+ Err ( e) => last_error = Some ( e) ,
251
+ }
252
+ }
253
+
254
+ Err ( last_error. expect ( "invariant, iterator should always return at least one item, and if the call fails it should return an error" ) )
255
+ }
221
256
}
222
257
223
258
pub const DEFAULT_TIMEOUT : Duration = Duration :: from_secs ( 5 ) ;
@@ -459,109 +494,27 @@ impl<'w> WorldAccessGuard<'w> {
459
494
)
460
495
}
461
496
462
- // #[track_caller]
463
- // /// Get access to the given component, this is the only way to access a component/resource safely (in the context of the world access guard)
464
- // pub fn get_component_with_access<T: Component>(
465
- // &self,
466
- // access: &WorldAccess,
467
- // entity: Entity,
468
- // ) -> ScriptResult<Option<&T>> {
469
- // let component_id = match self.0.cell.components().component_id::<T>() {
470
- // Some(id) => id,
471
- // None => return Ok(None),
472
- // };
473
-
474
- // if access.can_read(ReflectAccessId {
475
- // kind: ReflectAccessKind::ComponentOrResource,
476
- // id: component_id.index(),
477
- // }) {
478
- // // Safety: we have the correct access id
479
- // unsafe { Ok(self.0.cell.get_entity(entity).and_then(|e| e.get::<T>())) }
480
- // } else {
481
- // Err(ScriptError::new_reflection_error(
482
- // "Cannot read component, received invalid access".to_string(),
483
- // ))
484
- // }
485
- // }
486
-
487
- // #[track_caller]
488
- // /// Get access to the given component, this is the only way to access a component/resource safely (in the context of the world access guard)
489
- // pub fn get_component_with_access_mut<T: Component>(
490
- // &self,
491
- // access: &mut WorldAccess,
492
- // entity: Entity,
493
- // ) -> ScriptResult<Option<Mut<T>>> {
494
- // let component_id = match self.0.cell.components().component_id::<T>() {
495
- // Some(id) => id,
496
- // None => return Ok(None),
497
- // };
498
-
499
- // if access.can_write(ReflectAccessId {
500
- // kind: ReflectAccessKind::ComponentOrResource,
501
- // id: component_id.index(),
502
- // }) {
503
- // // Safety: we have the correct access id
504
- // unsafe {
505
- // Ok(self
506
- // .0
507
- // .cell
508
- // .get_entity(entity)
509
- // .and_then(|e| e.get_mut::<T>()))
510
- // }
511
- // } else {
512
- // Err(ScriptError::new_reflection_error(
513
- // "Cannot write component, received invalid access".to_string(),
514
- // ))
515
- // }
516
- // }
517
-
518
- // #[track_caller]
519
- // /// Get access to the given resource
520
- // pub fn get_resource_with_access<T: Resource>(
521
- // &self,
522
- // access: &WorldAccess,
523
- // ) -> ScriptResult<Option<&T>> {
524
- // let resource_id = match self.0.cell.components().resource_id::<T>() {
525
- // Some(id) => id,
526
- // None => return Ok(None),
527
- // };
528
-
529
- // if access.can_read(ReflectAccessId {
530
- // kind: ReflectAccessKind::ComponentOrResource,
531
- // id: resource_id.index(),
532
- // }) {
533
- // // Safety: we have the correct access id
534
- // unsafe { Ok(self.0.cell.get_resource::<T>()) }
535
- // } else {
536
- // Err(ScriptError::new_reflection_error(
537
- // "Cannot read resource, received invalid access".to_string(),
538
- // ))
539
- // }
540
- // }
541
-
542
- // #[track_caller]
543
- // /// Get access to the given resource, this is the only way to access a component/resource safely (in the context of the world access guard)
544
- // pub fn get_resource_with_access_mut<T: Resource>(
545
- // &self,
546
- // access: &mut WorldAccess,
547
- // ) -> ScriptResult<Option<Mut<T>>> {
548
- // let resource_id = match self.0.cell.components().resource_id::<T>() {
549
- // Some(id) => id,
550
- // None => return Ok(None),
551
- // };
552
-
553
- // if access.can_write(ReflectAccessId {
554
- // kind: ReflectAccessKind::ComponentOrResource,
555
- // id: resource_id.index(),
556
- // }) {
557
- // // Safety: we have the correct access id
558
- // unsafe { Ok(self.0.cell.get_resource_mut::<T>()) }
559
- // } else {
560
- // Err(ScriptError::new_reflection_error(
561
- // "Cannot write resource, received invalid access".to_string(),
562
- // ))
563
- // }
564
- // }
497
+ /// Try to lookup a function with the given name on the given type id's namespaces.
498
+ ///
499
+ /// Returns the function if found, otherwise returns the name of the function that was not found.
500
+ pub fn lookup_function (
501
+ & self ,
502
+ type_ids : impl IntoIterator < Item = TypeId > ,
503
+ name : impl Into < Cow < ' static , str > > ,
504
+ ) -> Result < DynamicScriptFunction , Cow < ' static , str > > {
505
+ let registry = self . script_function_registry ( ) ;
506
+ let registry = registry. read ( ) ;
507
+
508
+ let mut name = name. into ( ) ;
509
+ for type_id in type_ids {
510
+ name = match registry. get_function ( Namespace :: OnType ( type_id) , name) {
511
+ Ok ( func) => return Ok ( func. clone ( ) ) ,
512
+ Err ( name) => name,
513
+ } ;
514
+ }
515
+
516
+ Err ( name)
517
+ }
565
518
566
519
/// checks if a given entity exists and is valid
567
520
pub fn is_valid_entity ( & self , entity : Entity ) -> bool {
@@ -926,8 +879,15 @@ pub trait WorldContainer {
926
879
self . try_get_world ( ) . expect ( "World not set, or expired" )
927
880
}
928
881
882
+ fn get_callback_world ( & self ) -> WorldCallbackAccess {
883
+ self . try_get_callback_world ( )
884
+ . expect ( "World not set, or expired" )
885
+ }
886
+
929
887
/// Tries to get the world
930
888
fn try_get_world ( & self ) -> Result < Arc < WorldAccessGuard < ' static > > , Self :: Error > ;
889
+
890
+ fn try_get_callback_world ( & self ) -> Result < WorldCallbackAccess , Self :: Error > ;
931
891
}
932
892
933
893
/// A world container that stores the world in a thread local
@@ -955,6 +915,16 @@ impl WorldContainer for ThreadWorldContainer {
955
915
. ok_or_else ( InteropError :: missing_world)
956
916
} ) ?
957
917
}
918
+
919
+ fn try_get_callback_world ( & self ) -> Result < WorldCallbackAccess , Self :: Error > {
920
+ WORLD_CALLBACK_ACCESS . with ( |w| {
921
+ w. borrow ( )
922
+ . as_ref ( )
923
+ . cloned ( )
924
+ // .map(|w| w.try_read())
925
+ . ok_or_else ( InteropError :: missing_world)
926
+ } )
927
+ }
958
928
}
959
929
960
930
// #[cfg(test)]
0 commit comments