summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--CMakeLists.txt5
-rw-r--r--binding_generator.py4
-rw-r--r--gdextension/extension_api.json4
-rw-r--r--include/godot_cpp/godot.hpp32
-rw-r--r--src/godot.cpp90
-rw-r--r--tools/android.py8
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/"