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"
@@ -685,7 +716,7 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes):
685716 return "\n " .join (result )
686717
687718
688- def generate_builtin_class_header (builtin_api , size , used_classes , fully_used_classes ):
719+ def generate_builtin_class_header (builtin_api , size , used_classes , fully_used_classes , hooks = None ):
689720 result = []
690721
691722 class_name = builtin_api ["name" ]
@@ -1175,10 +1206,13 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
11751206
11761207 result .append ("" )
11771208
1209+ if hooks :
1210+ result = hooks .alter_builtin_class_header (builtin_api , result )
1211+
11781212 return "\n " .join (result )
11791213
11801214
1181- def generate_builtin_class_source (builtin_api , size , used_classes , fully_used_classes ):
1215+ def generate_builtin_class_source (builtin_api , size , used_classes , fully_used_classes , hooks = None ):
11821216 result = []
11831217
11841218 class_name = builtin_api ["name" ]
@@ -1490,10 +1524,13 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
14901524 result .append ("} //namespace godot" )
14911525 result .append ("" )
14921526
1527+ if hooks :
1528+ result = hooks .alter_builtin_class_source (builtin_api , result )
1529+
14931530 return "\n " .join (result )
14941531
14951532
1496- def generate_engine_classes_bindings (api , output_dir , use_template_get_node ):
1533+ def generate_engine_classes_bindings (api , output_dir , use_template_get_node , hooks = None ):
14971534 global engine_classes
14981535 global singletons
14991536 global native_structures
@@ -1685,12 +1722,12 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
16851722
16861723 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
16871724 header_file .write (
1688- generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node )
1725+ generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node , hooks )
16891726 )
16901727
16911728 with source_filename .open ("w+" , encoding = "utf-8" ) as source_file :
16921729 source_file .write (
1693- generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node )
1730+ generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node , hooks )
16941731 )
16951732
16961733 for native_struct in api ["native_structures" ]:
@@ -1749,7 +1786,7 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
17491786 header_file .write ("\n " .join (result ))
17501787
17511788
1752- def generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node ):
1789+ def generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node , hooks ):
17531790 global singletons
17541791 result = []
17551792
@@ -2068,10 +2105,13 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
20682105
20692106 result .append ("" )
20702107
2108+ if hooks :
2109+ result = hooks .alter_engine_class_header (class_api , result )
2110+
20712111 return "\n " .join (result )
20722112
20732113
2074- def generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node ):
2114+ def generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node , hooks = None ):
20752115 global singletons
20762116 result = []
20772117
@@ -2246,10 +2286,13 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
22462286 result .append ("} // namespace godot" )
22472287 result .append ("" )
22482288
2289+ if hooks :
2290+ result = hooks .alter_engine_class_source (class_api , result )
2291+
22492292 return "\n " .join (result )
22502293
22512294
2252- def generate_global_constants (api , output_dir ):
2295+ def generate_global_constants (api , output_dir , hooks = None ):
22532296 include_gen_folder = Path (output_dir ) / "include" / "godot_cpp" / "classes"
22542297 source_gen_folder = Path (output_dir ) / "src" / "classes"
22552298
@@ -2310,6 +2353,9 @@ def generate_global_constants(api, output_dir):
23102353
23112354 header .append ("" )
23122355
2356+ if hooks :
2357+ header = hooks .alter_global_constants (api , header )
2358+
23132359 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
23142360 header_file .write ("\n " .join (header ))
23152361
@@ -2376,7 +2422,7 @@ def generate_global_constant_binds(api, output_dir):
23762422 header_file .write ("\n " .join (header ))
23772423
23782424
2379- def generate_utility_functions (api , output_dir ):
2425+ def generate_utility_functions (api , output_dir , hooks = None ):
23802426 include_gen_folder = Path (output_dir ) / "include" / "godot_cpp" / "variant"
23812427 source_gen_folder = Path (output_dir ) / "src" / "variant"
23822428
@@ -2430,6 +2476,9 @@ def generate_utility_functions(api, output_dir):
24302476 header .append ("} // namespace godot" )
24312477 header .append ("" )
24322478
2479+ if hooks :
2480+ header = hooks .alter_utility_functions_header (api , header )
2481+
24332482 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
24342483 header_file .write ("\n " .join (header ))
24352484
@@ -2509,6 +2558,10 @@ def generate_utility_functions(api, output_dir):
25092558 source .append ("" )
25102559
25112560 source .append ("} // namespace godot" )
2561+ source .append ("" )
2562+
2563+ if hooks :
2564+ header = hooks .alter_utility_functions_source (api , source )
25122565
25132566 with source_filename .open ("w+" , encoding = "utf-8" ) as source_file :
25142567 source_file .write ("\n " .join (source ))
0 commit comments