77use std:: { cell:: RefCell , collections:: HashSet , ffi:: c_void} ;
88
99use godot:: {
10- builtin:: meta:: { MethodInfo , PropertyInfo , ToGodot } ,
10+ builtin:: {
11+ meta:: { MethodInfo , PropertyInfo , ToGodot } ,
12+ Callable ,
13+ } ,
1114 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 ,
1417 } ,
1518 log:: { godot_error, godot_print, godot_warn} ,
16- obj:: { InstanceId , WithBaseField } ,
19+ obj:: { EngineEnum , InstanceId , WithBaseField } ,
1720 prelude:: {
1821 godot_api, Array , Base , Dictionary , GString , Gd , GodotClass , Object , StringName , Variant ,
1922 VariantArray ,
@@ -35,18 +38,17 @@ const NOTIFICATION_EXTENSION_RELOADED: i32 = 2;
3538#[ derive( GodotClass ) ]
3639#[ class( base = ScriptExtension , tool) ]
3740pub ( 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 ] ) ]
3942 class_name : GString ,
4043
41- #[ var( usage_flags = [ PROPERTY_USAGE_STORAGE ] ) ]
44+ #[ var( usage_flags = [ STORAGE ] ) ]
4245 source_code : GString ,
4346
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 ] ) ]
4548 #[ allow( dead_code) ]
4649 owner_ids : Array < i64 > ,
4750
4851 owners : RefCell < Vec < Gd < WeakRef > > > ,
49- #[ base]
5052 base : Base < ScriptExtension > ,
5153}
5254
@@ -121,29 +123,28 @@ impl RustScript {
121123 . collect ( ) ;
122124 }
123125
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+ ) ,
146134 } ;
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" ) , & [ ] ) ;
147148 }
148149}
149150
@@ -194,16 +195,26 @@ impl IScriptExtension for RustScript {
194195 false
195196 }
196197
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 {
198199 self . owners
199200 . borrow_mut ( )
200201 . push ( godot:: engine:: utilities:: weakref ( for_object. to_variant ( ) ) . to ( ) ) ;
201202
202203 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 ( ) ;
204216
205- Self :: init_script_instance ( & mut instance) ;
206- create_script_instance ( instance)
217+ create_script_instance ( instance, for_object)
207218 }
208219
209220 unsafe fn placeholder_instance_create ( & self , for_object : Gd < Object > ) -> * mut c_void {
@@ -213,7 +224,7 @@ impl IScriptExtension for RustScript {
213224
214225 let placeholder = RustScriptPlaceholder :: new ( self . to_gd ( ) ) ;
215226
216- create_script_instance ( placeholder)
227+ create_script_instance ( placeholder, for_object )
217228 }
218229
219230 fn is_valid ( & self ) -> bool {
0 commit comments