Skip to content

Commit

Permalink
Rework GDCLASS macro to allow pure virtual functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Naros committed Jan 12, 2024
1 parent 0ddef6e commit 16be4f8
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 13 deletions.
34 changes: 23 additions & 11 deletions include/godot_cpp/classes/wrapped.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,17 @@
namespace godot {

class ClassDB;
template <class T>
class ClassCreator;

typedef void GodotObject;

// Base for all engine classes, to contain the pointer to the engine instance.
class Wrapped {
friend class GDExtensionBinding;
friend void postinitialize_handler(Wrapped *);
template <class T>
friend class ClassCreator;

protected:
#ifdef HOT_RELOAD_ENABLED
Expand Down Expand Up @@ -132,16 +136,33 @@ struct EngineClassRegistration {
} // namespace godot

#ifdef HOT_RELOAD_ENABLED
#define _GDCLASS_RECREATE(m_class, m_inherits) \
#define _GDCLASS_RECREATE(m_class) \
m_class *new_instance = (m_class *)memalloc(sizeof(m_class)); \
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance }; \
Wrapped::recreate_instance = &recreate_data; \
memnew_placement(new_instance, m_class); \
return new_instance;
#else
#define _GDCLASS_RECREATE(m_class, m_inherits) return nullptr;
#define _GDCLASS_RECREATE(m_class) return nullptr;
#endif

namespace godot {

template <class T>
class ClassCreator {
public:
static GDExtensionObjectPtr create(void *data) {
T *new_object = memnew(T);
return new_object->_owner;
};

static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) {
_GDCLASS_RECREATE(T)
}
};

} // namespace godot

// Use this on top of your own classes.
// Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes
// every line of the macro different
Expand Down Expand Up @@ -226,15 +247,6 @@ public:
return m_inherits::get_class_static(); \
} \
\
static GDExtensionObjectPtr create(void *data) { \
m_class *new_object = memnew(m_class); \
return new_object->_owner; \
} \
\
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
_GDCLASS_RECREATE(m_class, m_inherits); \
} \
\
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \
if (p_instance && m_class::_get_notification()) { \
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
Expand Down
4 changes: 2 additions & 2 deletions include/godot_cpp/core/class_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
T::to_string_bind, // GDExtensionClassToString to_string_func;
nullptr, // GDExtensionClassReference reference_func;
nullptr, // GDExtensionClassUnreference unreference_func;
T::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
ClassCreator<T>::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
T::recreate, // GDExtensionClassRecreateInstance recreate_instance_func;
ClassCreator<T>::recreate, // GDExtensionClassRecreateInstance recreate_instance_func;
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
Expand Down

0 comments on commit 16be4f8

Please sign in to comment.