summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Snopek <dsnopek@gmail.com>2024-02-12 18:43:12 -0600
committerGitHub <noreply@github.com>2024-02-12 18:43:12 -0600
commit5fcc43e54d68c45e7875a189e476c5fe7e14237d (patch)
treedf3b2a092d9981f6f25d1c65dcff249c711a93d9 /src
parent9a13efa0e30a502d44b0352cb1beee77b81d4112 (diff)
parent8fbb7cf79535a2b382d57ce2a094d4cbee316fd1 (diff)
downloadredot-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.cpp41
-rw-r--r--src/godot.cpp6
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);