1
- use std:: {
2
- ops:: { Deref , DerefMut } ,
3
- sync:: Arc ,
4
- } ;
5
-
6
1
use crate :: ReflectReference ;
7
2
/// Common functionality for all script hosts
8
3
use bevy:: {
9
- ecs:: system:: Command ,
4
+ ecs:: {
5
+ component:: ComponentId ,
6
+ query:: QueryBuilder ,
7
+ system:: Command ,
8
+ world:: { EntityRef , World } ,
9
+ } ,
10
10
prelude:: {
11
11
AppTypeRegistry , BuildWorldChildren , Children , DespawnChildrenRecursive , DespawnRecursive ,
12
12
Entity , Parent , ReflectComponent , ReflectDefault , ReflectResource ,
@@ -17,6 +17,12 @@ use bevy::{
17
17
} ,
18
18
} ;
19
19
use bevy_mod_scripting_core:: { prelude:: ScriptError , world:: WorldPointer } ;
20
+ use parking_lot:: MappedRwLockWriteGuard ;
21
+ use std:: {
22
+ any:: Any ,
23
+ ops:: { Deref , DerefMut } ,
24
+ sync:: Arc ,
25
+ } ;
20
26
21
27
/// Helper trait for retrieving a world pointer from a script context.
22
28
pub trait GetWorld {
@@ -65,6 +71,51 @@ impl Deref for ScriptTypeRegistration {
65
71
}
66
72
}
67
73
74
+ #[ derive( Clone ) ]
75
+ pub struct ScriptQueryBuilder {
76
+ world : ScriptWorld ,
77
+ components : Vec < ScriptTypeRegistration > ,
78
+ with : Vec < ScriptTypeRegistration > ,
79
+ without : Vec < ScriptTypeRegistration > ,
80
+ }
81
+
82
+ impl ScriptQueryBuilder {
83
+ pub fn new ( world : ScriptWorld ) -> Self {
84
+ Self {
85
+ world,
86
+ components : vec ! [ ] ,
87
+ with : vec ! [ ] ,
88
+ without : vec ! [ ] ,
89
+ }
90
+ }
91
+
92
+ pub fn components ( & mut self , components : Vec < ScriptTypeRegistration > ) -> & mut Self {
93
+ self . components . extend ( components) ;
94
+ self
95
+ }
96
+
97
+ pub fn with ( & mut self , with : Vec < ScriptTypeRegistration > ) -> & mut Self {
98
+ self . with . extend ( with) ;
99
+ self
100
+ }
101
+
102
+ pub fn without ( & mut self , without : Vec < ScriptTypeRegistration > ) -> & mut Self {
103
+ self . without . extend ( without) ;
104
+ self
105
+ }
106
+
107
+ pub fn build ( & mut self ) -> Result < Vec < ScriptQueryResult > , ScriptError > {
108
+ self . world . query (
109
+ std:: mem:: take ( & mut self . components ) ,
110
+ std:: mem:: take ( & mut self . with ) ,
111
+ std:: mem:: take ( & mut self . without ) ,
112
+ )
113
+ }
114
+ }
115
+
116
+ #[ derive( Clone ) ]
117
+ pub struct ScriptQueryResult ( pub Entity , pub Vec < ReflectReference > ) ;
118
+
68
119
#[ derive( Clone , Debug ) ]
69
120
pub struct ScriptWorld ( WorldPointer ) ;
70
121
@@ -104,6 +155,7 @@ impl ScriptWorld {
104
155
pub fn new ( ptr : WorldPointer ) -> Self {
105
156
Self ( ptr)
106
157
}
158
+
107
159
pub fn get_children ( & self , parent : Entity ) -> Vec < Entity > {
108
160
let w = self . read ( ) ;
109
161
w. get :: < Children > ( parent)
@@ -292,6 +344,7 @@ impl ScriptWorld {
292
344
293
345
Ok ( resource_data. reflect ( & w) . is_some ( ) )
294
346
}
347
+
295
348
pub fn remove_resource ( & mut self , res_type : ScriptTypeRegistration ) -> Result < ( ) , ScriptError > {
296
349
let mut w = self . write ( ) ;
297
350
@@ -301,4 +354,90 @@ impl ScriptWorld {
301
354
resource_data. remove ( & mut w) ;
302
355
Ok ( ( ) )
303
356
}
357
+
358
+ pub fn query (
359
+ & mut self ,
360
+ components : Vec < ScriptTypeRegistration > ,
361
+ with : Vec < ScriptTypeRegistration > ,
362
+ without : Vec < ScriptTypeRegistration > ,
363
+ ) -> Result < Vec < ScriptQueryResult > , ScriptError > {
364
+ let mut w = self . write ( ) ;
365
+
366
+ let get_id = |component : & ScriptTypeRegistration ,
367
+ w : & MappedRwLockWriteGuard < World > |
368
+ -> Result < ComponentId , ScriptError > {
369
+ w. components ( )
370
+ . get_id ( component. type_info ( ) . type_id ( ) )
371
+ . ok_or_else ( || {
372
+ ScriptError :: Other ( format ! ( "Not a component {}" , component. short_name( ) ) )
373
+ } )
374
+ } ;
375
+
376
+ let components: Vec < ( ReflectComponent , ComponentId ) > = components
377
+ . into_iter ( )
378
+ . map ( |component| {
379
+ let reflect_component = component. data :: < ReflectComponent > ( ) . ok_or_else ( || {
380
+ ScriptError :: Other ( format ! ( "Not a component {}" , component. short_name( ) ) )
381
+ } ) ;
382
+
383
+ let component_id = get_id ( & component, & w) ;
384
+ reflect_component. map ( |v1| component_id. map ( |v2| ( v1. clone ( ) , v2) ) ) ?
385
+ } )
386
+ . collect :: < Result < Vec < _ > , ScriptError > > ( ) ?;
387
+
388
+ let with_ids: Vec < ComponentId > = with
389
+ . iter ( )
390
+ . map ( |component| get_id ( component, & w) )
391
+ . collect :: < Result < Vec < _ > , ScriptError > > ( ) ?;
392
+
393
+ let without_ids: Vec < ComponentId > = without
394
+ . iter ( )
395
+ . map ( |component| get_id ( component, & w) )
396
+ . collect :: < Result < Vec < _ > , ScriptError > > ( ) ?;
397
+
398
+ let mut q = QueryBuilder :: < EntityRef > :: new ( & mut w) ;
399
+
400
+ for ( _, id) in & components {
401
+ q. ref_id ( * id) ;
402
+ }
403
+
404
+ for with_id in with_ids {
405
+ q. with_id ( with_id) ;
406
+ }
407
+
408
+ for without_id in without_ids {
409
+ q. without_id ( without_id) ;
410
+ }
411
+
412
+ let query_result: Vec < EntityRef < ' _ > > = q. build ( ) . iter_mut ( & mut w) . collect ( ) ;
413
+
414
+ query_result
415
+ . into_iter ( )
416
+ . map ( |filtered_entity| {
417
+ components
418
+ . clone ( )
419
+ . into_iter ( )
420
+ . map ( |( reflect_component, _) | {
421
+ let type_id = reflect_component. type_id ( ) ;
422
+ reflect_component
423
+ . reflect ( filtered_entity)
424
+ . map ( |_component| {
425
+ ReflectReference :: new_component_ref (
426
+ reflect_component,
427
+ filtered_entity. id ( ) ,
428
+ self . clone ( ) . into ( ) ,
429
+ )
430
+ } )
431
+ . ok_or_else ( || {
432
+ ScriptError :: Other ( format ! (
433
+ "Failed to reflect component during query: {:?}" ,
434
+ type_id
435
+ ) )
436
+ } )
437
+ } )
438
+ . collect :: < Result < Vec < _ > , ScriptError > > ( )
439
+ . map ( |references| ScriptQueryResult ( filtered_entity. id ( ) , references) )
440
+ } )
441
+ . collect :: < Result < Vec < _ > , ScriptError > > ( )
442
+ }
304
443
}
0 commit comments