@@ -44,7 +44,7 @@ def GlobRecursive(path, pattern, **kwargs):
4444 return found
4545
4646
47- KEYWORDS = ['GPROPERTY' , 'GMETHOD' , 'GGROUP' , 'GSUBGROUP' , 'GBITFIELD' , 'GSIGNAL' , 'GRPC' , 'GVARARG' , 'GIGNORE' , 'GBIND_METHODS_APPEND' , 'GBIND_METHODS_PREPEND' ]
47+ KEYWORDS = ['GPROPERTY' , 'GMETHOD' , 'GGROUP' , 'GSUBGROUP' , 'GBITFIELD' , 'GSIGNAL' , 'GRPC' , 'GVARARG' , 'GIGNORE' , 'GBIND_METHODS_APPEND' , 'GBIND_METHODS_PREPEND' , 'GRESOURCE_LOADER' , 'GRESOURCE_SAVER' ]
4848INIT_LEVELS = ['GINIT_LEVEL_CORE' , 'GINIT_LEVEL_SERVERS' , 'GINIT_LEVEL_SCENE' , 'GINIT_LEVEL_EDITOR' ]
4949
5050DONOTEDIT_MSG = "/*-- GENERATED FILE - DO NOT EDIT --*/\n \n "
@@ -488,10 +488,16 @@ def process_macros(item, macros, properties, is_ignored=False):
488488 is_ignored = True
489489
490490 case 'GBIND_METHODS_APPEND' :
491- class_defs ['bind_methods_append' ] += get_macro_body (filecontent , macro )
491+ class_defs ['bind_methods_append' ] += ' \n ' + get_macro_body (filecontent , macro ) + ' \n '
492492
493493 case 'GBIND_METHODS_PREPEND' :
494- class_defs ['bind_methods_prepend' ] += get_macro_body (filecontent , macro )
494+ class_defs ['bind_methods_prepend' ] += '\n ' + get_macro_body (filecontent , macro ) + '\n '
495+
496+ case 'GRESOURCE_LOADER' :
497+ class_defs ['is_resource_loader' ] = True
498+
499+ case 'GRESOURCE_SAVER' :
500+ class_defs ['is_resource_saver' ] = True
495501
496502
497503 return not is_ignored
@@ -541,7 +547,7 @@ def apply_macros(item, macros):
541547
542548 leftover = collapse_list (class_macros , lambda x : x .kind != CursorKind .MACRO_INSTANTIATION , apply_macros )
543549 for macro in leftover :
544- if macro .spelling not in ['GSIGNAL' , 'GGROUP' , 'GSUBGROUP' , 'GBIND_METHODS_APPEND' , 'GBIND_METHODS_PREPEND' ] + INIT_LEVELS :
550+ if macro .spelling not in ['GSIGNAL' , 'GGROUP' , 'GSUBGROUP' , 'GBIND_METHODS_APPEND' , 'GBIND_METHODS_PREPEND' , 'GRESOURCE_LOADER' , 'GRESOURCE_SAVER' ] + INIT_LEVELS :
545551 raise CppScriptException ('{}:{}:{}: error: macro without target member'
546552 .format (filename , macro .location .line , macro .location .column ))
547553 process_macros (None , leftover , None )
@@ -561,6 +567,7 @@ def parse_and_write_header(index, filename, filecontent, env):
561567
562568def write_header (file , defs , env ):
563569 header_defs = []
570+ global_variables = []
564571 for class_name_full , content in defs .items ():
565572 class_name = content ['class_name' ]
566573 Hmethod , Hstatic_method , Hvirtual_method , Hvaragr_method , Hprop , Hsignal , Henum , Hbitfield , Hconst = '' , '' , '' , '' , '' , '' , '' , '' , ''
@@ -645,6 +652,13 @@ def write_header(file, defs, env):
645652 for const in content ['constants' ]:
646653 Hconst += f'\t BIND_CONSTANT({ const } );\n '
647654
655+ if 'is_resource_loader' in content :
656+ variable_name = content ["class_name" ] + '_loader'
657+ global_variables .append (f'Ref<{ class_name_full } > { variable_name } ;' )
658+ elif 'is_resource_saver' in content :
659+ variable_name = content ["class_name" ] + '_saver'
660+ global_variables .append (f'Ref<{ class_name_full } > { variable_name } ;' )
661+
648662 header_rpc_config = 'void {}::_rpc_config() {{{}}}\n ' .format (
649663 class_name_full , '\n ' + header_rpc_config if header_rpc_config != '' else '' )
650664 header_bind_methods = '\n \n ' .join (i for i in [Hmethod , Hvirtual_method , Hstatic_method , Hvaragr_method , Hprop , Hsignal , Henum , Hbitfield , Hconst ] if i != '' )
@@ -660,7 +674,10 @@ def write_header(file, defs, env):
660674 gen_filename = filename_to_gen_filename (file , env )
661675 content = ''
662676 if len (defs ) != 0 :
663- header_include = '#include <cppscript_bindings.h>\n \n #include "{}"\n \n using namespace godot;\n \n ' .format (os .path .relpath (file , os .path .dirname (gen_filename )).replace ('\\ ' , '/' ))
677+ header_include = '#include <cppscript_bindings.h>\n \n #include "{}"\n \n using namespace godot;\n \n {}' \
678+ .format (
679+ os .path .relpath (file , os .path .dirname (gen_filename )).replace ('\\ ' , '/' ),
680+ ('\n ' .join (global_variables ) + '\n \n ' if global_variables != [] else '' ))
664681 content = DONOTEDIT_MSG + header_include + '\n ' .join (header_defs )
665682
666683 os .makedirs (os .path .dirname (gen_filename ), exist_ok = True )
@@ -673,12 +690,33 @@ def write_register_header(defs_all, env):
673690 scripts_header = DONOTEDIT_MSG
674691 classes_register_levels = {name [12 :] : [] for name in INIT_LEVELS }
675692
693+ loaders_savers = []
694+ def make_register_str_pair (class_name_full , content ):
695+ register_str = f"\t GDREGISTER_{ content ['type' ]} ({ class_name_full } );\n "
696+ unregister_str = ''
697+
698+ if 'is_resource_loader' in content :
699+ variable_name = f'{ content ["class_name" ]} _loader'
700+
701+ loaders_savers .append (f'extern Ref<{ class_name_full } > { variable_name } ;' )
702+ register_str += f'\t { variable_name } .instantiate();\n \t ResourceLoader::get_singleton()->add_resource_format_loader({ variable_name } );\n '
703+ unregister_str += f'\t ResourceLoader::get_singleton()->remove_resource_format_loader({ variable_name } );\n \t { variable_name } .unref();\n '
704+ elif 'is_resource_saver' in content :
705+ variable_name = f'{ content ["class_name" ]} _saver'
706+
707+ loaders_savers .append (f'extern Ref<{ class_name_full } > { variable_name } ;\n ' )
708+ register_str += f'\t { variable_name } .instantiate();\n \t ResourceSaver::get_singleton()->add_resource_format_saver({ variable_name } );\n '
709+ unregister_str += f'\t ResourceSaver::get_singleton()->remove_resource_format_saver({ variable_name } );\n \t { variable_name } .unref();\n '
710+
711+ return register_str , unregister_str
712+
676713 for file , filecontent in defs_all ['files' ].items ():
677714 classes = filecontent ['content' ]
678715 if len (classes ) == 0 :
679716 continue
680717
681718 scripts_header += '#include "{}"\n ' .format (os .path .relpath (file , os .path .dirname (target )).replace ('\\ ' , '/' ))
719+
682720 for class_name_full , content in classes .items ():
683721 # Ensure parent classes are registered before children
684722 # by iterating throught pairs of (base_name, register_str)
@@ -688,11 +726,15 @@ def write_register_header(defs_all, env):
688726 base = base if dots == - 1 else base [dots + 1 :]
689727 for i in range (len (classes_register )):
690728 if class_name == classes_register [i ][0 ]:
691- classes_register .insert (i , (base , f" \t GDREGISTER_ { content [ 'type' ] } ( { class_name_full } ); \n " ))
729+ classes_register .insert (i , (base , make_register_str_pair ( class_name_full , content ) ))
692730 break
693731 else :
694- classes_register .append ((base , f"\t GDREGISTER_{ content ['type' ]} ({ class_name_full } );\n " ))
732+ classes_register .append ((base , make_register_str_pair (class_name_full , content )))
733+
695734
735+ if loaders_savers != []:
736+ scripts_header += '#include <godot_cpp/classes/resource_loader.hpp>\n '
737+ scripts_header += '#include <godot_cpp/classes/resource_saver.hpp>\n '
696738
697739 classes_register_str = ''
698740 if classes_register_levels ['CORE' ] != []:
@@ -703,12 +745,19 @@ def write_register_header(defs_all, env):
703745 minimal_register_level = 'MODULE_INITIALIZATION_LEVEL_SCENE'
704746
705747 scripts_header += '\n using namespace godot;\n \n ' + \
706- f'static const ModuleInitializationLevel DEFAULT_INIT_LEVEL = { minimal_register_level } ;\n \n '
748+ f'static const ModuleInitializationLevel DEFAULT_INIT_LEVEL = { minimal_register_level } ;\n \n ' + \
749+ ('\n ' .join (loaders_savers ) + '\n \n ' if loaders_savers != [] else '' )
750+
707751 for level_name , defs in classes_register_levels .items ():
708- registers = '' .join (i for _ , i in defs )
752+ registers = '' .join (i [0 ] for _ , i in defs )
753+ unregisters = '' .join (i [1 ] for _ , i in defs )
754+
709755 classes_register_str += '_FORCE_INLINE_ void _register_level_{}() {{{}}}\n \n ' .format (
710756 level_name .lower (), '\n ' + registers if registers != '' else '' )
711757
758+ classes_register_str += '_FORCE_INLINE_ void _unregister_level_{}() {{{}}}\n \n ' .format (
759+ level_name .lower (), '\n ' + unregisters if unregisters != '' else '' )
760+
712761 scripts_header += classes_register_str
713762
714763 new_hash = hashlib .md5 (scripts_header .encode ()).hexdigest ()
0 commit comments