@@ -30,6 +30,14 @@ pub trait ScriptFunction<'env, Marker> {
30
30
fn into_dynamic_script_function ( self ) -> DynamicScriptFunction ;
31
31
}
32
32
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
+
33
41
/// Functionally identical to [`GetTypeRegistration`] but without the 'static bound
34
42
pub trait GetInnerTypeDependencies {
35
43
fn register_type_dependencies ( registry : & mut TypeRegistry ) ;
@@ -39,8 +47,8 @@ pub trait GetInnerTypeDependencies {
39
47
macro_rules! no_type_dependencies {
40
48
( $( $path: path) ,* ) => {
41
49
$(
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 ) { }
44
52
}
45
53
) *
46
54
} ;
@@ -115,7 +123,8 @@ pub struct CallerContext {
115
123
}
116
124
117
125
/// The Script Function equivalent for dynamic functions. Currently unused
118
- #[ derive( Clone ) ]
126
+ #[ derive( Clone , Reflect ) ]
127
+ #[ reflect( opaque) ]
119
128
pub struct DynamicScriptFunction {
120
129
name : Cow < ' static , str > ,
121
130
// 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 {
126
135
+ ' static ,
127
136
> ,
128
137
}
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
+
129
166
impl DynamicScriptFunction {
130
167
pub fn call (
131
168
& self ,
@@ -148,9 +185,72 @@ impl DynamicScriptFunction {
148
185
}
149
186
}
150
187
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
+
151
211
impl std:: fmt:: Debug for DynamicScriptFunction {
152
212
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
+ }
154
254
}
155
255
}
156
256
@@ -261,39 +361,59 @@ macro_rules! count {
261
361
macro_rules! impl_script_function {
262
362
263
363
( $( $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
+
277
397
278
398
} ;
279
399
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) ?) => {
281
401
#[ allow( non_snake_case) ]
282
402
impl <
283
403
' env,
284
404
$( $param: FromScript , ) *
285
405
O ,
286
406
F
287
- > ScriptFunction <' env,
407
+ > $trait_type <' env,
288
408
fn ( $( $contextty, ) ? $( $callbackty, ) ? $( $param ) ,* ) -> $res
289
409
> for F
290
410
where
291
411
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 ,
293
413
$( $param:: This <' env>: Into <$param>, ) *
294
414
{
295
415
#[ allow( unused_mut, unused_variables) ]
296
- fn into_dynamic_script_function ( self ) -> DynamicScriptFunction {
416
+ fn $trait_fn_name ( mut self ) -> $dynamic_type {
297
417
let func = ( move |caller_context: CallerContext , world: WorldCallbackAccess , args: Vec <ScriptValue > | {
298
418
let res: Result <ScriptValue , InteropError > = ( || {
299
419
let expected_arg_count = count!( $( $param ) * ) ;
@@ -330,7 +450,7 @@ macro_rules! impl_script_function {
330
450
script_value
331
451
} ) ;
332
452
333
- DynamicScriptFunction { func: Arc :: new ( func ) , name : core :: any :: type_name :: < Self > ( ) . into( ) }
453
+ func. into( )
334
454
}
335
455
}
336
456
} ;
0 commit comments