@@ -85,6 +85,9 @@ pub struct ScriptingPlugin<P: IntoScriptPluginParams> {
8585 pub context_initializers : Vec < ContextInitializer < P > > ,
8686 /// initializers for the contexts run every time before handling events
8787 pub context_pre_handling_initializers : Vec < ContextPreHandlingInitializer < P > > ,
88+
89+ /// Supported extensions to be added to the asset settings without the dot
90+ pub supported_extensions : & ' static [ & ' static str ] ,
8891}
8992
9093impl < P : IntoScriptPluginParams > Plugin for ScriptingPlugin < P > {
@@ -107,6 +110,8 @@ impl<P: IntoScriptPluginParams> Plugin for ScriptingPlugin<P> {
107110 register_script_plugin_systems :: < P > ( app) ;
108111 once_per_app_init ( app) ;
109112
113+ app. add_supported_script_extensions ( self . supported_extensions ) ;
114+
110115 app. world_mut ( )
111116 . resource_mut :: < ScriptAssetSettings > ( )
112117 . as_mut ( )
@@ -115,6 +120,10 @@ impl<P: IntoScriptPluginParams> Plugin for ScriptingPlugin<P> {
115120
116121 register_types ( app) ;
117122 }
123+
124+ fn finish ( & self , app : & mut App ) {
125+ once_per_app_finalize ( app) ;
126+ }
118127}
119128
120129impl < P : IntoScriptPluginParams > ScriptingPlugin < P > {
@@ -197,6 +206,29 @@ impl<P: IntoScriptPluginParams + AsMut<ScriptingPlugin<P>>> ConfigureScriptPlugi
197206 }
198207}
199208
209+ fn once_per_app_finalize ( app : & mut App ) {
210+ #[ derive( Resource ) ]
211+ struct BMSFinalized ;
212+
213+ if app. world ( ) . contains_resource :: < BMSFinalized > ( ) {
214+ return ;
215+ }
216+ app. insert_resource ( BMSFinalized ) ;
217+
218+ // read extensions from asset settings
219+ let asset_settings_extensions = app
220+ . world_mut ( )
221+ . get_resource_or_init :: < ScriptAssetSettings > ( )
222+ . supported_extensions ;
223+
224+ // convert extensions to static array
225+
226+ app. register_asset_loader ( ScriptAssetLoader {
227+ extensions : asset_settings_extensions,
228+ preprocessor : None ,
229+ } ) ;
230+ }
231+
200232// One of registration of things that need to be done only once per app
201233fn once_per_app_init ( app : & mut App ) {
202234 #[ derive( Resource ) ]
@@ -205,19 +237,14 @@ fn once_per_app_init(app: &mut App) {
205237 if app. world ( ) . contains_resource :: < BMSInitialized > ( ) {
206238 return ;
207239 }
208-
209240 app. insert_resource ( BMSInitialized ) ;
210241
211242 app. add_event :: < ScriptErrorEvent > ( )
212243 . add_event :: < ScriptCallbackEvent > ( )
213244 . init_resource :: < AppReflectAllocator > ( )
214245 . init_resource :: < Scripts > ( )
215246 . init_asset :: < ScriptAsset > ( )
216- . init_resource :: < AppScriptFunctionRegistry > ( )
217- . register_asset_loader ( ScriptAssetLoader {
218- extensions : & [ ] ,
219- preprocessor : None ,
220- } ) ;
247+ . init_resource :: < AppScriptFunctionRegistry > ( ) ;
221248
222249 app. add_systems (
223250 PostUpdate ,
@@ -274,3 +301,63 @@ impl AddRuntimeInitializer for App {
274301 self
275302 }
276303}
304+
305+ /// Trait for adding a supported extension to the script asset settings.
306+ ///
307+ /// This is only valid in the plugin building phase, as the asset loader will be created in the `finalize` phase.
308+ /// Any changes to the asset settings after that will not be reflected in the asset loader.
309+ pub trait ConfigureScriptAssetSettings {
310+ /// Adds a supported extension to the asset settings
311+ fn add_supported_script_extensions ( & mut self , extensions : & [ & ' static str ] ) -> & mut Self ;
312+ }
313+
314+ impl ConfigureScriptAssetSettings for App {
315+ fn add_supported_script_extensions ( & mut self , extensions : & [ & ' static str ] ) -> & mut Self {
316+ let mut asset_settings = self
317+ . world_mut ( )
318+ . get_resource_or_init :: < ScriptAssetSettings > ( ) ;
319+
320+ let mut new_arr = Vec :: from ( asset_settings. supported_extensions ) ;
321+
322+ new_arr. extend ( extensions) ;
323+
324+ let new_arr_static = Vec :: leak ( new_arr) ;
325+
326+ asset_settings. supported_extensions = new_arr_static;
327+
328+ self
329+ }
330+ }
331+
332+ #[ cfg( test) ]
333+ mod test {
334+ use super :: * ;
335+
336+ #[ tokio:: test]
337+ async fn test_asset_extensions_correctly_accumulate ( ) {
338+ let mut app = App :: new ( ) ;
339+ app. init_resource :: < ScriptAssetSettings > ( ) ;
340+ app. add_plugins ( AssetPlugin :: default ( ) ) ;
341+
342+ app. world_mut ( )
343+ . resource_mut :: < ScriptAssetSettings > ( )
344+ . supported_extensions = & [ "lua" , "rhai" ] ;
345+
346+ once_per_app_finalize ( & mut app) ;
347+
348+ let asset_loader = app
349+ . world ( )
350+ . get_resource :: < AssetServer > ( )
351+ . expect ( "Asset loader not found" ) ;
352+
353+ asset_loader
354+ . get_asset_loader_with_extension ( "lua" )
355+ . await
356+ . expect ( "Lua loader not found" ) ;
357+
358+ asset_loader
359+ . get_asset_loader_with_extension ( "rhai" )
360+ . await
361+ . expect ( "Rhai loader not found" ) ;
362+ }
363+ }
0 commit comments