1- use std:: {
2- ops:: { Deref , DerefMut } ,
3- sync:: Arc ,
4- } ;
5-
61use crate :: ReflectReference ;
72/// Common functionality for all script hosts
83use bevy:: {
9- ecs:: system:: Command ,
4+ ecs:: {
5+ component:: ComponentId ,
6+ query:: QueryBuilder ,
7+ system:: Command ,
8+ world:: { EntityRef , World } ,
9+ } ,
1010 prelude:: {
1111 AppTypeRegistry , BuildWorldChildren , Children , DespawnChildrenRecursive , DespawnRecursive ,
1212 Entity , Parent , ReflectComponent , ReflectDefault , ReflectResource ,
@@ -17,6 +17,12 @@ use bevy::{
1717 } ,
1818} ;
1919use 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+ } ;
2026
2127/// Helper trait for retrieving a world pointer from a script context.
2228pub trait GetWorld {
@@ -65,6 +71,51 @@ impl Deref for ScriptTypeRegistration {
6571 }
6672}
6773
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+
68119#[ derive( Clone , Debug ) ]
69120pub struct ScriptWorld ( WorldPointer ) ;
70121
@@ -104,6 +155,7 @@ impl ScriptWorld {
104155 pub fn new ( ptr : WorldPointer ) -> Self {
105156 Self ( ptr)
106157 }
158+
107159 pub fn get_children ( & self , parent : Entity ) -> Vec < Entity > {
108160 let w = self . read ( ) ;
109161 w. get :: < Children > ( parent)
@@ -292,6 +344,7 @@ impl ScriptWorld {
292344
293345 Ok ( resource_data. reflect ( & w) . is_some ( ) )
294346 }
347+
295348 pub fn remove_resource ( & mut self , res_type : ScriptTypeRegistration ) -> Result < ( ) , ScriptError > {
296349 let mut w = self . write ( ) ;
297350
@@ -301,4 +354,90 @@ impl ScriptWorld {
301354 resource_data. remove ( & mut w) ;
302355 Ok ( ( ) )
303356 }
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+ }
304443}
0 commit comments