@@ -30,6 +30,14 @@ pub trait ScriptFunction<'env, Marker> {
3030 fn into_dynamic_script_function ( self ) -> DynamicScriptFunction ;
3131}
3232
33+ #[ diagnostic:: on_unimplemented(
34+ message = "Only functions with all arguments impplementing FromScript and return values supporting IntoScript are supported. Registering functions also requires they implement GetInnerTypeDependencies" ,
35+ note = "If you're trying to return a non-primitive type, you might need to use Val<T> Ref<T> or Mut<T> wrappers"
36+ ) ]
37+ pub trait ScriptFunctionMut < ' env , Marker > {
38+ fn into_dynamic_script_function_mut ( self ) -> DynamicScriptFunctionMut ;
39+ }
40+
3341/// Functionally identical to [`GetTypeRegistration`] but without the 'static bound
3442pub trait GetInnerTypeDependencies {
3543 fn register_type_dependencies ( registry : & mut TypeRegistry ) ;
@@ -39,8 +47,8 @@ pub trait GetInnerTypeDependencies {
3947macro_rules! no_type_dependencies {
4048 ( $( $path: path) ,* ) => {
4149 $(
42- impl GetInnerTypeDependencies for $path {
43- fn register_type_dependencies( _registry: & mut TypeRegistry ) { }
50+ impl $crate :: bindings :: function :: script_function :: GetInnerTypeDependencies for $path {
51+ fn register_type_dependencies( _registry: & mut bevy :: reflect :: TypeRegistry ) { }
4452 }
4553 ) *
4654 } ;
@@ -115,7 +123,8 @@ pub struct CallerContext {
115123}
116124
117125/// The Script Function equivalent for dynamic functions. Currently unused
118- #[ derive( Clone ) ]
126+ #[ derive( Clone , Reflect ) ]
127+ #[ reflect( opaque) ]
119128pub struct DynamicScriptFunction {
120129 name : Cow < ' static , str > ,
121130 // TODO: info about the function, this is hard right now because of non 'static lifetimes in wrappers, we can't use TypePath etc
@@ -126,6 +135,34 @@ pub struct DynamicScriptFunction {
126135 + ' static ,
127136 > ,
128137}
138+
139+ impl PartialEq for DynamicScriptFunction {
140+ fn eq ( & self , other : & Self ) -> bool {
141+ self . name == other. name
142+ }
143+ }
144+
145+ #[ derive( Clone , Reflect ) ]
146+ #[ reflect( opaque) ]
147+ pub struct DynamicScriptFunctionMut {
148+ name : Cow < ' static , str > ,
149+ func : Arc <
150+ RwLock <
151+ // I'd rather consume an option or something instead of having the RWLock but I just wanna get this release out
152+ dyn FnMut ( CallerContext , WorldCallbackAccess , Vec < ScriptValue > ) -> ScriptValue
153+ + Send
154+ + Sync
155+ + ' static ,
156+ > ,
157+ > ,
158+ }
159+
160+ impl PartialEq for DynamicScriptFunctionMut {
161+ fn eq ( & self , other : & Self ) -> bool {
162+ self . name == other. name
163+ }
164+ }
165+
129166impl DynamicScriptFunction {
130167 pub fn call (
131168 & self ,
@@ -148,9 +185,72 @@ impl DynamicScriptFunction {
148185 }
149186}
150187
188+ impl DynamicScriptFunctionMut {
189+ pub fn call (
190+ & mut self ,
191+ context : CallerContext ,
192+ world : WorldCallbackAccess ,
193+ args : Vec < ScriptValue > ,
194+ ) -> ScriptValue {
195+ let mut write = self . func . write ( ) ;
196+ write ( context, world, args)
197+ }
198+
199+ pub fn name ( & self ) -> & Cow < ' static , str > {
200+ & self . name
201+ }
202+
203+ pub fn with_name < N : Into < Cow < ' static , str > > > ( self , name : N ) -> Self {
204+ Self {
205+ name : name. into ( ) ,
206+ func : self . func ,
207+ }
208+ }
209+ }
210+
151211impl std:: fmt:: Debug for DynamicScriptFunction {
152212 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
153- f. debug_struct ( "DynamicScriptFunction" ) . finish ( )
213+ f. debug_struct ( "DynamicScriptFunction" )
214+ . field ( "name" , self . name ( ) )
215+ . finish ( )
216+ }
217+ }
218+
219+ impl std:: fmt:: Debug for DynamicScriptFunctionMut {
220+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
221+ f. debug_struct ( "DynamicScriptFunctionMut" )
222+ . field ( "name" , self . name ( ) )
223+ . finish ( )
224+ }
225+ }
226+
227+ impl < F > From < F > for DynamicScriptFunction
228+ where
229+ F : Fn ( CallerContext , WorldCallbackAccess , Vec < ScriptValue > ) -> ScriptValue
230+ + Send
231+ + Sync
232+ + ' static ,
233+ {
234+ fn from ( fn_ : F ) -> Self {
235+ DynamicScriptFunction {
236+ name : std:: any:: type_name :: < F > ( ) . into ( ) ,
237+ func : Arc :: new ( fn_) ,
238+ }
239+ }
240+ }
241+
242+ impl < F > From < F > for DynamicScriptFunctionMut
243+ where
244+ F : FnMut ( CallerContext , WorldCallbackAccess , Vec < ScriptValue > ) -> ScriptValue
245+ + Send
246+ + Sync
247+ + ' static ,
248+ {
249+ fn from ( fn_ : F ) -> Self {
250+ DynamicScriptFunctionMut {
251+ name : std:: any:: type_name :: < F > ( ) . into ( ) ,
252+ func : Arc :: new ( RwLock :: new ( fn_) ) ,
253+ }
154254 }
155255}
156256
@@ -261,39 +361,59 @@ macro_rules! count {
261361macro_rules! impl_script_function {
262362
263363 ( $( $param: ident ) ,* ) => {
264- // fn(T1...Tn) -> O
265- impl_script_function!( @ $( $param ) ,* : -> O => O ) ;
266- // fn(WorldCallbackAccess, T1...Tn) -> O
267- impl_script_function!( @ $( $param ) ,* : , ( callback: WorldCallbackAccess ) -> O => O ) ;
268- // fn(CallerContext, WorldCallbackAccess, T1...Tn) -> O
269- impl_script_function!( @ $( $param ) ,* : ( context: CallerContext ) , ( callback: WorldCallbackAccess ) -> O => O ) ;
270-
271- // fn(T1...Tn) -> Result<O, InteropError>
272- impl_script_function!( @ $( $param ) ,* : -> O => Result <O , InteropError > where s) ;
273- // fn(WorldCallbackAccess, T1...Tn) -> Result<O, InteropError>
274- impl_script_function!( @ $( $param ) ,* : , ( callback: WorldCallbackAccess ) -> O => Result <O , InteropError > where s) ;
275- // fn(CallerContext, WorldCallbackAccess, T1...Tn) -> Result<O, InteropError>
276- impl_script_function!( @ $( $param ) ,* : ( context: CallerContext ) , ( callback: WorldCallbackAccess ) -> O => Result <O , InteropError > where s) ;
364+ // all of this is pretty heavy on the compile time.
365+ // ideally we'd do less, but for now this will suffice
366+
367+ // Fn(T1...Tn) -> O
368+ impl_script_function!( @ ScriptFunction Fn DynamicScriptFunction into_dynamic_script_function $( $param ) ,* : -> O => O ) ;
369+ // FnMut(T1...Tn) -> O
370+ impl_script_function!( @ ScriptFunctionMut FnMut DynamicScriptFunctionMut into_dynamic_script_function_mut $( $param ) ,* : -> O => O ) ;
371+
372+ // Fn(WorldCallbackAccess, T1...Tn) -> O
373+ impl_script_function!( @ ScriptFunction Fn DynamicScriptFunction into_dynamic_script_function $( $param ) ,* : , ( callback: WorldCallbackAccess ) -> O => O ) ;
374+ // FnMut(WorldCallbackAccess, T1...Tn) -> O
375+ impl_script_function!( @ ScriptFunctionMut FnMut DynamicScriptFunctionMut into_dynamic_script_function_mut $( $param ) ,* : , ( callback: WorldCallbackAccess ) -> O => O ) ;
376+
377+ // Fn(CallerContext, WorldCallbackAccess, T1...Tn) -> O
378+ impl_script_function!( @ ScriptFunction Fn DynamicScriptFunction into_dynamic_script_function $( $param ) ,* : ( context: CallerContext ) , ( callback: WorldCallbackAccess ) -> O => O ) ;
379+ // FnMut(CallerContext, WorldCallbackAccess, T1...Tn) -> O
380+ impl_script_function!( @ ScriptFunctionMut FnMut DynamicScriptFunctionMut into_dynamic_script_function_mut $( $param ) ,* : ( context: CallerContext ) , ( callback: WorldCallbackAccess ) -> O => O ) ;
381+
382+ // Fn(T1...Tn) -> Result<O, InteropError>
383+ impl_script_function!( @ ScriptFunction Fn DynamicScriptFunction into_dynamic_script_function $( $param ) ,* : -> O => Result <O , InteropError > where s) ;
384+ // FnMut(T1...Tn) -> Result<O, InteropError>
385+ impl_script_function!( @ ScriptFunctionMut FnMut DynamicScriptFunctionMut into_dynamic_script_function_mut $( $param ) ,* : -> O => Result <O , InteropError > where s) ;
386+
387+ // Fn(WorldCallbackAccess, T1...Tn) -> Result<O, InteropError>
388+ impl_script_function!( @ ScriptFunction Fn DynamicScriptFunction into_dynamic_script_function $( $param ) ,* : , ( callback: WorldCallbackAccess ) -> O => Result <O , InteropError > where s) ;
389+ // FnMut(WorldCallbackAccess, T1...Tn) -> Result<O, InteropError>
390+ impl_script_function!( @ ScriptFunctionMut FnMut DynamicScriptFunctionMut into_dynamic_script_function_mut $( $param ) ,* : , ( callback: WorldCallbackAccess ) -> O => Result <O , InteropError > where s) ;
391+
392+ // Fn(CallerContext, WorldCallbackAccess, T1...Tn) -> Result<O, InteropError>
393+ impl_script_function!( @ ScriptFunction Fn DynamicScriptFunction into_dynamic_script_function $( $param ) ,* : ( context: CallerContext ) , ( callback: WorldCallbackAccess ) -> O => Result <O , InteropError > where s) ;
394+ // FnMut(CallerContext, WorldCallbackAccess, T1...Tn) -> Result<O, InteropError>
395+ impl_script_function!( @ ScriptFunctionMut FnMut DynamicScriptFunctionMut into_dynamic_script_function_mut $( $param ) ,* : ( context: CallerContext ) , ( callback: WorldCallbackAccess ) -> O => Result <O , InteropError > where s) ;
396+
277397
278398 } ;
279399
280- ( @ $( $param: ident ) ,* : $( ( $context: ident: $contextty: ty) ) ? $( , ( $callback: ident: $callbackty: ty) ) ? -> O => $res: ty $( where $out: ident) ?) => {
400+ ( @ $trait_type : ident $fn_type : ident $dynamic_type : ident $trait_fn_name : ident $ ( $param: ident ) ,* : $( ( $context: ident: $contextty: ty) ) ? $( , ( $callback: ident: $callbackty: ty) ) ? -> O => $res: ty $( where $out: ident) ?) => {
281401 #[ allow( non_snake_case) ]
282402 impl <
283403 ' env,
284404 $( $param: FromScript , ) *
285405 O ,
286406 F
287- > ScriptFunction <' env,
407+ > $trait_type <' env,
288408 fn ( $( $contextty, ) ? $( $callbackty, ) ? $( $param ) ,* ) -> $res
289409 > for F
290410 where
291411 O : IntoScript + TypePath + GetOwnership ,
292- F : Fn ( $( $contextty, ) ? $( $callbackty, ) ? $( $param ) ,* ) -> $res + Send + Sync + ' static ,
412+ F : $fn_type ( $( $contextty, ) ? $( $callbackty, ) ? $( $param ) ,* ) -> $res + Send + Sync + ' static ,
293413 $( $param:: This <' env>: Into <$param>, ) *
294414 {
295415 #[ allow( unused_mut, unused_variables) ]
296- fn into_dynamic_script_function ( self ) -> DynamicScriptFunction {
416+ fn $trait_fn_name ( mut self ) -> $dynamic_type {
297417 let func = ( move |caller_context: CallerContext , world: WorldCallbackAccess , args: Vec <ScriptValue > | {
298418 let res: Result <ScriptValue , InteropError > = ( || {
299419 let expected_arg_count = count!( $( $param ) * ) ;
@@ -330,7 +450,7 @@ macro_rules! impl_script_function {
330450 script_value
331451 } ) ;
332452
333- DynamicScriptFunction { func: Arc :: new ( func ) , name : core :: any :: type_name :: < Self > ( ) . into( ) }
453+ func. into( )
334454 }
335455 }
336456 } ;
0 commit comments