diff options
| author | David Snopek <dsnopek@gmail.com> | 2024-02-12 18:43:12 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-12 18:43:12 -0600 |
| commit | 5fcc43e54d68c45e7875a189e476c5fe7e14237d (patch) | |
| tree | df3b2a092d9981f6f25d1c65dcff249c711a93d9 /src | |
| parent | 9a13efa0e30a502d44b0352cb1beee77b81d4112 (diff) | |
| parent | 8fbb7cf79535a2b382d57ce2a094d4cbee316fd1 (diff) | |
| download | redot-cpp-5fcc43e54d68c45e7875a189e476c5fe7e14237d.tar.gz | |
Merge pull request #1377 from dsnopek/gdextension-register-virtual-method
Allow GDExtensions to register virtual methods and call them on scripts (godot-cpp support)
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/class_db.cpp | 41 | ||||
| -rw-r--r-- | src/godot.cpp | 6 |
2 files changed, 47 insertions, 0 deletions
diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index 1f4b135..acead8b 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -32,6 +32,7 @@ #include <godot_cpp/core/error_macros.hpp> #include <godot_cpp/godot.hpp> +#include <godot_cpp/templates/vector.hpp> #include <godot_cpp/core/memory.hpp> @@ -337,6 +338,46 @@ void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p type.virtual_methods[p_method] = p_call; } +void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names) { + std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class); + ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class))); + + GDExtensionClassVirtualMethodInfo mi; + mi.name = (GDExtensionStringNamePtr)&p_method.name; + mi.method_flags = p_method.flags; + mi.return_value = p_method.return_val._to_gdextension(); + mi.return_value_metadata = p_method.return_val_metadata; + mi.argument_count = p_method.arguments.size(); + if (mi.argument_count > 0) { + mi.arguments = (GDExtensionPropertyInfo *)memalloc(sizeof(GDExtensionPropertyInfo) * mi.argument_count); + mi.arguments_metadata = (GDExtensionClassMethodArgumentMetadata *)memalloc(sizeof(GDExtensionClassMethodArgumentMetadata) * mi.argument_count); + for (int i = 0; i < mi.argument_count; i++) { + mi.arguments[i] = p_method.arguments[i]._to_gdextension(); + mi.arguments_metadata[i] = p_method.arguments_metadata[i]; + } + } else { + mi.arguments = nullptr; + mi.arguments_metadata = nullptr; + } + + if (p_arg_names.size() != mi.argument_count) { + WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name); + } else { + for (int i = 0; i < p_arg_names.size(); i++) { + mi.arguments[i].name = (GDExtensionStringNamePtr)&p_arg_names[i]; + } + } + + internal::gdextension_interface_classdb_register_extension_class_virtual_method(internal::library, &p_class, &mi); + + if (mi.arguments) { + memfree(mi.arguments); + } + if (mi.arguments_metadata) { + memfree(mi.arguments_metadata); + } +} + void ClassDB::initialize_class(const ClassInfo &p_cl) { } diff --git a/src/godot.cpp b/src/godot.cpp index 5c2aaa6..a80ad90 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -171,6 +171,8 @@ GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_na GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr; GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr; GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr; +GDExtensionInterfaceObjectHasScriptMethod gdextension_interface_object_has_script_method = nullptr; +GDExtensionInterfaceObjectCallScriptMethod gdextension_interface_object_call_script_method = nullptr; GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr; GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr; GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr; @@ -183,6 +185,7 @@ GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_metho GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClass2 gdextension_interface_classdb_register_extension_class2 = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr; +GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed = nullptr; @@ -408,6 +411,8 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo); LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId); LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId); + LOAD_PROC_ADDRESS(object_has_script_method, GDExtensionInterfaceObjectHasScriptMethod); + LOAD_PROC_ADDRESS(object_call_script_method, GDExtensionInterfaceObjectCallScriptMethod); LOAD_PROC_ADDRESS(callable_custom_create, GDExtensionInterfaceCallableCustomCreate); LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData); LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject); @@ -420,6 +425,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(classdb_get_class_tag, GDExtensionInterfaceClassdbGetClassTag); LOAD_PROC_ADDRESS(classdb_register_extension_class2, GDExtensionInterfaceClassdbRegisterExtensionClass2); LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod); + LOAD_PROC_ADDRESS(classdb_register_extension_class_virtual_method, GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod); LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant); LOAD_PROC_ADDRESS(classdb_register_extension_class_property, GDExtensionInterfaceClassdbRegisterExtensionClassProperty); LOAD_PROC_ADDRESS(classdb_register_extension_class_property_indexed, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed); |
