diff options
-rw-r--r-- | .github/workflows/ci.yml | 2 | ||||
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | binding_generator.py | 4 | ||||
-rw-r--r-- | gdextension/extension_api.json | 4 | ||||
-rw-r--r-- | include/godot_cpp/godot.hpp | 32 | ||||
-rw-r--r-- | src/godot.cpp | 90 | ||||
-rw-r--r-- | tools/android.py | 8 |
7 files changed, 104 insertions, 41 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9560e9..4bb1af3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,7 +117,7 @@ jobs: - name: Web dependencies if: ${{ matrix.platform == 'web' }} - uses: mymindstorm/setup-emsdk@v12 + uses: mymindstorm/setup-emsdk@v13 with: version: ${{env.EM_VERSION}} actions-cache-folder: ${{env.EM_CACHE_FOLDER}} diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fe8638..75ff500 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,10 +99,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-DNOMINMAX) else() # GCC/Clang - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -g") - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g") else() set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3") endif(CMAKE_BUILD_TYPE MATCHES Debug) @@ -134,6 +132,7 @@ endif() execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GENERATED_FILES_LIST + OUTPUT_STRIP_TRAILING_WHITESPACE ) add_custom_command(OUTPUT ${GENERATED_FILES_LIST} diff --git a/binding_generator.py b/binding_generator.py index 676ff74..6ebee3d 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -138,9 +138,7 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False): def print_file_list(api_filepath, output_dir, headers=False, sources=False): - end = ";" - for f in get_file_list(api_filepath, output_dir, headers, sources): - print(f, end=end) + print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None) def scons_emit_files(target, source, env): diff --git a/gdextension/extension_api.json b/gdextension/extension_api.json index e8f02ed..d868c7f 100644 --- a/gdextension/extension_api.json +++ b/gdextension/extension_api.json @@ -3,9 +3,9 @@ "version_major": 4, "version_minor": 2, "version_patch": 0, - "version_status": "rc1", + "version_status": "rc2", "version_build": "official", - "version_full_name": "Godot Engine v4.2.rc1.official" + "version_full_name": "Godot Engine v4.2.rc2.official" }, "builtin_class_sizes": [ { diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index d2184a4..c9e9022 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -194,26 +194,44 @@ enum ModuleInitializationLevel { MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE, MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS, MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE, - MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR + MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR, + MODULE_INITIALIZATION_LEVEL_MAX }; class GDExtensionBinding { public: using Callback = void (*)(ModuleInitializationLevel p_level); - static Callback init_callback; - static Callback terminate_callback; - static GDExtensionInitializationLevel minimum_initialization_level; - static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization); + struct InitData { + GDExtensionInitializationLevel minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE; + Callback init_callback = nullptr; + Callback terminate_callback = nullptr; + }; + + class InitDataList { + int data_count = 0; + int data_capacity = 0; + InitData **data = nullptr; + + public: + void add(InitData *p_cb); + ~InitDataList(); + }; + + static bool api_initialized; + static int level_initialized[MODULE_INITIALIZATION_LEVEL_MAX]; + static InitDataList initdata; + static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization); public: - static void initialize_level(void *userdata, GDExtensionInitializationLevel p_level); - static void deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level); + static void initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level); + static void deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level); class InitObject { GDExtensionInterfaceGetProcAddress get_proc_address; GDExtensionClassLibraryPtr library; GDExtensionInitialization *initialization; + mutable InitData *init_data = nullptr; public: InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization); diff --git a/src/godot.cpp b/src/godot.cpp index 70c5978..ee4156b 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -196,9 +196,9 @@ GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugi } // namespace internal -GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr; -GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr; -GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE; +bool GDExtensionBinding::api_initialized = false; +int GDExtensionBinding::level_initialized[MODULE_INITIALIZATION_LEVEL_MAX] = { 0 }; +GDExtensionBinding::InitDataList GDExtensionBinding::initdata; #define ERR_PRINT_EARLY(m_msg) \ internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false) @@ -225,7 +225,20 @@ typedef struct { GDExtensionInterfacePrintErrorWithMessage print_error_with_message; } LegacyGDExtensionInterface; -GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { +GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization) { + if (!p_init_data || !p_init_data->init_callback) { + ERR_FAIL_V_MSG(false, "Initialization callback must be defined."); + } + + if (api_initialized) { + r_initialization->initialize = initialize_level; + r_initialization->deinitialize = deinitialize_level; + r_initialization->userdata = p_init_data; + r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level; + + return true; + } + // Make sure we weren't passed the legacy struct. uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address; if (raw_interface[0] == 4 && raw_interface[1] == 0) { @@ -415,59 +428,96 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge r_initialization->initialize = initialize_level; r_initialization->deinitialize = deinitialize_level; - r_initialization->minimum_initialization_level = minimum_initialization_level; - - ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined."); + r_initialization->userdata = p_init_data; + r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level; Variant::init_bindings(); godot::internal::register_engine_classes(); + api_initialized = true; return true; } #undef LOAD_PROC_ADDRESS #undef ERR_PRINT_EARLY -void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) { +void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) { + ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX); ClassDB::current_level = p_level; - if (init_callback) { - init_callback(static_cast<ModuleInitializationLevel>(p_level)); + InitData *init_data = static_cast<InitData *>(p_userdata); + if (init_data && init_data->init_callback) { + init_data->init_callback(static_cast<ModuleInitializationLevel>(p_level)); } - ClassDB::initialize(p_level); + if (level_initialized[p_level] == 0) { + ClassDB::initialize(p_level); + } + level_initialized[p_level]++; } -void GDExtensionBinding::deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level) { +void GDExtensionBinding::deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) { + ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX); ClassDB::current_level = p_level; - if (terminate_callback) { - terminate_callback(static_cast<ModuleInitializationLevel>(p_level)); + InitData *init_data = static_cast<InitData *>(p_userdata); + if (init_data && init_data->terminate_callback) { + init_data->terminate_callback(static_cast<ModuleInitializationLevel>(p_level)); + } + + level_initialized[p_level]--; + if (level_initialized[p_level] == 0) { + EditorPlugins::deinitialize(p_level); + ClassDB::deinitialize(p_level); + } +} + +void GDExtensionBinding::InitDataList::add(InitData *p_data) { + if (data_count == data_capacity) { + void *new_ptr = realloc(data, sizeof(InitData *) * (data_capacity + 32)); + if (new_ptr) { + data = (InitData **)(new_ptr); + data_capacity += 32; + } else { + ERR_FAIL_MSG("Unable to allocate memory for extension callbacks."); + } } + data[data_count++] = p_data; +} - EditorPlugins::deinitialize(p_level); - ClassDB::deinitialize(p_level); +GDExtensionBinding::InitDataList::~InitDataList() { + for (int i = 0; i < data_count; i++) { + if (data[i]) { + delete data[i]; + } + } + if (data) { + free(data); + } } + GDExtensionBinding::InitObject::InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { get_proc_address = p_get_proc_address; library = p_library; initialization = r_initialization; + init_data = new InitData(); + GDExtensionBinding::initdata.add(init_data); } void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const { - GDExtensionBinding::init_callback = p_init; + init_data->init_callback = p_init; } void GDExtensionBinding::InitObject::register_terminator(Callback p_terminate) const { - GDExtensionBinding::terminate_callback = p_terminate; + init_data->terminate_callback = p_terminate; } void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const { - GDExtensionBinding::minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level); + init_data->minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level); } GDExtensionBool GDExtensionBinding::InitObject::init() const { - return GDExtensionBinding::init(get_proc_address, library, initialization); + return GDExtensionBinding::init(get_proc_address, library, init_data, initialization); } } // namespace godot diff --git a/tools/android.py b/tools/android.py index 479ee15..bee58c4 100644 --- a/tools/android.py +++ b/tools/android.py @@ -8,7 +8,7 @@ def options(opts): opts.Add( "android_api_level", "Target Android API level", - "18" if "32" in ARGUMENTS.get("arch", "arm64") else "21", + "21", ) opts.Add( "ANDROID_HOME", @@ -47,11 +47,9 @@ def generate(env): my_spawn.configure(env) # Validate API level - api_level = int(env["android_api_level"]) - if "64" in env["arch"] and api_level < 21: - print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21") + if int(env["android_api_level"]) < 21: + print("WARNING: minimum supported Android target api is 21. Forcing target api 21.") env["android_api_level"] = "21" - api_level = 21 # Setup toolchain toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/" |