Rework GDCLASS macro to allow abstract classes#1359
Conversation
68aad1e to
16be4f8
Compare
|
I'd suggest adding a pure virtual class to the test project to verify the functionality |
|
My bad making an improved suggestion |
|
This fixes the problem, and uses the existing examples, applied on top of your PR: diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp
index 43dc365..4e071aa 100644
--- a/include/godot_cpp/classes/wrapped.hpp
+++ b/include/godot_cpp/classes/wrapped.hpp
@@ -152,12 +152,20 @@ template <class T>
class ClassCreator {
public:
static GDExtensionObjectPtr create(void *data) {
- T *new_object = memnew(T);
- return new_object->_owner;
- };
+ if constexpr (!std::is_abstract_v<T>) {
+ T *new_object = memnew(T);
+ return new_object->_owner;
+ } else {
+ return nullptr;
+ }
+ }
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) {
- _GDCLASS_RECREATE(T)
+ if constexpr (!std::is_abstract_v<T>) {
+ _GDCLASS_RECREATE(T);
+ } else {
+ return nullptr;
+ }
}
};
diff --git a/test/src/example.h b/test/src/example.h
index 32d66d5..99e0d5c 100644
--- a/test/src/example.h
+++ b/test/src/example.h
@@ -196,31 +196,17 @@ class ExampleVirtual : public Object {
protected:
static void _bind_methods() {}
+
+ virtual int test_function() { return 25; }
};
class ExampleAbstract : public Object {
GDCLASS(ExampleAbstract, Object);
-protected:
- static void _bind_methods() {}
-};
-
-class ExamplePureVirtualBase : public Object {
- GDCLASS(ExamplePureVirtualBase, Object);
-
protected:
static void _bind_methods() {}
virtual int test_function() = 0;
};
-class ExamplePureVirtual : public ExamplePureVirtualBase {
- GDCLASS(ExamplePureVirtual, ExamplePureVirtualBase);
-
-protected:
- static void _bind_methods() {}
-
- int test_function() override { return 25; }
-};
-
#endif // EXAMPLE_CLASS_H
diff --git a/test/src/register_types.cpp b/test/src/register_types.cpp
index 5b99d38..dbb37d9 100644
--- a/test/src/register_types.cpp
+++ b/test/src/register_types.cpp
@@ -26,9 +26,6 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
ClassDB::register_class<Example>();
ClassDB::register_class<ExampleVirtual>(true);
ClassDB::register_abstract_class<ExampleAbstract>();
-
- GDREGISTER_VIRTUAL_CLASS(ExamplePureVirtualBase);
- GDREGISTER_CLASS(ExamplePureVirtual);
}
void uninitialize_example_module(ModuleInitializationLevel p_level) { |
|
Will look at this after work today. |
cbb1e72 to
ab3db91
Compare
|
Hi @AThousandShips, I decided to actually keep the example classes as I think they provide context specifically for this fix. Your suggestion implements a non-pure virtual function on a class, which worked just fine with the GDCLASS macro without this fix. The problem I'm trying to solve here is pure virtual functions, and your suggested test case doesn't explicitly showcase that aspect. I hope that's okay, would just rather be thorough and explicit so we avoid breaking this in the future. |
|
Not sure how you tested it but the examples I provided failed to work both with your fix and the unchanged library Also you probably didn't read my suggestion properly, it does add a pure virtual function to the abstract class: class ExampleAbstract : public Object {
GDCLASS(ExampleAbstract, Object);
protected:
static void _bind_methods() {}
virtual int test_function() = 0;
}; |
dsnopek
left a comment
There was a problem hiding this comment.
Thanks!
This looks exactly like the approach I was imagining for solving this problem.
I only have a couple nitpicks in addition to AThousandShips' comments.
aa01df9 to
097f698
Compare
dsnopek
left a comment
There was a problem hiding this comment.
Thanks! This is looking really great! :-)
I have just some super tiny nitpicks, mostly around naming.
Thanks @dsnopek, added a commit with the suggested changes. |
|
Thanks! The changes look good. However, you'll need to squash your PR into a single commit before it can be merged - see: https://docs.godotengine.org/en/latest/contributing/workflow/pr_workflow.html#the-interactive-rebase |
|
Cherry-picking to 4.2 in #1372 |
Fixes #1287
This PR moves the
createandrecreatemethods out of theGDCLASSmacro and adjusts the references in theClassDBto use the newClassCreatortemplate class that provides the same functionality as the previous methods in the macro.Users can now freely create Godot classes with pure virtual functions, i.e. this is now possible: