feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -96,8 +96,7 @@ static String fix_doc_description(const String &p_bbcode) {
// Based on what EditorHelp does.
return p_bbcode.dedent()
.replace("\t", "")
.replace("\r", "")
.remove_chars("\t\r")
.strip_edges();
}
@ -107,16 +106,22 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
{
//header
Dictionary header;
header["version_major"] = VERSION_MAJOR;
header["version_minor"] = VERSION_MINOR;
#if VERSION_PATCH
header["version_patch"] = VERSION_PATCH;
header["version_major"] = GODOT_VERSION_MAJOR;
header["version_minor"] = GODOT_VERSION_MINOR;
#if GODOT_VERSION_PATCH
header["version_patch"] = GODOT_VERSION_PATCH;
#else
header["version_patch"] = 0;
#endif
header["version_status"] = VERSION_STATUS;
header["version_build"] = VERSION_BUILD;
header["version_full_name"] = VERSION_FULL_NAME;
header["version_status"] = GODOT_VERSION_STATUS;
header["version_build"] = GODOT_VERSION_BUILD;
header["version_full_name"] = GODOT_VERSION_FULL_NAME;
#if REAL_T_IS_DOUBLE
header["precision"] = "double";
#else
header["precision"] = "single";
#endif
api_dump["header"] = header;
}
@ -278,43 +283,43 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
#define REAL_MEMBER_OFFSET(type, member) \
{ \
type, \
member, \
"float", \
sizeof(float), \
"float", \
sizeof(float), \
"double", \
sizeof(double), \
"double", \
sizeof(double), \
member, \
"float", \
sizeof(float), \
"float", \
sizeof(float), \
"double", \
sizeof(double), \
"double", \
sizeof(double), \
}
#define INT32_MEMBER_OFFSET(type, member) \
{ \
type, \
member, \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
member, \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
}
#define INT32_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
{ \
type, \
member, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
}
#define REAL_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
@ -970,14 +975,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
Array values;
List<StringName> enum_constant_list;
ClassDB::get_enum_constants(class_name, F, &enum_constant_list, true);
for (List<StringName>::Element *G = enum_constant_list.front(); G; G = G->next()) {
for (const StringName &enum_constant : enum_constant_list) {
Dictionary d3;
d3["name"] = String(G->get());
d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
d3["name"] = String(enum_constant);
d3["value"] = ClassDB::get_integer_constant(class_name, enum_constant);
if (p_include_docs) {
for (const DocData::ConstantDoc &constant_doc : class_doc->constants) {
if (constant_doc.name == G->get()) {
if (constant_doc.name == enum_constant) {
d3["description"] = fix_doc_description(constant_doc.description);
break;
}
@ -1048,9 +1053,8 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
}
Array arguments;
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++i) {
const PropertyInfo &pinfo = *itr;
for (int64_t i = 0; i < mi.arguments.size(); ++i) {
const PropertyInfo &pinfo = mi.arguments[i];
Dictionary d3;
d3["name"] = pinfo.name;
@ -1175,11 +1179,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
Array arguments;
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = F.arguments.begin(); itr != F.arguments.end(); ++itr, ++i) {
for (int64_t i = 0; i < F.arguments.size(); ++i) {
Dictionary d3;
d3["name"] = itr->name;
d3["type"] = get_property_info_type_name(*itr);
d3["name"] = F.arguments[i].name;
d3["type"] = get_property_info_type_name(F.arguments[i]);
if (F.get_argument_meta(i) > 0) {
d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i));
}
@ -1340,16 +1343,16 @@ static bool compare_value(const String &p_path, const String &p_field, const Var
} else if (p_old_value.get_type() == Variant::DICTIONARY && p_new_value.get_type() == Variant::DICTIONARY) {
Dictionary old_dict = p_old_value;
Dictionary new_dict = p_new_value;
for (const Variant &key : old_dict.keys()) {
if (!new_dict.has(key)) {
for (const KeyValue<Variant, Variant> &kv : old_dict) {
if (!new_dict.has(kv.key)) {
failed = true;
print_error(vformat("Validate extension JSON: Error: Field '%s': %s was removed.", p_path, key));
print_error(vformat("Validate extension JSON: Error: Field '%s': %s was removed.", p_path, kv.key));
continue;
}
if (p_allow_name_change && key == "name") {
if (p_allow_name_change && kv.key == "name") {
continue;
}
if (!compare_value(path, key, old_dict[key], new_dict[key], p_allow_name_change)) {
if (!compare_value(path, kv.key, kv.value, new_dict[kv.key], p_allow_name_change)) {
failed = true;
}
}
@ -1420,25 +1423,25 @@ static bool compare_dict_array(const Dictionary &p_old_api, const Dictionary &p_
bool optional = field.begins_with("*");
if (optional) {
// This is an optional field, but if exists it has to exist in both.
field = field.substr(1, field.length());
field = field.substr(1);
}
bool added = field.begins_with("+");
if (added) {
// Meaning this field must either exist or contents may not exist.
field = field.substr(1, field.length());
field = field.substr(1);
}
bool enum_values = field.begins_with("$");
if (enum_values) {
// Meaning this field is a list of enum values.
field = field.substr(1, field.length());
field = field.substr(1);
}
bool allow_name_change = field.begins_with("@");
if (allow_name_change) {
// Meaning that when structurally comparing the old and new value, the dictionary entry 'name' may change.
field = field.substr(1, field.length());
field = field.substr(1);
}
Variant old_value;
@ -1598,8 +1601,8 @@ Error GDExtensionAPIDump::validate_extension_json_file(const String &p_path) {
int major = header["version_major"];
int minor = header["version_minor"];
ERR_FAIL_COND_V_MSG(major != VERSION_MAJOR, ERR_INVALID_DATA, vformat("JSON API dump is for a different engine version (%d) than this one (%d)", major, VERSION_MAJOR));
ERR_FAIL_COND_V_MSG(minor > VERSION_MINOR, ERR_INVALID_DATA, vformat("JSON API dump is for a newer version of the engine: %d.%d", major, minor));
ERR_FAIL_COND_V_MSG(major != GODOT_VERSION_MAJOR, ERR_INVALID_DATA, vformat("JSON API dump is for a different engine version (%d) than this one (%d)", major, GODOT_VERSION_MAJOR));
ERR_FAIL_COND_V_MSG(minor > GODOT_VERSION_MINOR, ERR_INVALID_DATA, vformat("JSON API dump is for a newer version of the engine: %d.%d", major, minor));
}
bool failed = false;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EXTENSION_API_DUMP_H
#define EXTENSION_API_DUMP_H
#pragma once
#include "core/extension/gdextension.h"
@ -42,5 +41,3 @@ public:
static Error validate_extension_json_file(const String &p_path);
};
#endif
#endif // EXTENSION_API_DUMP_H

View file

@ -679,6 +679,13 @@ void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExte
memnew_placement(r_path, String(library_path));
}
void GDExtension::_register_get_classes_used_callback(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback) {
#ifdef TOOLS_ENABLED
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
self->get_classes_used_callback = p_callback;
#endif
}
HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) {
@ -799,6 +806,7 @@ void GDExtension::initialize_gdextensions() {
register_interface_function("classdb_register_extension_class_signal", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_signal);
register_interface_function("classdb_unregister_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_unregister_extension_class);
register_interface_function("get_library_path", (GDExtensionInterfaceFunctionPtr)&GDExtension::_get_library_path);
register_interface_function("editor_register_get_classes_used_callback", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_get_classes_used_callback);
}
void GDExtension::finalize_gdextensions() {
@ -1034,6 +1042,14 @@ void GDExtension::_untrack_instance(void *p_user_data, void *p_instance) {
extension->instances.erase(obj->get_instance_id());
}
PackedStringArray GDExtension::get_classes_used() const {
PackedStringArray ret;
if (get_classes_used_callback) {
get_classes_used_callback((GDExtensionTypePtr)&ret);
}
return ret;
}
Vector<StringName> GDExtensionEditorPlugins::extension_classes;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_add_plugin = nullptr;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_H
#define GDEXTENSION_H
#pragma once
#include "core/extension/gdextension_interface.h"
#include "core/extension/gdextension_loader.h"
@ -94,6 +93,7 @@ class GDExtension : public Resource {
static void _register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count);
static void _unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name);
static void _get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path);
static void _register_get_classes_used_callback(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
GDExtensionInitialization initialization;
int32_t level_initialized = -1;
@ -102,6 +102,7 @@ class GDExtension : public Resource {
bool is_reloading = false;
Vector<GDExtensionMethodBind *> invalid_methods;
Vector<ObjectID> instance_bindings;
GDExtensionEditorGetClassesUsedCallback get_classes_used_callback = nullptr;
static void _track_instance(void *p_user_data, void *p_instance);
static void _untrack_instance(void *p_user_data, void *p_instance);
@ -156,6 +157,8 @@ public:
void track_instance_binding(Object *p_object);
void untrack_instance_binding(Object *p_object);
PackedStringArray get_classes_used() const;
#endif
InitializationLevel get_minimum_library_initialization_level() const;
@ -226,5 +229,3 @@ public:
};
#endif // TOOLS_ENABLED
#endif // GDEXTENSION_H

View file

@ -241,11 +241,25 @@ GDExtensionInterfaceFunctionPtr gdextension_get_proc_address(const char *p_name)
return GDExtension::get_interface_function(p_name);
}
#ifndef DISABLE_DEPRECATED
static void gdextension_get_godot_version(GDExtensionGodotVersion *r_godot_version) {
r_godot_version->major = VERSION_MAJOR;
r_godot_version->minor = VERSION_MINOR;
r_godot_version->patch = VERSION_PATCH;
r_godot_version->string = VERSION_FULL_NAME;
r_godot_version->major = GODOT_VERSION_MAJOR;
r_godot_version->minor = GODOT_VERSION_MINOR;
r_godot_version->patch = GODOT_VERSION_PATCH;
r_godot_version->string = GODOT_VERSION_FULL_NAME;
}
#endif
static void gdextension_get_godot_version2(GDExtensionGodotVersion2 *r_godot_version) {
r_godot_version->major = GODOT_VERSION_MAJOR;
r_godot_version->minor = GODOT_VERSION_MINOR;
r_godot_version->patch = GODOT_VERSION_PATCH;
r_godot_version->hex = GODOT_VERSION_HEX;
r_godot_version->status = GODOT_VERSION_STATUS;
r_godot_version->build = GODOT_VERSION_BUILD;
r_godot_version->hash = GODOT_VERSION_HASH;
r_godot_version->timestamp = GODOT_VERSION_TIMESTAMP;
r_godot_version->string = GODOT_VERSION_FULL_NAME;
}
// Memory Functions
@ -858,84 +872,82 @@ static GDExtensionPtrUtilityFunction gdextension_variant_get_ptr_utility_functio
//string helpers
static void gdextension_string_new_with_latin1_chars(GDExtensionUninitializedStringPtr r_dest, const char *p_contents) {
memnew_placement(r_dest, String(p_contents));
String *dest = memnew_placement(r_dest, String);
dest->append_latin1(Span<char>(p_contents, p_contents ? strlen(p_contents) : 0));
}
static void gdextension_string_new_with_utf8_chars(GDExtensionUninitializedStringPtr r_dest, const char *p_contents) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf8(p_contents);
String *dest = memnew_placement(r_dest, String);
dest->append_utf8(p_contents);
}
static void gdextension_string_new_with_utf16_chars(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16(p_contents);
String *dest = memnew_placement(r_dest, String);
dest->append_utf16(p_contents);
}
static void gdextension_string_new_with_utf32_chars(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents) {
memnew_placement(r_dest, String((const char32_t *)p_contents));
String *dest = memnew_placement(r_dest, String);
dest->append_utf32(Span(p_contents, p_contents ? strlen(p_contents) : 0));
}
static void gdextension_string_new_with_wide_chars(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents) {
if constexpr (sizeof(wchar_t) == 2) {
// wchar_t is 16 bit, parse.
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16((const char16_t *)p_contents);
// wchar_t is 16 bit (UTF-16).
String *dest = memnew_placement(r_dest, String);
dest->append_utf16((const char16_t *)p_contents);
} else {
// wchar_t is 32 bit, copy.
memnew_placement(r_dest, String((const char32_t *)p_contents));
// wchar_t is 32 bit (UTF-32).
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span((const char32_t *)p_contents, p_contents ? strlen(p_contents) : 0));
}
}
static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
memnew_placement(r_dest, String(p_contents, p_size));
String *dest = memnew_placement(r_dest, String);
dest->append_latin1(Span(p_contents, p_contents ? _strlen_clipped(p_contents, p_size) : 0));
}
static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf8(p_contents, p_size);
String *dest = memnew_placement(r_dest, String);
dest->append_utf8(p_contents, p_size);
}
static GDExtensionInt gdextension_string_new_with_utf8_chars_and_len2(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
return (GDExtensionInt)dest->parse_utf8(p_contents, p_size);
String *dest = memnew_placement(r_dest, String);
return (GDExtensionInt)dest->append_utf8(p_contents, p_size);
}
static void gdextension_string_new_with_utf16_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16(p_contents, p_char_count);
String *dest = memnew_placement(r_dest, String);
dest->append_utf16(p_contents, p_char_count);
}
static GDExtensionInt gdextension_string_new_with_utf16_chars_and_len2(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count, GDExtensionBool p_default_little_endian) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
return (GDExtensionInt)dest->parse_utf16(p_contents, p_char_count, p_default_little_endian);
String *dest = memnew_placement(r_dest, String);
return (GDExtensionInt)dest->append_utf16(p_contents, p_char_count, p_default_little_endian);
}
static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_char_count) {
memnew_placement(r_dest, String((const char32_t *)p_contents, p_char_count));
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span(p_contents, p_contents ? _strlen_clipped(p_contents, p_char_count) : 0));
}
static void gdextension_string_new_with_wide_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_char_count) {
if constexpr (sizeof(wchar_t) == 2) {
// wchar_t is 16 bit, parse.
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16((const char16_t *)p_contents, p_char_count);
// wchar_t is 16 bit (UTF-16).
String *dest = memnew_placement(r_dest, String);
dest->append_utf16((const char16_t *)p_contents, p_char_count);
} else {
// wchar_t is 32 bit, copy.
memnew_placement(r_dest, String((const char32_t *)p_contents, p_char_count));
// wchar_t is 32 bit (UTF-32).
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span((const char32_t *)p_contents, p_contents ? _strlen_clipped((const char32_t *)p_contents, p_char_count) : 0));
}
}
static GDExtensionInt gdextension_string_to_latin1_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) {
String *self = (String *)p_self;
CharString cs = self->ascii(true);
CharString cs = self->latin1();
GDExtensionInt len = cs.length();
if (r_text) {
const char *s_text = cs.ptr();
@ -1040,16 +1052,12 @@ static void gdextension_string_name_new_with_latin1_chars(GDExtensionUninitializ
}
static void gdextension_string_name_new_with_utf8_chars(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents) {
String tmp;
tmp.parse_utf8(p_contents);
String tmp = String::utf8(p_contents);
memnew_placement(r_dest, StringName(tmp));
}
static void gdextension_string_name_new_with_utf8_chars_and_len(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents, GDExtensionInt p_size) {
String tmp;
tmp.parse_utf8(p_contents, p_size);
String tmp = String::utf8(p_contents, p_size);
memnew_placement(r_dest, StringName(tmp));
}
@ -1543,11 +1551,8 @@ static void gdextension_placeholder_script_instance_update(GDExtensionScriptInst
properties_list.push_back(PropertyInfo::from_dict(d));
}
List<Variant> keys;
values.get_key_list(&keys);
for (const Variant &E : keys) {
values_map.insert(E, values[E]);
for (const KeyValue<Variant, Variant> &kv : values) {
values_map.insert(kv.key, kv.value);
}
placeholder->update(properties_list, values_map);
@ -1572,6 +1577,15 @@ static GDExtensionScriptInstancePtr gdextension_object_get_script_instance(GDExt
return script_instance_extension->instance;
}
static void gdextension_object_set_script_instance(GDExtensionObjectPtr p_object, GDExtensionScriptInstancePtr p_script_instance) {
ERR_FAIL_NULL(p_object);
Object *o = (Object *)p_object;
ScriptInstance *script_instance = (ScriptInstanceExtension *)p_script_instance;
o->set_script_instance(script_instance);
}
#ifndef DISABLE_DEPRECATED
static void gdextension_callable_custom_create(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo *p_custom_callable_info) {
memnew_placement(r_callable, Callable(memnew(CallableCustomExtension(p_custom_callable_info))));
@ -1666,7 +1680,10 @@ static void gdextension_editor_help_load_xml_from_utf8_chars(const char *p_data)
#define REGISTER_INTERFACE_FUNC(m_name) GDExtension::register_interface_function(#m_name, (GDExtensionInterfaceFunctionPtr) & gdextension_##m_name)
void gdextension_setup_interface() {
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(get_godot_version);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(get_godot_version2);
REGISTER_INTERFACE_FUNC(mem_alloc);
REGISTER_INTERFACE_FUNC(mem_realloc);
REGISTER_INTERFACE_FUNC(mem_free);
@ -1809,6 +1826,7 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(placeholder_script_instance_create);
REGISTER_INTERFACE_FUNC(placeholder_script_instance_update);
REGISTER_INTERFACE_FUNC(object_get_script_instance);
REGISTER_INTERFACE_FUNC(object_set_script_instance);
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(callable_custom_create);
#endif // DISABLE_DEPRECATED

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_INTERFACE_H
#define GDEXTENSION_INTERFACE_H
#pragma once
/* This is a C class header, you can copy it and use it directly in your own binders.
* Together with the JSON file, you should be able to generate any binder.
@ -401,6 +400,9 @@ typedef struct {
typedef void *GDExtensionClassLibraryPtr;
/* Passed a pointer to a PackedStringArray that should be filled with the classes that may be used by the GDExtension. */
typedef void (*GDExtensionEditorGetClassesUsedCallback)(GDExtensionTypePtr p_packed_string_array);
/* Method */
typedef enum {
@ -790,9 +792,22 @@ typedef struct {
const char *string;
} GDExtensionGodotVersion;
typedef struct {
uint32_t major;
uint32_t minor;
uint32_t patch;
uint32_t hex; // Full version encoded as hexadecimal with one byte (2 hex digits) per number (e.g. for "3.1.12" it would be 0x03010C)
const char *status; // (e.g. "stable", "beta", "rc1", "rc2")
const char *build; // (e.g. "custom_build")
const char *hash; // Full Git commit hash.
uint64_t timestamp; // Git commit date UNIX timestamp in seconds, or 0 if unavailable.
const char *string; // (e.g. "Godot v3.1.4.stable.official.mono")
} GDExtensionGodotVersion2;
/**
* @name get_godot_version
* @since 4.1
* @deprecated in Godot 4.5. Use `get_godot_version2` instead.
*
* Gets the Godot version that the GDExtension was loaded into.
*
@ -800,6 +815,16 @@ typedef struct {
*/
typedef void (*GDExtensionInterfaceGetGodotVersion)(GDExtensionGodotVersion *r_godot_version);
/**
* @name get_godot_version2
* @since 4.5
*
* Gets the Godot version that the GDExtension was loaded into.
*
* @param r_godot_version A pointer to the structure to write the version information into.
*/
typedef void (*GDExtensionInterfaceGetGodotVersion2)(GDExtensionGodotVersion2 *r_godot_version);
/* INTERFACE: Memory */
/**
@ -2721,6 +2746,17 @@ typedef void (*GDExtensionInterfacePlaceHolderScriptInstanceUpdate)(GDExtensionS
*/
typedef GDExtensionScriptInstanceDataPtr (*GDExtensionInterfaceObjectGetScriptInstance)(GDExtensionConstObjectPtr p_object, GDExtensionObjectPtr p_language);
/**
* @name object_set_script_instance
* @since 4.5
*
* Set the script instance data attached to this object.
*
* @param p_object A pointer to the Object.
* @param p_script_instance A pointer to the script instance data to attach to this object.
*/
typedef void (*GDExtensionInterfaceObjectSetScriptInstance)(GDExtensionObjectPtr p_object, GDExtensionScriptInstanceDataPtr p_script_instance);
/* INTERFACE: Callable */
/**
@ -3078,8 +3114,22 @@ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);
/**
* @name editor_register_get_classes_used_callback
* @since 4.5
*
* Registers a callback that Godot can call to get the list of all classes (from ClassDB) that may be used by the calling GDExtension.
*
* This is used by the editor to generate a build profile (in "Tools" > "Engine Compilation Configuration Editor..." > "Detect from project"),
* in order to recompile Godot with only the classes used.
* In the provided callback, the GDExtension should provide the list of classes that _may_ be used statically, thus the time of invocation shouldn't matter.
* If a GDExtension doesn't register a callback, Godot will assume that it could be using any classes.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_callback The callback to retrieve the list of classes used.
*/
typedef void (*GDExtensionInterfaceEditorRegisterGetClassesUsedCallback)(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
#ifdef __cplusplus
}
#endif
#endif // GDEXTENSION_INTERFACE_H

View file

@ -307,12 +307,12 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
bool compatible = true;
// Check version lexicographically.
if (VERSION_MAJOR != compatibility_minimum[0]) {
compatible = VERSION_MAJOR > compatibility_minimum[0];
} else if (VERSION_MINOR != compatibility_minimum[1]) {
compatible = VERSION_MINOR > compatibility_minimum[1];
if (GODOT_VERSION_MAJOR != compatibility_minimum[0]) {
compatible = GODOT_VERSION_MAJOR > compatibility_minimum[0];
} else if (GODOT_VERSION_MINOR != compatibility_minimum[1]) {
compatible = GODOT_VERSION_MINOR > compatibility_minimum[1];
} else {
compatible = VERSION_PATCH >= compatibility_minimum[2];
compatible = GODOT_VERSION_PATCH >= compatibility_minimum[2];
}
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
@ -334,15 +334,15 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
}
compatible = true;
if (VERSION_MAJOR != compatibility_maximum[0]) {
compatible = VERSION_MAJOR < compatibility_maximum[0];
} else if (VERSION_MINOR != compatibility_maximum[1]) {
compatible = VERSION_MINOR < compatibility_maximum[1];
if (GODOT_VERSION_MAJOR != compatibility_maximum[0]) {
compatible = GODOT_VERSION_MAJOR < compatibility_maximum[0];
} else if (GODOT_VERSION_MINOR != compatibility_maximum[1]) {
compatible = GODOT_VERSION_MINOR < compatibility_maximum[1];
}
#if VERSION_PATCH
#if GODOT_VERSION_PATCH
// #if check to avoid -Wtype-limits warning when 0.
else {
compatible = VERSION_PATCH <= compatibility_maximum[2];
compatible = GODOT_VERSION_PATCH <= compatibility_maximum[2];
}
#endif

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_LIBRARY_LOADER_H
#define GDEXTENSION_LIBRARY_LOADER_H
#pragma once
#include <functional>
@ -38,6 +37,8 @@
#include "core/os/shared_object.h"
class GDExtensionLibraryLoader : public GDExtensionLoader {
GDSOFTCLASS(GDExtensionLibraryLoader, GDExtensionLoader);
friend class GDExtensionManager;
friend class GDExtension;
@ -81,5 +82,3 @@ public:
Error parse_gdextension_file(const String &p_path);
};
#endif // GDEXTENSION_LIBRARY_LOADER_H

View file

@ -28,14 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_LOADER_H
#define GDEXTENSION_LOADER_H
#pragma once
#include "core/object/ref_counted.h"
class GDExtension;
class GDExtensionLoader : public RefCounted {
GDSOFTCLASS(GDExtensionLoader, GDExtensionLoader);
public:
virtual Error open_library(const String &p_path) = 0;
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) = 0;
@ -44,5 +45,3 @@ public:
virtual bool has_library_changed() const = 0;
virtual bool library_exists() const = 0;
};
#endif // GDEXTENSION_LOADER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_MANAGER_H
#define GDEXTENSION_MANAGER_H
#pragma once
#include "core/extension/gdextension.h"
@ -92,5 +91,3 @@ public:
};
VARIANT_ENUM_CAST(GDExtensionManager::LoadStatus)
#endif // GDEXTENSION_MANAGER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_SPECIAL_COMPAT_HASHES_H
#define GDEXTENSION_SPECIAL_COMPAT_HASHES_H
#pragma once
#ifndef DISABLE_DEPRECATED
@ -58,5 +57,3 @@ public:
};
#endif // DISABLE_DEPRECATED
#endif // GDEXTENSION_SPECIAL_COMPAT_HASHES_H

View file

@ -1,55 +1,37 @@
import zlib
import methods
def run(target, source, env):
src = str(source[0])
dst = str(target[0])
with open(src, "rb") as f, open(dst, "w", encoding="utf-8", newline="\n") as g:
buf = f.read()
decomp_size = len(buf)
# Use maximum zlib compression level to further reduce file size
# (at the cost of initial build times).
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
g.write(
"""/* THIS FILE IS GENERATED DO NOT EDIT */
#ifndef GDEXTENSION_INTERFACE_DUMP_H
#define GDEXTENSION_INTERFACE_DUMP_H
buffer = methods.get_buffer(str(source[0]))
decomp_size = len(buffer)
buffer = methods.compress_buffer(buffer)
with methods.generated_wrapper(str(target[0])) as file:
file.write(f"""\
#ifdef TOOLS_ENABLED
#include "core/io/compression.h"
#include "core/io/file_access.h"
#include "core/string/ustring.h"
"""
)
inline constexpr int _gdextension_interface_data_compressed_size = {len(buffer)};
inline constexpr int _gdextension_interface_data_uncompressed_size = {decomp_size};
inline constexpr unsigned char _gdextension_interface_data_compressed[] = {{
{methods.format_buffer(buffer, 1)}
}};
g.write("static const int _gdextension_interface_data_compressed_size = " + str(len(buf)) + ";\n")
g.write("static const int _gdextension_interface_data_uncompressed_size = " + str(decomp_size) + ";\n")
g.write("static const unsigned char _gdextension_interface_data_compressed[] = {\n")
for i in range(len(buf)):
g.write("\t" + str(buf[i]) + ",\n")
g.write("};\n")
g.write(
"""
class GDExtensionInterfaceDump {
public:
static void generate_gdextension_interface_file(const String &p_path) {
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
ERR_FAIL_COND_MSG(fa.is_null(), vformat("Cannot open file '%s' for writing.", p_path));
Vector<uint8_t> data;
data.resize(_gdextension_interface_data_uncompressed_size);
int ret = Compression::decompress(data.ptrw(), _gdextension_interface_data_uncompressed_size, _gdextension_interface_data_compressed, _gdextension_interface_data_compressed_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
fa->store_buffer(data.ptr(), data.size());
};
};
class GDExtensionInterfaceDump {{
public:
static void generate_gdextension_interface_file(const String &p_path) {{
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
ERR_FAIL_COND_MSG(fa.is_null(), vformat("Cannot open file '%s' for writing.", p_path));
Vector<uint8_t> data;
data.resize(_gdextension_interface_data_uncompressed_size);
int ret = Compression::decompress(data.ptrw(), _gdextension_interface_data_uncompressed_size, _gdextension_interface_data_compressed, _gdextension_interface_data_compressed_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
fa->store_buffer(data.ptr(), data.size());
}};
}};
#endif // TOOLS_ENABLED
#endif // GDEXTENSION_INTERFACE_DUMP_H
"""
)
""")

View file

@ -119,10 +119,7 @@ def generate_ex_version(argcount, const=False, returns=False):
def run(target, source, env):
max_versions = 12
txt = """
#ifndef GDEXTENSION_WRAPPERS_GEN_H
#define GDEXTENSION_WRAPPERS_GEN_H
"""
txt = "#pragma once"
for i in range(max_versions + 1):
txt += "\n/* Extension Wrapper " + str(i) + " Arguments */\n"
@ -138,7 +135,5 @@ def run(target, source, env):
txt += generate_mod_version(i, True, False)
txt += generate_mod_version(i, True, True)
txt += "\n#endif\n"
with open(str(target[0]), "w", encoding="utf-8", newline="\n") as f:
f.write(txt)