1
1
//! Systems and resources for handling script assets and events
2
2
3
3
use crate :: {
4
+ StaticScripts ,
5
+ ScriptComponent ,
4
6
commands:: { CreateOrUpdateScript , DeleteScript } ,
5
7
error:: ScriptError ,
6
8
script:: ScriptId ,
7
9
IntoScriptPluginParams , ScriptingSystemSet ,
8
10
} ;
9
11
use bevy:: {
10
12
app:: { App , PreUpdate } ,
11
- asset:: { Asset , AssetEvent , AssetId , AssetLoader , AssetPath , Assets } ,
13
+ asset:: { Asset , AssetEvent , AssetId , AssetLoader , AssetPath , Assets , LoadState } ,
12
14
ecs:: system:: Resource ,
13
15
log:: { debug, info, trace, warn} ,
14
16
prelude:: {
15
17
Commands , Event , EventReader , EventWriter , IntoSystemConfigs , IntoSystemSetConfigs , Res ,
16
- ResMut ,
18
+ ResMut , Added , Query , Local , Handle , AssetServer ,
17
19
} ,
18
20
reflect:: TypePath ,
19
21
utils:: hashbrown:: HashMap ,
20
22
} ;
21
- use std:: borrow:: Cow ;
23
+ use std:: { borrow:: Cow , collections :: VecDeque } ;
22
24
23
25
/// Represents a scripting language. Languages which compile into another language should use the target language as their language.
24
26
#[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Default ) ]
@@ -300,6 +302,7 @@ pub(crate) fn remove_script_metadata(
300
302
pub ( crate ) fn sync_script_data < P : IntoScriptPluginParams > (
301
303
mut events : EventReader < ScriptAssetEvent > ,
302
304
script_assets : Res < Assets < ScriptAsset > > ,
305
+ static_scripts : Res < StaticScripts > ,
303
306
mut commands : Commands ,
304
307
) {
305
308
for event in events. read ( ) {
@@ -326,14 +329,16 @@ pub(crate) fn sync_script_data<P: IntoScriptPluginParams>(
326
329
continue ;
327
330
}
328
331
329
- info ! ( "{}: Loading Script: {:?}" , P :: LANGUAGE , metadata. asset_id, ) ;
330
332
331
- if let Some ( asset) = script_assets. get ( metadata. asset_id ) {
332
- commands. queue ( CreateOrUpdateScript :: < P > :: new (
333
- metadata. asset_id . clone ( ) ,
334
- asset. content . clone ( ) ,
335
- Some ( script_assets. reserve_handle ( ) . clone_weak ( ) ) ,
336
- ) ) ;
333
+ if static_scripts. iter ( ) . any ( |handle| handle. id ( ) == metadata. asset_id ) {
334
+ info ! ( "{}: Loading static script: {:?}" , P :: LANGUAGE , metadata. asset_id, ) ;
335
+ if let Some ( asset) = script_assets. get ( metadata. asset_id ) {
336
+ commands. queue ( CreateOrUpdateScript :: < P > :: new (
337
+ metadata. asset_id . clone ( ) ,
338
+ asset. content . clone ( ) ,
339
+ Some ( script_assets. reserve_handle ( ) . clone_weak ( ) ) ,
340
+ ) ) ;
341
+ }
337
342
}
338
343
}
339
344
ScriptAssetEvent :: Removed ( _) => {
@@ -344,6 +349,57 @@ pub(crate) fn sync_script_data<P: IntoScriptPluginParams>(
344
349
}
345
350
}
346
351
352
+ pub ( crate ) fn eval_script < P : IntoScriptPluginParams > (
353
+ script_comps : Query < & ScriptComponent , Added < ScriptComponent > > ,
354
+ mut script_queue : Local < VecDeque < ScriptId > > ,
355
+ script_assets : Res < Assets < ScriptAsset > > ,
356
+ asset_server : Res < AssetServer > ,
357
+ mut commands : Commands ,
358
+ ) {
359
+ for script_comp in & script_comps {
360
+ for handle in & script_comp. 0 {
361
+ script_queue. push_back ( handle. id ( ) ) ;
362
+ }
363
+ }
364
+ while ! script_queue. is_empty ( ) {
365
+ let script_ready = script_queue. front ( ) . map ( |script_id| match asset_server. load_state ( * script_id) {
366
+ LoadState :: Failed ( e) => {
367
+ warn ! ( "Failed to load script {}" , & script_id) ;
368
+ true
369
+ }
370
+ LoadState :: Loaded => true ,
371
+ _ => false
372
+ } ) . unwrap_or ( false ) ;
373
+ if ! script_ready {
374
+ break ;
375
+ }
376
+ // NOTE: Maybe once pop_front_if is stabalized.
377
+ // if let Some(script_id) = script_queue.pop_front_if(|script_id| match asset_server.load_state(script_id) {
378
+ // LoadState::Failed(e) => {
379
+ // warn!("Failed to load script {}", &script_id);
380
+ // true
381
+ // }
382
+ // LoadState::Loaded => true,
383
+ // _ => false
384
+ // }) {
385
+ if let Some ( script_id) = script_queue. pop_front ( ) {
386
+ if let Some ( asset) = script_assets. get ( script_id) {
387
+ commands. queue ( CreateOrUpdateScript :: < P > :: new (
388
+ script_id,
389
+ asset. content . clone ( ) ,
390
+ Some ( Handle :: Weak ( script_id) ) ,
391
+ ) ) ;
392
+ } else {
393
+ // This is probably a load failure. What to do? We've already
394
+ // provided a warning on failure. Doing nothing is fine then we
395
+ // process the next one.
396
+ }
397
+ } else {
398
+ break ;
399
+ }
400
+ }
401
+ }
402
+
347
403
/// Setup all the asset systems for the scripting plugin and the dependencies
348
404
#[ profiling:: function]
349
405
pub ( crate ) fn configure_asset_systems ( app : & mut App ) -> & mut App {
@@ -379,7 +435,7 @@ pub(crate) fn configure_asset_systems_for_plugin<P: IntoScriptPluginParams>(
379
435
) -> & mut App {
380
436
app. add_systems (
381
437
PreUpdate ,
382
- sync_script_data :: < P > . in_set ( ScriptingSystemSet :: ScriptCommandDispatch ) ,
438
+ ( eval_script :: < P > , sync_script_data :: < P > ) . in_set ( ScriptingSystemSet :: ScriptCommandDispatch ) ,
383
439
) ;
384
440
app
385
441
}
0 commit comments