Skip to content

Commit 6c04514

Browse files
authored
Merge pull request #1359 from Naros/GH-1287
Rework GDCLASS macro to allow abstract classes
2 parents 480a0f8 + 5f350e2 commit 6c04514

File tree

4 files changed

+45
-33
lines changed

4 files changed

+45
-33
lines changed

include/godot_cpp/classes/wrapped.hpp

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ typedef void GodotObject;
4848
// Base for all engine classes, to contain the pointer to the engine instance.
4949
class Wrapped {
5050
friend class GDExtensionBinding;
51+
friend class ClassDB;
5152
friend void postinitialize_handler(Wrapped *);
5253

5354
protected:
@@ -131,17 +132,6 @@ struct EngineClassRegistration {
131132

132133
} // namespace godot
133134

134-
#ifdef HOT_RELOAD_ENABLED
135-
#define _GDCLASS_RECREATE(m_class, m_inherits) \
136-
m_class *new_instance = (m_class *)memalloc(sizeof(m_class)); \
137-
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance }; \
138-
Wrapped::recreate_instance = &recreate_data; \
139-
memnew_placement(new_instance, m_class); \
140-
return new_instance;
141-
#else
142-
#define _GDCLASS_RECREATE(m_class, m_inherits) return nullptr;
143-
#endif
144-
145135
// Use this on top of your own classes.
146136
// Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes
147137
// every line of the macro different
@@ -226,15 +216,6 @@ public:
226216
return m_inherits::get_class_static(); \
227217
} \
228218
\
229-
static GDExtensionObjectPtr create(void *data) { \
230-
m_class *new_object = memnew(m_class); \
231-
return new_object->_owner; \
232-
} \
233-
\
234-
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
235-
_GDCLASS_RECREATE(m_class, m_inherits); \
236-
} \
237-
\
238219
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \
239220
if (p_instance && m_class::_get_notification()) { \
240221
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
@@ -437,14 +418,6 @@ public:
437418
return m_inherits::get_class_static(); \
438419
} \
439420
\
440-
static GDExtensionObjectPtr create(void *data) { \
441-
return nullptr; \
442-
} \
443-
\
444-
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
445-
return nullptr; \
446-
} \
447-
\
448421
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
449422
} \
450423
\

include/godot_cpp/core/class_db.hpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,33 @@ class ClassDB {
112112
template <class T, bool is_abstract>
113113
static void _register_class(bool p_virtual = false, bool p_exposed = true);
114114

115+
template <class T>
116+
static GDExtensionObjectPtr _create_instance_func(void *data) {
117+
if constexpr (!std::is_abstract_v<T>) {
118+
T *new_object = memnew(T);
119+
return new_object->_owner;
120+
} else {
121+
return nullptr;
122+
}
123+
}
124+
125+
template <class T>
126+
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
127+
if constexpr (!std::is_abstract_v<T>) {
128+
#ifdef HOT_RELOAD_ENABLED
129+
T *new_instance = (T *)memalloc(sizeof(T));
130+
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance };
131+
Wrapped::recreate_instance = &recreate_data;
132+
memnew_placement(new_instance, T);
133+
return new_instance;
134+
#else
135+
return nullptr;
136+
#endif
137+
} else {
138+
return nullptr;
139+
}
140+
}
141+
115142
public:
116143
template <class T>
117144
static void register_class(bool p_virtual = false);
@@ -202,9 +229,9 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
202229
T::to_string_bind, // GDExtensionClassToString to_string_func;
203230
nullptr, // GDExtensionClassReference reference_func;
204231
nullptr, // GDExtensionClassUnreference unreference_func;
205-
T::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
232+
&_create_instance_func<T>, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
206233
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
207-
T::recreate, // GDExtensionClassRecreateInstance recreate_instance_func;
234+
&_recreate_instance_func<T>, // GDExtensionClassRecreateInstance recreate_instance_func;
208235
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
209236
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
210237
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;

test/src/example.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,22 @@ class ExampleVirtual : public Object {
198198
static void _bind_methods() {}
199199
};
200200

201-
class ExampleAbstract : public Object {
202-
GDCLASS(ExampleAbstract, Object);
201+
class ExampleAbstractBase : public Object {
202+
GDCLASS(ExampleAbstractBase, Object);
203203

204204
protected:
205205
static void _bind_methods() {}
206+
207+
virtual int test_function() = 0;
208+
};
209+
210+
class ExampleConcrete : public ExampleAbstractBase {
211+
GDCLASS(ExampleConcrete, ExampleAbstractBase);
212+
213+
protected:
214+
static void _bind_methods() {}
215+
216+
virtual int test_function() override { return 25; }
206217
};
207218

208219
#endif // EXAMPLE_CLASS_H

test/src/register_types.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
2525
ClassDB::register_class<ExampleMin>();
2626
ClassDB::register_class<Example>();
2727
ClassDB::register_class<ExampleVirtual>(true);
28-
ClassDB::register_abstract_class<ExampleAbstract>();
28+
ClassDB::register_abstract_class<ExampleAbstractBase>();
29+
ClassDB::register_class<ExampleConcrete>();
2930
}
3031

3132
void uninitialize_example_module(ModuleInitializationLevel p_level) {

0 commit comments

Comments
 (0)