11use std:: { any:: type_name, marker:: PhantomData } ;
22
3- use bevy:: { asset:: Handle , ecs:: world:: Mut , log:: debug, prelude:: Command } ;
3+ use bevy:: {
4+ asset:: Handle ,
5+ ecs:: world:: Mut ,
6+ log:: { debug, info} ,
7+ prelude:: Command ,
8+ } ;
49
510use crate :: {
611 asset:: ScriptAsset ,
712 context:: { Context , ContextLoadingSettings , ScriptContexts } ,
13+ event:: { IntoCallbackLabel , OnScriptLoaded , OnScriptUnloaded } ,
14+ handler:: CallbackSettings ,
815 prelude:: { Runtime , RuntimeContainer } ,
916 script:: { Script , ScriptId , Scripts } ,
1017 systems:: handle_script_errors,
@@ -33,17 +40,47 @@ impl<P: IntoScriptPluginParams> Command for DeleteScript<P> {
3340 . expect ( "No ScriptLoadingSettings resource found" )
3441 . clone ( ) ;
3542
43+ let runner = world
44+ . get_resource :: < CallbackSettings < P > > ( )
45+ . expect ( "No CallbackSettings resource found" )
46+ . callback_handler
47+ . expect ( "No callback handler set" ) ;
48+
49+ let mut ctxts = world
50+ . remove_non_send_resource :: < ScriptContexts < P > > ( )
51+ . unwrap ( ) ;
52+
53+ let mut runtime_container = world
54+ . remove_non_send_resource :: < RuntimeContainer < P > > ( )
55+ . unwrap ( ) ;
56+
3657 world. resource_scope ( |world, mut scripts : Mut < Scripts > | {
3758 if let Some ( script) = scripts. scripts . remove ( & self . id ) {
3859 debug ! ( "Deleting script with id: {}" , self . id) ;
39- let mut ctxts = world. get_non_send_resource_mut :: < ScriptContexts < P > > ( ) ;
40- let ctxts = ctxts. as_deref_mut ( ) . unwrap ( ) ;
60+
61+ // first let the script uninstall itself
62+ match ( runner) (
63+ vec ! [ ] ,
64+ bevy:: ecs:: entity:: Entity :: from_raw ( 0 ) ,
65+ & self . id ,
66+ & OnScriptUnloaded :: into_callback_label ( ) ,
67+ ctxts. get_mut ( script. context_id ) . unwrap ( ) ,
68+ & settings. context_pre_handling_initializers ,
69+ & mut runtime_container. runtime ,
70+ world,
71+ ) {
72+ Ok ( _) => { } ,
73+ Err ( e) => {
74+ handle_script_errors ( world, [ e. with_context ( format ! ( "Running unload hook for script with id: {}. Runtime type: {}, Context type: {}" , self . id, type_name:: <P :: R >( ) , type_name:: <P :: C >( ) ) ) ] . into_iter ( ) ) ;
75+ }
76+ }
77+
4178 let assigner = settings
4279 . assigner
4380 . as_ref ( )
4481 . expect ( "Could not find context assigner in settings" ) ;
4582 debug ! ( "Removing script with id: {}" , self . id) ;
46- ( assigner. remove ) ( script. context_id , & script, ctxts)
83+ ( assigner. remove ) ( script. context_id , & script, & mut ctxts)
4784 } else {
4885 bevy:: log:: error!(
4986 "Attempted to delete script with id: {} but it does not exist, doing nothing!" ,
@@ -53,6 +90,8 @@ impl<P: IntoScriptPluginParams> Command for DeleteScript<P> {
5390 } ) ;
5491
5592 world. insert_resource ( settings) ;
93+ world. insert_non_send_resource ( ctxts) ;
94+ world. insert_non_send_resource ( runtime_container) ;
5695 }
5796}
5897
@@ -80,6 +119,10 @@ impl<P: IntoScriptPluginParams> CreateOrUpdateScript<P> {
80119
81120impl < P : IntoScriptPluginParams > Command for CreateOrUpdateScript < P > {
82121 fn apply ( self , world : & mut bevy:: prelude:: World ) {
122+ debug ! (
123+ "CreateOrUpdateScript command applying to script_id: {}" ,
124+ self . id
125+ ) ;
83126 let settings = world
84127 . get_resource :: < ContextLoadingSettings < P > > ( )
85128 . unwrap ( )
@@ -90,9 +133,12 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
90133 let mut runtime = world
91134 . remove_non_send_resource :: < RuntimeContainer < P > > ( )
92135 . unwrap ( ) ;
136+
137+ let mut runner = world. get_resource :: < CallbackSettings < P > > ( ) . unwrap ( ) ;
93138 // assign context
94139 let assigner = settings. assigner . clone ( ) . expect ( "No context assigner set" ) ;
95140 let builder = settings. loader . clone ( ) . expect ( "No context loader set" ) ;
141+ let runner = runner. callback_handler . expect ( "No callback handler set" ) ;
96142
97143 world. resource_scope ( |world, mut scripts : Mut < Scripts > | {
98144
@@ -111,6 +157,15 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
111157 debug ! ( "Context assigned: {:?}" , current_context_id) ;
112158
113159 let current_context_id = if let Some ( id) = current_context_id {
160+ // reload existing context
161+ let current_context = contexts. get_mut ( id) . unwrap ( ) ;
162+ match ( builder. reload ) ( & self . id , & self . content , current_context, & settings. context_initializers , & settings. context_pre_handling_initializers , world, & mut runtime. runtime ) {
163+ Ok ( _) => { } ,
164+ Err ( e) => {
165+ handle_script_errors ( world, [ e. with_context ( format ! ( "Reloading script with id: {}. Runtime type: {}, Context type: {}" , self . id, type_name:: <P :: R >( ) , type_name:: <P :: C >( ) ) ) ] . into_iter ( ) ) ;
166+ return ;
167+ }
168+ } ;
114169 id
115170 } else {
116171 let ctxt = ( builder. load ) ( & self . id , & self . content , & settings. context_initializers , & settings. context_pre_handling_initializers , world, & mut runtime. runtime ) ;
@@ -123,6 +178,7 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
123178 }
124179 } ;
125180
181+
126182 if let Some ( previous) = previous_context_id {
127183 if previous != current_context_id {
128184 debug ! (
@@ -134,6 +190,13 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
134190 }
135191 }
136192
193+ let context = contexts. get_mut ( current_context_id) . expect ( "Context not found" ) ;
194+ match ( runner) ( vec ! [ ] , bevy:: ecs:: entity:: Entity :: from_raw ( 0 ) , & self . id , & OnScriptLoaded :: into_callback_label ( ) , context, & settings. context_pre_handling_initializers , & mut runtime. runtime , world) {
195+ Ok ( _) => { } ,
196+ Err ( e) => {
197+ handle_script_errors ( world, [ e. with_context ( format ! ( "Running initialization hook for script with id: {}. Runtime type: {}, Context type: {}" , self . id, type_name:: <P :: R >( ) , type_name:: <P :: C >( ) ) ) ] . into_iter ( ) ) ;
198+ } ,
199+ }
137200
138201 // now we can insert the actual script
139202 scripts. scripts . insert (
@@ -144,6 +207,8 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
144207 context_id : current_context_id,
145208 } ,
146209 ) ;
210+
211+ // finally we trigger on_script_loaded
147212 } ) ;
148213 world. insert_resource ( settings) ;
149214 world. insert_non_send_resource ( runtime) ;
0 commit comments