7
7
use std:: { cell:: RefCell , collections:: HashSet , ffi:: c_void} ;
8
8
9
9
use godot:: {
10
- builtin:: meta:: { MethodInfo , PropertyInfo , ToGodot } ,
10
+ builtin:: {
11
+ meta:: { MethodInfo , PropertyInfo , ToGodot } ,
12
+ Callable ,
13
+ } ,
11
14
engine:: {
12
- create_script_instance, notify:: ObjectNotification , ClassDb , Engine , IScriptExtension ,
13
- Script , ScriptExtension , ScriptInstance , ScriptLanguage , WeakRef ,
15
+ create_script_instance, notify:: ObjectNotification , object :: ConnectFlags , ClassDb , Engine ,
16
+ IScriptExtension , Script , ScriptExtension , ScriptLanguage , WeakRef ,
14
17
} ,
15
18
log:: { godot_error, godot_print, godot_warn} ,
16
- obj:: { InstanceId , WithBaseField } ,
19
+ obj:: { EngineEnum , InstanceId , WithBaseField } ,
17
20
prelude:: {
18
21
godot_api, Array , Base , Dictionary , GString , Gd , GodotClass , Object , StringName , Variant ,
19
22
VariantArray ,
@@ -35,18 +38,17 @@ const NOTIFICATION_EXTENSION_RELOADED: i32 = 2;
35
38
#[ derive( GodotClass ) ]
36
39
#[ class( base = ScriptExtension , tool) ]
37
40
pub ( super ) struct RustScript {
38
- #[ var( get = get_class_name, set = set_class_name, usage_flags = [ PROPERTY_USAGE_STORAGE ] ) ]
41
+ #[ var( get = get_class_name, set = set_class_name, usage_flags = [ STORAGE ] ) ]
39
42
class_name : GString ,
40
43
41
- #[ var( usage_flags = [ PROPERTY_USAGE_STORAGE ] ) ]
44
+ #[ var( usage_flags = [ STORAGE ] ) ]
42
45
source_code : GString ,
43
46
44
- #[ var( get = owner_ids, set = set_owner_ids, usage_flags = [ PROPERTY_USAGE_STORAGE ] ) ]
47
+ #[ var( get = owner_ids, set = set_owner_ids, usage_flags = [ STORAGE ] ) ]
45
48
#[ allow( dead_code) ]
46
49
owner_ids : Array < i64 > ,
47
50
48
51
owners : RefCell < Vec < Gd < WeakRef > > > ,
49
- #[ base]
50
52
base : Base < ScriptExtension > ,
51
53
}
52
54
@@ -121,29 +123,28 @@ impl RustScript {
121
123
. collect ( ) ;
122
124
}
123
125
124
- fn init_script_instance ( instance : & mut RustScriptInstance ) {
125
- match instance. call ( StringName :: from ( "_init" ) , & [ ] ) {
126
- Ok ( _) => ( ) ,
127
- Err ( err) => {
128
- use godot:: sys:: * ;
129
-
130
- if !matches ! (
131
- err,
132
- GDEXTENSION_CALL_OK | GDEXTENSION_CALL_ERROR_INVALID_METHOD
133
- ) {
134
- let error_code = match err {
135
- GDEXTENSION_CALL_ERROR_INSTANCE_IS_NULL => "INSTANCE_IS_NULL" ,
136
- GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT => "INVALID_ARGUMENT" ,
137
- GDEXTENSION_CALL_ERROR_METHOD_NOT_CONST => "METHOD_NOT_CONST" ,
138
- GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS => "TOO_FEW_ARGUMENTS" ,
139
- GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS => "TOO_MANY_ARGUMENTS" ,
140
- _ => "UNKNOWN" ,
141
- } ;
142
-
143
- godot_error ! ( "failed to call rust script _init fn: {}" , error_code) ;
144
- }
145
- }
126
+ #[ func]
127
+ fn init_script_instance ( base : Variant ) {
128
+ let mut base: Gd < Object > = match base. try_to ( ) {
129
+ Ok ( base) => base,
130
+ Err ( err) => panic ! (
131
+ "init_rust_script_instance was called without base object bind!\n {}" ,
132
+ err
133
+ ) ,
146
134
} ;
135
+
136
+ if let Err ( err) = base. get_script ( ) . try_to :: < Gd < RustScript > > ( ) {
137
+ godot_warn ! ( "expected new script to be previously assigned RustScript, but it wasn't!" ) ;
138
+ godot_warn ! ( "{}" , err) ;
139
+
140
+ return ;
141
+ }
142
+
143
+ if !base. has_method ( "_init" . into ( ) ) {
144
+ return ;
145
+ }
146
+
147
+ base. call ( StringName :: from ( "_init" ) , & [ ] ) ;
147
148
}
148
149
}
149
150
@@ -194,16 +195,26 @@ impl IScriptExtension for RustScript {
194
195
false
195
196
}
196
197
197
- unsafe fn instance_create ( & self , for_object : Gd < Object > ) -> * mut c_void {
198
+ unsafe fn instance_create ( & self , mut for_object : Gd < Object > ) -> * mut c_void {
198
199
self . owners
199
200
. borrow_mut ( )
200
201
. push ( godot:: engine:: utilities:: weakref ( for_object. to_variant ( ) ) . to ( ) ) ;
201
202
202
203
let data = self . create_remote_instance ( for_object. clone ( ) ) ;
203
- let mut instance = RustScriptInstance :: new ( data, for_object, self . to_gd ( ) ) ;
204
+ let instance = RustScriptInstance :: new ( data, for_object. clone ( ) , self . to_gd ( ) ) ;
205
+
206
+ let callbale_args = VariantArray :: from ( & [ for_object. to_variant ( ) ] ) ;
207
+
208
+ for_object
209
+ . connect_ex (
210
+ StringName :: from ( "script_changed" ) ,
211
+ Callable :: from_object_method ( & self . to_gd ( ) , "init_script_instance" )
212
+ . bindv ( callbale_args) ,
213
+ )
214
+ . flags ( ConnectFlags :: ONE_SHOT . ord ( ) as u32 )
215
+ . done ( ) ;
204
216
205
- Self :: init_script_instance ( & mut instance) ;
206
- create_script_instance ( instance)
217
+ create_script_instance ( instance, for_object)
207
218
}
208
219
209
220
unsafe fn placeholder_instance_create ( & self , for_object : Gd < Object > ) -> * mut c_void {
@@ -213,7 +224,7 @@ impl IScriptExtension for RustScript {
213
224
214
225
let placeholder = RustScriptPlaceholder :: new ( self . to_gd ( ) ) ;
215
226
216
- create_script_instance ( placeholder)
227
+ create_script_instance ( placeholder, for_object )
217
228
}
218
229
219
230
fn is_valid ( & self ) -> bool {
0 commit comments