1
1
use std:: { any:: type_name, marker:: PhantomData } ;
2
2
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
+ } ;
4
9
5
10
use crate :: {
6
11
asset:: ScriptAsset ,
7
12
context:: { Context , ContextLoadingSettings , ScriptContexts } ,
13
+ event:: { IntoCallbackLabel , OnScriptLoaded , OnScriptUnloaded } ,
14
+ handler:: CallbackSettings ,
8
15
prelude:: { Runtime , RuntimeContainer } ,
9
16
script:: { Script , ScriptId , Scripts } ,
10
17
systems:: handle_script_errors,
@@ -33,17 +40,47 @@ impl<P: IntoScriptPluginParams> Command for DeleteScript<P> {
33
40
. expect ( "No ScriptLoadingSettings resource found" )
34
41
. clone ( ) ;
35
42
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
+
36
57
world. resource_scope ( |world, mut scripts : Mut < Scripts > | {
37
58
if let Some ( script) = scripts. scripts . remove ( & self . id ) {
38
59
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
+
41
78
let assigner = settings
42
79
. assigner
43
80
. as_ref ( )
44
81
. expect ( "Could not find context assigner in settings" ) ;
45
82
debug ! ( "Removing script with id: {}" , self . id) ;
46
- ( assigner. remove ) ( script. context_id , & script, ctxts)
83
+ ( assigner. remove ) ( script. context_id , & script, & mut ctxts)
47
84
} else {
48
85
bevy:: log:: error!(
49
86
"Attempted to delete script with id: {} but it does not exist, doing nothing!" ,
@@ -53,6 +90,8 @@ impl<P: IntoScriptPluginParams> Command for DeleteScript<P> {
53
90
} ) ;
54
91
55
92
world. insert_resource ( settings) ;
93
+ world. insert_non_send_resource ( ctxts) ;
94
+ world. insert_non_send_resource ( runtime_container) ;
56
95
}
57
96
}
58
97
@@ -80,6 +119,10 @@ impl<P: IntoScriptPluginParams> CreateOrUpdateScript<P> {
80
119
81
120
impl < P : IntoScriptPluginParams > Command for CreateOrUpdateScript < P > {
82
121
fn apply ( self , world : & mut bevy:: prelude:: World ) {
122
+ debug ! (
123
+ "CreateOrUpdateScript command applying to script_id: {}" ,
124
+ self . id
125
+ ) ;
83
126
let settings = world
84
127
. get_resource :: < ContextLoadingSettings < P > > ( )
85
128
. unwrap ( )
@@ -90,9 +133,12 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
90
133
let mut runtime = world
91
134
. remove_non_send_resource :: < RuntimeContainer < P > > ( )
92
135
. unwrap ( ) ;
136
+
137
+ let mut runner = world. get_resource :: < CallbackSettings < P > > ( ) . unwrap ( ) ;
93
138
// assign context
94
139
let assigner = settings. assigner . clone ( ) . expect ( "No context assigner set" ) ;
95
140
let builder = settings. loader . clone ( ) . expect ( "No context loader set" ) ;
141
+ let runner = runner. callback_handler . expect ( "No callback handler set" ) ;
96
142
97
143
world. resource_scope ( |world, mut scripts : Mut < Scripts > | {
98
144
@@ -111,6 +157,15 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
111
157
debug ! ( "Context assigned: {:?}" , current_context_id) ;
112
158
113
159
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
+ } ;
114
169
id
115
170
} else {
116
171
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> {
123
178
}
124
179
} ;
125
180
181
+
126
182
if let Some ( previous) = previous_context_id {
127
183
if previous != current_context_id {
128
184
debug ! (
@@ -134,6 +190,13 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
134
190
}
135
191
}
136
192
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
+ }
137
200
138
201
// now we can insert the actual script
139
202
scripts. scripts . insert (
@@ -144,6 +207,8 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
144
207
context_id : current_context_id,
145
208
} ,
146
209
) ;
210
+
211
+ // finally we trigger on_script_loaded
147
212
} ) ;
148
213
world. insert_resource ( settings) ;
149
214
world. insert_non_send_resource ( runtime) ;
0 commit comments