8
8
use std:: ffi:: c_void;
9
9
10
10
use godot:: builtin:: { Array , Dictionary , GString , StringName , Variant , VariantType } ;
11
- use godot:: classes:: { IScriptExtension , Object , Script , ScriptExtension , ScriptLanguage } ;
11
+ use godot:: classes:: script_language:: ScriptNameCasing ;
12
+ use godot:: classes:: {
13
+ IScriptExtension , IScriptLanguageExtension , Object , Script , ScriptExtension , ScriptLanguage ,
14
+ ScriptLanguageExtension ,
15
+ } ;
12
16
use godot:: global:: { Error , MethodFlags } ;
13
17
use godot:: meta:: { ClassName , FromGodot , MethodInfo , PropertyInfo , ToGodot } ;
14
18
use godot:: obj:: script:: { create_script_instance, ScriptInstance , SiMut } ;
15
- use godot:: obj:: { Base , Gd , WithBaseField } ;
19
+ use godot:: obj:: { Base , Gd , NewAlloc , WithBaseField } ;
16
20
use godot:: register:: { godot_api, GodotClass } ;
17
21
use godot:: sys;
18
22
23
+ use crate :: framework:: itest;
24
+
19
25
#[ derive( GodotClass ) ]
20
- #[ class( base = ScriptExtension , init , tool) ]
26
+ #[ class( base = ScriptExtension , no_init , tool) ]
21
27
struct TestScript {
28
+ language : Gd < TestScriptLanguage > ,
22
29
base : Base < ScriptExtension > ,
23
30
}
24
31
32
+ impl TestScript {
33
+ fn new ( language : Gd < TestScriptLanguage > ) -> Gd < Self > {
34
+ Gd :: from_init_fn ( |base| Self { language, base } )
35
+ }
36
+ }
37
+
25
38
#[ rustfmt:: skip]
26
39
#[ godot_api]
27
40
impl IScriptExtension for TestScript {
41
+
28
42
fn can_instantiate ( & self ) -> bool {
29
43
true
30
44
}
@@ -33,6 +47,10 @@ impl IScriptExtension for TestScript {
33
47
create_script_instance ( TestScriptInstance :: new ( self . to_gd ( ) . upcast ( ) ) , for_object)
34
48
}
35
49
50
+ fn get_language ( & self ) -> Option < Gd < ScriptLanguage > > {
51
+ Some ( self . language . clone ( ) . upcast ( ) )
52
+ }
53
+
36
54
fn editor_can_reload_from_file ( & mut self ) -> bool { unreachable ! ( ) }
37
55
fn get_base_script ( & self ) -> Option < Gd < Script > > { unreachable ! ( ) }
38
56
fn get_global_name ( & self ) -> StringName { unreachable ! ( ) }
@@ -51,7 +69,6 @@ impl IScriptExtension for TestScript {
51
69
fn get_method_info ( & self , _method : StringName ) -> Dictionary { unreachable ! ( ) }
52
70
fn is_tool ( & self ) -> bool { unreachable ! ( ) }
53
71
fn is_valid ( & self ) -> bool { unreachable ! ( ) }
54
- fn get_language ( & self ) -> Option < Gd < ScriptLanguage > > { unreachable ! ( ) }
55
72
fn has_script_signal ( & self , _signall : StringName ) -> bool { unreachable ! ( ) }
56
73
fn get_script_signal_list ( & self ) -> Array < Dictionary > { unreachable ! ( ) }
57
74
fn has_property_default_value ( & self , _property : StringName ) -> bool { unreachable ! ( ) }
@@ -75,12 +92,18 @@ struct TestScriptInstance {
75
92
prop_list : Vec < PropertyInfo > ,
76
93
method_list : Vec < MethodInfo > ,
77
94
script : Gd < Script > ,
95
+ script_language : Gd < ScriptLanguage > ,
78
96
}
79
97
80
98
impl TestScriptInstance {
81
- fn new ( script : Gd < Script > ) -> Self {
99
+ fn new ( script : Gd < TestScript > ) -> Self {
82
100
Self {
83
- script,
101
+ script_language : {
102
+ let s = script. bind ( ) ;
103
+
104
+ s. get_language ( ) . unwrap ( )
105
+ } ,
106
+ script : script. upcast ( ) ,
84
107
script_property_b : false ,
85
108
prop_list : vec ! [ PropertyInfo :: new_var:: <i64 >( "script_property_a" ) ] ,
86
109
@@ -200,7 +223,7 @@ impl ScriptInstance for TestScriptInstance {
200
223
}
201
224
202
225
fn get_language ( & self ) -> Gd < ScriptLanguage > {
203
- panic ! ( "language is not implemented" )
226
+ self . script_language . clone ( )
204
227
}
205
228
206
229
fn on_refcount_decremented ( & self ) -> bool {
@@ -222,3 +245,109 @@ impl ScriptInstance for TestScriptInstance {
222
245
None
223
246
}
224
247
}
248
+
249
+ #[ derive( GodotClass ) ]
250
+ #[ class( base = ScriptLanguageExtension , tool, init) ]
251
+ struct TestScriptLanguage {
252
+ base : Base < ScriptLanguageExtension > ,
253
+ }
254
+
255
+ #[ godot_api]
256
+ impl TestScriptLanguage {
257
+ #[ func]
258
+ fn new_script ( & self ) -> Gd < TestScript > {
259
+ TestScript :: new ( self . base ( ) . to_godot ( ) . cast ( ) )
260
+ }
261
+ }
262
+
263
+ #[ godot_api]
264
+ #[ rustfmt:: skip]
265
+ impl IScriptLanguageExtension for TestScriptLanguage {
266
+ fn get_name ( & self ) -> GString { unreachable ! ( ) }
267
+ fn init_ext ( & mut self ) { unreachable ! ( ) }
268
+ fn get_type ( & self ) -> GString { unreachable ! ( ) }
269
+ fn get_extension ( & self ) -> GString { unreachable ! ( ) }
270
+ fn finish ( & mut self ) { unreachable ! ( ) }
271
+ fn get_reserved_words ( & self ) -> godot:: prelude:: PackedStringArray { unreachable ! ( ) }
272
+ fn is_control_flow_keyword ( & self , _keyword : GString ) -> bool { unreachable ! ( ) }
273
+ fn get_comment_delimiters ( & self ) -> godot:: prelude:: PackedStringArray { unreachable ! ( ) }
274
+ fn get_string_delimiters ( & self ) -> godot:: prelude:: PackedStringArray { unreachable ! ( ) }
275
+ fn make_template ( & self , _template : GString , _class_name : GString , _base_class_name : GString ) -> Option < Gd < Script > > { unreachable ! ( ) }
276
+ fn get_built_in_templates ( & self , _object : StringName ) -> Array < Dictionary > { unreachable ! ( ) }
277
+ fn is_using_templates ( & mut self ) -> bool { unreachable ! ( ) }
278
+ fn validate ( & self , _script : GString , _path : GString , _validate_functions : bool , _validate_errors : bool , _validate_warnings : bool , _validate_safe_lines : bool ) -> Dictionary { unreachable ! ( ) }
279
+ fn validate_path ( & self , _path : GString ) -> GString { unreachable ! ( ) }
280
+ fn create_script ( & self ) -> Option < Gd < Object > > { unreachable ! ( ) }
281
+ fn has_named_classes ( & self ) -> bool { unreachable ! ( ) }
282
+ fn supports_builtin_mode ( & self ) -> bool { unreachable ! ( ) }
283
+ fn supports_documentation ( & self ) -> bool { unreachable ! ( ) }
284
+ fn can_inherit_from_file ( & self ) -> bool { unreachable ! ( ) }
285
+ fn find_function ( & self , _class_name : GString , _function_namee : GString ) -> i32 { unreachable ! ( ) }
286
+ fn make_function ( & self , _class_name : GString , _function_name : GString , _function_args : godot:: prelude:: PackedStringArray ) -> GString { unreachable ! ( ) }
287
+ fn open_in_external_editor ( & mut self , _script : Option < Gd < Script > > , _line : i32 , _column : i32 ) -> godot:: global:: Error { unreachable ! ( ) }
288
+ fn overrides_external_editor ( & mut self ) -> bool { unreachable ! ( ) }
289
+ fn complete_code ( & self , _code : GString , _pathh : GString , _ownerer : Option < Gd < Object > > ) -> Dictionary { unreachable ! ( ) }
290
+ fn lookup_code ( & self , _code : GString , _symbol : GString , _path : GString , _owner : Option < Gd < Object > > ) -> Dictionary { unreachable ! ( ) }
291
+ fn auto_indent_code ( & self , _code : GString , _from_linee : i32 , _to_line : i32 ) -> GString { unreachable ! ( ) }
292
+ fn add_global_constant ( & mut self , _name : StringName , _valuee : Variant ) { unreachable ! ( ) }
293
+ fn add_named_global_constant ( & mut self , _name : StringName , _valuee : Variant ) { unreachable ! ( ) }
294
+ fn remove_named_global_constant ( & mut self , _name : StringName ) { unreachable ! ( ) }
295
+ fn thread_enter ( & mut self ) { unreachable ! ( ) }
296
+ fn thread_exit ( & mut self ) { unreachable ! ( ) }
297
+ fn debug_get_error ( & self ) -> GString { unreachable ! ( ) }
298
+ fn debug_get_stack_level_count ( & self ) -> i32 { unreachable ! ( ) }
299
+ fn debug_get_stack_level_line ( & self , _level : i32 ) -> i32 { unreachable ! ( ) }
300
+ fn debug_get_stack_level_function ( & self , _level : i32 ) -> GString { unreachable ! ( ) }
301
+ fn debug_get_stack_level_locals ( & mut self , _level : i32 , _max_subitems : i32 , _max_depth : i32 ) -> Dictionary { unreachable ! ( ) }
302
+ fn debug_get_stack_level_members ( & mut self , _level : i32 , _max_subitems : i32 , _max_depth : i32 ) -> Dictionary { unreachable ! ( ) }
303
+ unsafe fn debug_get_stack_level_instance ( & mut self , _level : i32 ) -> * mut c_void { unreachable ! ( ) }
304
+ fn debug_get_globals ( & mut self , _max_subitems : i32 , _max_depthh : i32 ) -> Dictionary { unreachable ! ( ) }
305
+ fn debug_parse_stack_level_expression ( & mut self , _level : i32 , _expression : GString , _max_subitems : i32 , _max_depth : i32 ) -> GString { unreachable ! ( ) }
306
+ fn debug_get_current_stack_info ( & mut self ) -> Array < Dictionary > { unreachable ! ( ) }
307
+ fn reload_all_scripts ( & mut self ) { unreachable ! ( ) }
308
+ fn reload_tool_script ( & mut self , _script : Option < Gd < Script > > , _soft_reloadd : bool ) { unreachable ! ( ) }
309
+ fn get_recognized_extensions ( & self ) -> godot:: prelude:: PackedStringArray { unreachable ! ( ) }
310
+ fn get_public_functions ( & self ) -> Array < Dictionary > { unreachable ! ( ) }
311
+ fn get_public_constants ( & self ) -> Dictionary { unreachable ! ( ) }
312
+ fn get_public_annotations ( & self ) -> Array < Dictionary > { unreachable ! ( ) }
313
+ fn profiling_start ( & mut self ) { unreachable ! ( ) }
314
+ fn profiling_stop ( & mut self ) { unreachable ! ( ) }
315
+ unsafe fn profiling_get_accumulated_data ( & mut self , _info_array : * mut godot:: classes:: native:: ScriptLanguageExtensionProfilingInfo , _info_max : i32 ) -> i32 { unreachable ! ( ) }
316
+ unsafe fn profiling_get_frame_data ( & mut self , _info_array : * mut godot:: classes:: native:: ScriptLanguageExtensionProfilingInfo , _info_max : i32 ) -> i32 { unreachable ! ( ) }
317
+ fn frame ( & mut self ) { unreachable ! ( ) }
318
+ fn handles_global_class_type ( & self , _type_ : GString ) -> bool { unreachable ! ( ) }
319
+ fn get_global_class_name ( & self , _path : GString ) -> Dictionary { unreachable ! ( ) }
320
+ #[ cfg( since_api = "4.3" ) ]
321
+ fn profiling_set_save_native_calls ( & mut self , _enable : bool ) { unreachable ! ( ) }
322
+ #[ cfg( since_api = "4.3" ) ]
323
+ fn debug_get_stack_level_source ( & self , _level : i32 ) -> GString { unreachable ! ( ) }
324
+ #[ cfg( since_api = "4.3" ) ]
325
+ fn can_make_function ( & self ) -> bool { unreachable ! ( ) }
326
+ #[ cfg( since_api = "4.3" ) ]
327
+ fn preferred_file_name_casing ( & self ) -> ScriptNameCasing { unreachable ! ( ) }
328
+ #[ cfg( since_api = "4.4" ) ]
329
+ fn reload_scripts ( & mut self , _scripts : Array < Variant > , _soft : bool ) { unreachable ! ( ) }
330
+ }
331
+
332
+ // -------- Test Cases --------
333
+
334
+ /// Test that [`script_instance_exists`] returns true if a instance of a script exists for the given object.
335
+ #[ itest]
336
+ fn script_instance_exists ( ) {
337
+ let language = TestScriptLanguage :: new_alloc ( ) ;
338
+ let script = TestScript :: new ( language. clone ( ) ) ;
339
+ let mut object = Object :: new_alloc ( ) ;
340
+
341
+ object. set_script ( & script. to_variant ( ) ) ;
342
+
343
+ let instance_exists = godot:: obj:: script:: script_instance_exists ( & object, & script, & language) ;
344
+ assert ! ( instance_exists) ;
345
+
346
+ object. set_script ( & Variant :: nil ( ) ) ;
347
+
348
+ let instance_exists = godot:: obj:: script:: script_instance_exists ( & object, & script, & language) ;
349
+ assert ! ( !instance_exists) ;
350
+
351
+ object. free ( ) ;
352
+ language. free ( ) ;
353
+ }
0 commit comments