11#!/usr/bin/env python
22
3+ import importlib .util
34import json
45import re
56import shutil
7+ import sys
68from pathlib import Path
79
810from make_interface_header import generate_gdextension_interface_header
@@ -284,16 +286,45 @@ def print_file_list(api_filepath, output_dir, headers=False, sources=False):
284286
285287
286288def generate_bindings (
287- api_filepath , interface_filepath , use_template_get_node , bits = "64" , precision = "single" , output_dir = "."
289+ api_filepath ,
290+ interface_filepath ,
291+ use_template_get_node ,
292+ bits = "64" ,
293+ precision = "single" ,
294+ output_dir = "." ,
295+ hooks_path = None ,
288296):
289297 api = {}
290298 with open (api_filepath , encoding = "utf-8" ) as api_file :
291299 api = json .load (api_file )
292- _generate_bindings (api , api_filepath , interface_filepath , use_template_get_node , bits , precision , output_dir )
300+ custom_hooks = None
301+ if hooks_path :
302+ # load the file dynamically
303+ try :
304+ spec = importlib .util .spec_from_file_location ("custom_binding_generator_hooks" , hooks_path )
305+ loaded_module = importlib .util .module_from_spec (spec )
306+ sys .modules ["custom_binding_generator_hooks" ] = loaded_module
307+ spec .loader .exec_module (loaded_module )
308+ # assume the class is named 'CustomBindingGeneratorHooks'
309+ custom_hooks = loaded_module .CustomBindingGeneratorHooks ()
310+ except Exception :
311+ raise Exception (
312+ "Failed to load custom binding generator hooks. Make sure your path points to a python file which defines a class named 'BindingGeneratorHooks'"
313+ )
314+ _generate_bindings (
315+ api , api_filepath , interface_filepath , use_template_get_node , bits , precision , output_dir , custom_hooks
316+ )
293317
294318
295319def _generate_bindings (
296- api , api_filepath , interface_filepath , use_template_get_node , bits = "64" , precision = "single" , output_dir = "."
320+ api ,
321+ api_filepath ,
322+ interface_filepath ,
323+ use_template_get_node ,
324+ bits = "64" ,
325+ precision = "single" ,
326+ output_dir = "." ,
327+ hooks = None ,
297328):
298329 if "precision" in api ["header" ] and precision != api ["header" ]["precision" ]:
299330 raise Exception (
@@ -318,12 +349,12 @@ def _generate_bindings(
318349
319350 generate_gdextension_interface_loader (interface_filepath , target_dir )
320351
321- generate_global_constants (api , target_dir )
352+ generate_global_constants (api , target_dir , hooks )
322353 generate_version_header (api , target_dir )
323354 generate_global_constant_binds (api , target_dir )
324- generate_builtin_bindings (api , target_dir , real_t + "_" + bits )
325- generate_engine_classes_bindings (api , target_dir , use_template_get_node )
326- generate_utility_functions (api , target_dir )
355+ generate_builtin_bindings (api , target_dir , real_t + "_" + bits , hooks )
356+ generate_engine_classes_bindings (api , target_dir , use_template_get_node , hooks )
357+ generate_utility_functions (api , target_dir , hooks )
327358
328359
329360def generate_gdextension_interface_loader (interface_filepath , output_dir ):
@@ -502,7 +533,7 @@ def generate_gdextension_interface_loader_source(data):
502533singletons = []
503534
504535
505- def generate_builtin_bindings (api , output_dir , build_config ):
536+ def generate_builtin_bindings (api , output_dir , build_config , hooks = None ):
506537 global builtin_classes
507538
508539 core_gen_folder = Path (output_dir ) / "include" / "godot_cpp" / "core"
@@ -606,10 +637,10 @@ def generate_builtin_bindings(api, output_dir, build_config):
606637 fully_used_classes .sort ()
607638
608639 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
609- header_file .write (generate_builtin_class_header (builtin_api , size , used_classes , fully_used_classes ))
640+ header_file .write (generate_builtin_class_header (builtin_api , size , used_classes , fully_used_classes , hooks ))
610641
611642 with source_filename .open ("w+" , encoding = "utf-8" ) as source_file :
612- source_file .write (generate_builtin_class_source (builtin_api , size , used_classes , fully_used_classes ))
643+ source_file .write (generate_builtin_class_source (builtin_api , size , used_classes , fully_used_classes , hooks ))
613644
614645 # Create a header with all builtin types for convenience.
615646 builtin_header_filename = include_gen_folder / "builtin_types.hpp"
@@ -684,7 +715,7 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes):
684715 return "\n " .join (result )
685716
686717
687- def generate_builtin_class_header (builtin_api , size , used_classes , fully_used_classes ):
718+ def generate_builtin_class_header (builtin_api , size , used_classes , fully_used_classes , hooks = None ):
688719 result = []
689720
690721 class_name = builtin_api ["name" ]
@@ -1174,10 +1205,13 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
11741205
11751206 result .append ("" )
11761207
1208+ if hooks :
1209+ result = hooks .alter_builtin_class_header (builtin_api , result )
1210+
11771211 return "\n " .join (result )
11781212
11791213
1180- def generate_builtin_class_source (builtin_api , size , used_classes , fully_used_classes ):
1214+ def generate_builtin_class_source (builtin_api , size , used_classes , fully_used_classes , hooks = None ):
11811215 result = []
11821216
11831217 class_name = builtin_api ["name" ]
@@ -1489,10 +1523,13 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
14891523 result .append ("} //namespace godot" )
14901524 result .append ("" )
14911525
1526+ if hooks :
1527+ result = hooks .alter_builtin_class_source (builtin_api , result )
1528+
14921529 return "\n " .join (result )
14931530
14941531
1495- def generate_engine_classes_bindings (api , output_dir , use_template_get_node ):
1532+ def generate_engine_classes_bindings (api , output_dir , use_template_get_node , hooks = None ):
14961533 global engine_classes
14971534 global singletons
14981535 global native_structures
@@ -1684,12 +1721,12 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
16841721
16851722 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
16861723 header_file .write (
1687- generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node )
1724+ generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node , hooks )
16881725 )
16891726
16901727 with source_filename .open ("w+" , encoding = "utf-8" ) as source_file :
16911728 source_file .write (
1692- generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node )
1729+ generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node , hooks )
16931730 )
16941731
16951732 for native_struct in api ["native_structures" ]:
@@ -1748,7 +1785,7 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
17481785 header_file .write ("\n " .join (result ))
17491786
17501787
1751- def generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node ):
1788+ def generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node , hooks ):
17521789 global singletons
17531790 result = []
17541791
@@ -2073,10 +2110,13 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
20732110
20742111 result .append ("" )
20752112
2113+ if hooks :
2114+ result = hooks .alter_engine_class_header (class_api , result )
2115+
20762116 return "\n " .join (result )
20772117
20782118
2079- def generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node ):
2119+ def generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node , hooks = None ):
20802120 global singletons
20812121 result = []
20822122
@@ -2254,10 +2294,13 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
22542294 result .append ("} // namespace godot" )
22552295 result .append ("" )
22562296
2297+ if hooks :
2298+ result = hooks .alter_engine_class_source (class_api , result )
2299+
22572300 return "\n " .join (result )
22582301
22592302
2260- def generate_global_constants (api , output_dir ):
2303+ def generate_global_constants (api , output_dir , hooks = None ):
22612304 include_gen_folder = Path (output_dir ) / "include" / "godot_cpp" / "classes"
22622305 source_gen_folder = Path (output_dir ) / "src" / "classes"
22632306
@@ -2318,6 +2361,9 @@ def generate_global_constants(api, output_dir):
23182361
23192362 header .append ("" )
23202363
2364+ if hooks :
2365+ header = hooks .alter_global_constants (api , header )
2366+
23212367 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
23222368 header_file .write ("\n " .join (header ))
23232369
@@ -2384,7 +2430,7 @@ def generate_global_constant_binds(api, output_dir):
23842430 header_file .write ("\n " .join (header ))
23852431
23862432
2387- def generate_utility_functions (api , output_dir ):
2433+ def generate_utility_functions (api , output_dir , hooks = None ):
23882434 include_gen_folder = Path (output_dir ) / "include" / "godot_cpp" / "variant"
23892435 source_gen_folder = Path (output_dir ) / "src" / "variant"
23902436
@@ -2438,6 +2484,9 @@ def generate_utility_functions(api, output_dir):
24382484 header .append ("} // namespace godot" )
24392485 header .append ("" )
24402486
2487+ if hooks :
2488+ header = hooks .alter_utility_functions_header (api , header )
2489+
24412490 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
24422491 header_file .write ("\n " .join (header ))
24432492
@@ -2517,6 +2566,10 @@ def generate_utility_functions(api, output_dir):
25172566 source .append ("" )
25182567
25192568 source .append ("} // namespace godot" )
2569+ source .append ("" )
2570+
2571+ if hooks :
2572+ header = hooks .alter_utility_functions_source (api , source )
25202573
25212574 with source_filename .open ("w+" , encoding = "utf-8" ) as source_file :
25222575 source_file .write ("\n " .join (source ))
0 commit comments