Skip to content

Update for GDExtension interface changes in Godot 4.5 #1792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion binding_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,6 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append("\tconst Variant &operator[](int64_t p_index) const;")
result.append("\tVariant &operator[](int64_t p_index);")
result.append("\tvoid set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script);")
result.append("\tvoid _ref(const Array &p_from) const;")
result.append("""
struct Iterator {
_FORCE_INLINE_ Variant &operator*() const;
Expand Down
4 changes: 4 additions & 0 deletions gdextension/gdextension_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,12 @@ typedef void (*GDExtensionMainLoopShutdownCallback)();
typedef void (*GDExtensionMainLoopFrameCallback)();

typedef struct {
// Will be called after Godot is started and is fully initialized.
GDExtensionMainLoopStartupCallback startup_func;
// Will be called before Godot is shutdown when it is still fully initialized.
GDExtensionMainLoopShutdownCallback shutdown_func;
// Will be called for each process frame. This will run after all `_process()` methods on Node, and before `ScriptServer::frame()`.
// This is intended to be the equivalent of `ScriptLanguage::frame()` for GDExtension language bindings that don't use the script API.
GDExtensionMainLoopFrameCallback frame_func;
} GDExtensionMainLoopCallbacks;

Expand Down
18 changes: 15 additions & 3 deletions include/godot_cpp/godot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ extern "C" GDExtensionInterfaceGetProcAddress gdextension_interface_get_proc_add
extern "C" GDExtensionClassLibraryPtr library;
extern "C" void *token;

extern "C" GDExtensionGodotVersion godot_version;
extern "C" GDExtensionGodotVersion2 godot_version;

// All of the GDExtension interface functions.
extern "C" GDExtensionInterfaceGetGodotVersion gdextension_interface_get_godot_version;
extern "C" GDExtensionInterfaceGetGodotVersion2 gdextension_interface_get_godot_version2;
extern "C" GDExtensionInterfaceMemAlloc gdextension_interface_mem_alloc;
extern "C" GDExtensionInterfaceMemRealloc gdextension_interface_mem_realloc;
extern "C" GDExtensionInterfaceMemFree gdextension_interface_mem_free;
Expand Down Expand Up @@ -155,7 +155,6 @@ extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_inter
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index;
extern "C" GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayRef gdextension_interface_array_ref;
extern "C" GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed;
extern "C" GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index;
extern "C" GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const;
Expand Down Expand Up @@ -204,6 +203,7 @@ extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_inter
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len;
extern "C" GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw;
extern "C" GDExtensionInterfaceImagePtr gdextension_interface_image_ptr;
extern "C" GDExtensionInterfaceRegisterMainLoopCallbacks gdextension_interface_register_main_loop_callbacks;

class DocDataRegistration {
public:
Expand All @@ -228,6 +228,11 @@ class GDExtensionBinding {
GDExtensionInitializationLevel minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
Callback init_callback = nullptr;
Callback terminate_callback = nullptr;
GDExtensionMainLoopCallbacks main_loop_callbacks = {};

inline bool has_main_loop_callbacks() const {
return main_loop_callbacks.frame_func || main_loop_callbacks.startup_func || main_loop_callbacks.shutdown_func;
}
};

class InitDataList {
Expand Down Expand Up @@ -262,6 +267,13 @@ class GDExtensionBinding {
void register_terminator(Callback p_init) const;
void set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const;

// Register a callback that is called after all initialization levels when Godot is fully initialized.
void register_startup_callback(GDExtensionMainLoopStartupCallback p_callback) const;
// Register a callback that is called for every process frame. This will run after all `_process()` methods on Node, and before `ScriptServer::frame()`.
void register_frame_callback(GDExtensionMainLoopFrameCallback p_callback) const;
// Register a callback that is called before Godot is shutdown when it is still fully initialized.
void register_shutdown_callback(GDExtensionMainLoopShutdownCallback p_callback) const;

GDExtensionBool init() const;
};
};
Expand Down
8 changes: 4 additions & 4 deletions include/godot_cpp/variant/typed_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ class TypedArray : public Array {
public:
_FORCE_INLINE_ void operator=(const Array &p_array) {
ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type.");
_ref(p_array);
Array::operator=(p_array);
}
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
TypedArray(Array(p_variant)) {
}
_FORCE_INLINE_ TypedArray(const Array &p_array) {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
if (is_same_typed(p_array)) {
_ref(p_array);
Array::operator=(p_array);
} else {
assign(p_array);
}
Expand All @@ -68,7 +68,7 @@ class TypedArray : public Array {
public: \
_FORCE_INLINE_ void operator=(const Array &p_array) { \
ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); \
_ref(p_array); \
Array::operator=(p_array); \
} \
_FORCE_INLINE_ TypedArray(std::initializer_list<Variant> p_init) : \
Array(Array(p_init), m_variant_type, StringName(), Variant()) { \
Expand All @@ -79,7 +79,7 @@ class TypedArray : public Array {
_FORCE_INLINE_ TypedArray(const Array &p_array) { \
set_typed(m_variant_type, StringName(), Variant()); \
if (is_same_typed(p_array)) { \
_ref(p_array); \
Array::operator=(p_array); \
} else { \
assign(p_array); \
} \
Expand Down
28 changes: 22 additions & 6 deletions src/godot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ GDExtensionInterfaceGetProcAddress gdextension_interface_get_proc_address = null
GDExtensionClassLibraryPtr library = nullptr;
void *token = nullptr;

GDExtensionGodotVersion godot_version = { 0, 0, 0, nullptr };
GDExtensionGodotVersion2 godot_version = {};

// All of the GDExtension interface functions.
GDExtensionInterfaceGetGodotVersion gdextension_interface_get_godot_version = nullptr;
GDExtensionInterfaceGetGodotVersion2 gdextension_interface_get_godot_version2 = nullptr;
GDExtensionInterfaceMemAlloc gdextension_interface_mem_alloc = nullptr;
GDExtensionInterfaceMemRealloc gdextension_interface_mem_realloc = nullptr;
GDExtensionInterfaceMemFree gdextension_interface_mem_free = nullptr;
Expand Down Expand Up @@ -162,7 +162,6 @@ GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed
GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const = nullptr;
GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index = nullptr;
GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const = nullptr;
GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr;
GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed = nullptr;
GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index = nullptr;
GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const = nullptr;
Expand Down Expand Up @@ -211,6 +210,7 @@ GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor
GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len = nullptr;
GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw = nullptr;
GDExtensionInterfaceImagePtr gdextension_interface_image_ptr = nullptr;
GDExtensionInterfaceRegisterMainLoopCallbacks gdextension_interface_register_main_loop_callbacks = nullptr;

struct DocData {
const char *hash = nullptr;
Expand Down Expand Up @@ -308,8 +308,8 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
internal::library = p_library;
internal::token = p_library;

LOAD_PROC_ADDRESS(get_godot_version, GDExtensionInterfaceGetGodotVersion);
internal::gdextension_interface_get_godot_version(&internal::godot_version);
LOAD_PROC_ADDRESS(get_godot_version2, GDExtensionInterfaceGetGodotVersion2);
internal::gdextension_interface_get_godot_version2(&internal::godot_version);

// Check that godot-cpp was compiled using an extension_api.json older or at the
// same version as the Godot that is loading it.
Expand Down Expand Up @@ -447,7 +447,6 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(packed_vector4_array_operator_index_const, GDExtensionInterfacePackedVector4ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(array_operator_index, GDExtensionInterfaceArrayOperatorIndex);
LOAD_PROC_ADDRESS(array_operator_index_const, GDExtensionInterfaceArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(array_ref, GDExtensionInterfaceArrayRef);
LOAD_PROC_ADDRESS(array_set_typed, GDExtensionInterfaceArraySetTyped);
LOAD_PROC_ADDRESS(dictionary_operator_index, GDExtensionInterfaceDictionaryOperatorIndex);
LOAD_PROC_ADDRESS(dictionary_operator_index_const, GDExtensionInterfaceDictionaryOperatorIndexConst);
Expand Down Expand Up @@ -496,6 +495,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars_and_len, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen);
LOAD_PROC_ADDRESS(image_ptrw, GDExtensionInterfaceImagePtrw);
LOAD_PROC_ADDRESS(image_ptr, GDExtensionInterfaceImagePtr);
LOAD_PROC_ADDRESS(register_main_loop_callbacks, GDExtensionInterfaceRegisterMainLoopCallbacks);

r_initialization->initialize = initialize_level;
r_initialization->deinitialize = deinitialize_level;
Expand Down Expand Up @@ -526,6 +526,10 @@ void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializ
}
level_initialized[p_level]++;

if ((ModuleInitializationLevel)p_level == MODULE_INITIALIZATION_LEVEL_CORE && init_data && init_data->has_main_loop_callbacks()) {
internal::gdextension_interface_register_main_loop_callbacks(internal::library, &init_data->main_loop_callbacks);
}

if ((ModuleInitializationLevel)p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
internal::gdextension_interface_editor_register_get_classes_used_callback(internal::library, &ClassDB::_editor_get_classes_used_callback);

Expand Down Expand Up @@ -596,6 +600,18 @@ void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(Mo
init_data->minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level);
}

void GDExtensionBinding::InitObject::register_startup_callback(GDExtensionMainLoopStartupCallback p_callback) const {
init_data->main_loop_callbacks.startup_func = p_callback;
}

void GDExtensionBinding::InitObject::register_frame_callback(GDExtensionMainLoopFrameCallback p_callback) const {
init_data->main_loop_callbacks.frame_func = p_callback;
}

void GDExtensionBinding::InitObject::register_shutdown_callback(GDExtensionMainLoopShutdownCallback p_callback) const {
init_data->main_loop_callbacks.shutdown_func = p_callback;
}

GDExtensionBool GDExtensionBinding::InitObject::init() const {
return GDExtensionBinding::init(get_proc_address, library, init_data, initialization);
}
Expand Down
4 changes: 0 additions & 4 deletions src/variant/packed_arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,6 @@ void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Var
internal::gdextension_interface_array_set_typed((GDExtensionTypePtr *)this, (GDExtensionVariantType)p_type, (GDExtensionConstStringNamePtr)&p_class_name, (GDExtensionConstVariantPtr)&p_script);
}

void Array::_ref(const Array &p_from) const {
internal::gdextension_interface_array_ref((GDExtensionTypePtr *)this, (GDExtensionConstTypePtr *)&p_from);
}

const Variant *Array::ptr() const {
return (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
Expand Down
Loading