Browse Source

Add support for virtual and abstract classes

Ricardo Buring 2 years ago
parent
commit
01960ffc9f

+ 2 - 0
godot-headers/godot/gdnative_interface.h

@@ -234,6 +234,8 @@ typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtension
 typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
 
 typedef struct {
+	GDNativeBool is_virtual;
+	GDNativeBool is_abstract;
 	GDNativeExtensionClassSet set_func;
 	GDNativeExtensionClassGet get_func;
 	GDNativeExtensionClassGetPropertyList get_property_list_func;

+ 22 - 3
include/godot_cpp/core/class_db.hpp

@@ -108,9 +108,14 @@ private:
 		return ret;
 	}
 
+	template <class T, bool is_abstract>
+	static void _register_class(bool p_virtual = false);
+
 public:
 	template <class T>
-	static void register_class();
+	static void register_class(bool p_virtual = false);
+	template <class T>
+	static void register_abstract_class();
 
 	template <class N, class M, typename... VarArgs>
 	static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
@@ -153,8 +158,8 @@ public:
 		godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, ___call##m_method);                           \
 	}
 
-template <class T>
-void ClassDB::register_class() {
+template <class T, bool is_abstract>
+void ClassDB::_register_class(bool p_virtual) {
 	// Register this class within our plugin
 	ClassInfo cl;
 	cl.name = T::get_class_static();
@@ -169,6 +174,8 @@ void ClassDB::register_class() {
 
 	// Register this class with Godot
 	GDNativeExtensionClassCreationInfo class_info = {
+		p_virtual, // GDNativeBool is_virtual;
+		is_abstract, // GDNativeBool is_abstract;
 		T::set_bind, // GDNativeExtensionClassSet set_func;
 		T::get_bind, // GDNativeExtensionClassGet get_func;
 		T::get_property_list_bind, // GDNativeExtensionClassGetPropertyList get_property_list_func;
@@ -195,6 +202,16 @@ void ClassDB::register_class() {
 	initialize_class(classes[cl.name]);
 }
 
+template <class T>
+void ClassDB::register_class(bool p_virtual) {
+	ClassDB::_register_class<T, false>(p_virtual);
+}
+
+template <class T>
+void ClassDB::register_abstract_class() {
+	ClassDB::_register_class<T, true>();
+}
+
 template <class N, class M, typename... VarArgs>
 MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
 	Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
@@ -251,6 +268,8 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, const char *p_name, M
 }
 
 #define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>();
+#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true);
+#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>();
 
 } // namespace godot
 

+ 14 - 0
test/src/example.h

@@ -107,4 +107,18 @@ public:
 
 VARIANT_ENUM_CAST(Example, Constants);
 
+class ExampleVirtual : public Object {
+	GDCLASS(ExampleVirtual, Object);
+
+protected:
+	static void _bind_methods() {}
+};
+
+class ExampleAbstract : public Object {
+	GDCLASS(ExampleAbstract, Object);
+
+protected:
+	static void _bind_methods() {}
+};
+
 #endif // EXAMPLE_CLASS_H

+ 2 - 0
test/src/register_types.cpp

@@ -24,6 +24,8 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
 	ClassDB::register_class<ExampleRef>();
 	ClassDB::register_class<ExampleMin>();
 	ClassDB::register_class<Example>();
+	ClassDB::register_class<ExampleVirtual>(true);
+	ClassDB::register_abstract_class<ExampleAbstract>();
 }
 
 void uninitialize_example_module(ModuleInitializationLevel p_level) {