@@ -26,7 +26,7 @@ use bevy::{
26
26
entity:: Entity ,
27
27
query:: { Access , FilteredAccess , FilteredAccessSet , QueryState } ,
28
28
reflect:: AppTypeRegistry ,
29
- schedule:: { IntoSystemConfigs , SystemSet } ,
29
+ schedule:: { IntoSystemConfigs , IntoSystemSetConfigs , SystemSet } ,
30
30
system:: { IntoSystem , System } ,
31
31
world:: { unsafe_world_cell:: UnsafeWorldCell , World } ,
32
32
} ,
@@ -49,7 +49,7 @@ impl std::fmt::Debug for ScriptSystemSet {
49
49
}
50
50
51
51
impl ScriptSystemSet {
52
- /// Creates a new script system set with a unique id
52
+ /// Creates a new script system set
53
53
pub fn new ( id : impl Into < Cow < ' static , str > > ) -> Self {
54
54
Self ( id. into ( ) )
55
55
}
@@ -139,7 +139,7 @@ impl ScriptSystemBuilder {
139
139
world : WorldGuard ,
140
140
schedule : & ReflectSchedule ,
141
141
) -> Result < ReflectSystem , InteropError > {
142
- let o = world. scope_schedule ( schedule, |world, schedule| {
142
+ world. scope_schedule ( schedule, |world, schedule| {
143
143
// this is different to a normal event handler
144
144
// the system doesn't listen to events
145
145
// it immediately calls a singular script with a predefined payload
@@ -156,8 +156,7 @@ impl ScriptSystemBuilder {
156
156
// this is quite important, by default systems are placed in a set defined by their TYPE, i.e. in this case
157
157
// all script systems would be the same
158
158
// let set = ScriptSystemSet::next();
159
- let mut config = IntoSystemConfigs :: < IsDynamicScriptSystem < P > > :: into_configs ( self ) ;
160
-
159
+ let mut set_config = IntoSystemSetConfigs :: into_configs ( set) ;
161
160
// apply ordering
162
161
for ( other, is_before) in before_systems
163
162
. into_iter ( )
@@ -167,50 +166,28 @@ impl ScriptSystemBuilder {
167
166
for default_set in other. default_system_sets ( ) {
168
167
if is_before {
169
168
bevy:: log:: info!( "before {default_set:?}" ) ;
170
- config = config . before ( * default_set) ;
169
+ system_config = system_config . before ( * default_set) ;
171
170
} else { bevy:: log:: info!( "before {default_set:?}" ) ;
172
171
bevy:: log:: info!( "after {default_set:?}" ) ;
173
- config = config . after ( * default_set) ;
172
+ system_config = system_config . after ( * default_set) ;
174
173
}
175
174
}
176
175
}
177
176
178
- schedule. add_systems ( config) ;
177
+ schedule. add_systems ( system_config) ;
178
+ // TODO: the node id seems to always be system.len()
179
+ // if this is slow, we can always just get the node id that way
180
+ // and let the schedule initialize itself right before it gets run
181
+ // for now I want to avoid not having the right ID as that'd be a pain
179
182
schedule. initialize ( world) ?;
180
-
181
- let dot = bevy_system_reflection:: schedule_to_dot_graph ( schedule) ;
182
-
183
- std:: fs:: write ( format ! ( "/home/makspll/git/bevy_mod_scripting/{system_name}_post_update.dot" ) , dot) . expect ( "Unable to write file" ) ;
184
-
185
183
// now find the system
186
184
let ( node_id, system) = schedule
187
185
. systems ( ) ?
188
186
. find ( |( _, b) | b. name ( ) . deref ( ) == system_name)
189
187
. ok_or_else ( || InteropError :: invariant ( "After adding the system, it was not found in the schedule, could not return a reference to it" ) ) ?;
190
188
191
-
192
-
193
189
Ok ( ReflectSystem :: from_system ( system. as_ref ( ) , node_id) )
194
-
195
- } ) ?;
196
-
197
- // #[allow(clippy::expect_used)]
198
- // world.with_global_access(|world| {
199
-
200
- // let mut app = App::new();
201
- // std::mem::swap(app.world_mut(), world);
202
-
203
- // let dot = bevy_mod_debugdump::schedule_graph_dot(&mut app, PostUpdate, &Settings{
204
- // ..Default::default()
205
- // });
206
- // // save to ./graph.dot
207
- // std::fs::write("/home/makspll/git/bevy_mod_scripting/post_update.dot", dot).expect("Unable to write file");
208
-
209
- // // swap worlds back
210
- // std::mem::swap(app.world_mut(), world);
211
- // }).expect("");
212
-
213
- o
190
+ } ) ?
214
191
}
215
192
}
216
193
@@ -407,7 +384,7 @@ impl<P: IntoScriptPluginParams> System for DynamicScriptSystem<P> {
407
384
}
408
385
409
386
fn is_send ( & self ) -> bool {
410
- true
387
+ ! self . is_exclusive ( )
411
388
}
412
389
413
390
fn is_exclusive ( & self ) -> bool {
@@ -640,3 +617,61 @@ impl<P: IntoScriptPluginParams> System for DynamicScriptSystem<P> {
640
617
vec ! [ ScriptSystemSet :: new( self . name. clone( ) ) . intern( ) ]
641
618
}
642
619
}
620
+
621
+
622
+ #[ cfg( test) ]
623
+ mod test {
624
+ use bevy:: { app:: { App , MainScheduleOrder , Update } , asset:: AssetPlugin , diagnostic:: DiagnosticsPlugin , ecs:: schedule:: { ScheduleLabel , Schedules } } ;
625
+ use test_utils:: make_test_plugin;
626
+
627
+ use super :: * ;
628
+
629
+
630
+ make_test_plugin ! ( crate ) ;
631
+
632
+ fn test_system_rust ( world : & mut World ) { }
633
+
634
+ #[ test]
635
+ fn test_script_system_with_existing_system_dependency_can_execute ( ) {
636
+ let mut app = App :: new ( ) ;
637
+
638
+ #[ derive( ScheduleLabel , Clone , Debug , Hash , PartialEq , Eq ) ]
639
+ struct TestSchedule ;
640
+
641
+ app. add_plugins ( ( AssetPlugin :: default ( ) , DiagnosticsPlugin , TestPlugin :: default ( ) ) ) ;
642
+ app. init_schedule ( TestSchedule ) ;
643
+ let mut main_schedule_order = app. world_mut ( ) . resource_mut :: < MainScheduleOrder > ( ) ;
644
+ main_schedule_order. insert_after ( Update , TestSchedule ) ;
645
+ app. add_systems ( TestSchedule , test_system_rust) ;
646
+
647
+
648
+ // run the app once
649
+ app. finish ( ) ;
650
+ app. cleanup ( ) ;
651
+ app. update ( ) ;
652
+
653
+ // find existing rust system
654
+ let test_system = app. world_mut ( ) . resource_scope :: < Schedules , _ > ( |_, schedules| {
655
+ let ( node_id, system) = schedules. get ( TestSchedule )
656
+ . unwrap ( )
657
+ . systems ( )
658
+ . unwrap ( )
659
+ . find ( |( _, system) | {
660
+ system. name ( ) . contains ( "test_system_rust" )
661
+ } )
662
+ . unwrap ( ) ;
663
+
664
+ ReflectSystem :: from_system ( system. as_ref ( ) , node_id)
665
+ } ) ;
666
+
667
+
668
+ // now dynamically add script system via builder
669
+ let mut builder = ScriptSystemBuilder :: new ( "test" . into ( ) , "empty_script" . into ( ) ) ;
670
+ builder. before_system ( test_system) ;
671
+
672
+ let _ = builder. build :: < TestPlugin > ( WorldAccessGuard :: new_exclusive ( app. world_mut ( ) ) , & ReflectSchedule :: from_label ( TestSchedule ) ) . unwrap ( ) ;
673
+
674
+ // now re-run app, expect no panicks
675
+ app. update ( ) ;
676
+ }
677
+ }
0 commit comments