Merge pull request #1359 from Naros/GH-1287
Rework GDCLASS macro to allow abstract classespull/1367/head
commit
6c04514039
|
@ -48,6 +48,7 @@ typedef void GodotObject;
|
||||||
// Base for all engine classes, to contain the pointer to the engine instance.
|
// Base for all engine classes, to contain the pointer to the engine instance.
|
||||||
class Wrapped {
|
class Wrapped {
|
||||||
friend class GDExtensionBinding;
|
friend class GDExtensionBinding;
|
||||||
|
friend class ClassDB;
|
||||||
friend void postinitialize_handler(Wrapped *);
|
friend void postinitialize_handler(Wrapped *);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -131,17 +132,6 @@ struct EngineClassRegistration {
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
||||||
#ifdef HOT_RELOAD_ENABLED
|
|
||||||
#define _GDCLASS_RECREATE(m_class, m_inherits) \
|
|
||||||
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;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Use this on top of your own classes.
|
// 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
|
// 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
|
// every line of the macro different
|
||||||
|
@ -226,15 +216,6 @@ public:
|
||||||
return m_inherits::get_class_static(); \
|
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) { \
|
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \
|
||||||
if (p_instance && m_class::_get_notification()) { \
|
if (p_instance && m_class::_get_notification()) { \
|
||||||
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
|
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
|
||||||
|
@ -437,14 +418,6 @@ public:
|
||||||
return m_inherits::get_class_static(); \
|
return m_inherits::get_class_static(); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static GDExtensionObjectPtr create(void *data) { \
|
|
||||||
return nullptr; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
|
|
||||||
return nullptr; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
|
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
|
|
@ -112,6 +112,33 @@ private:
|
||||||
template <class T, bool is_abstract>
|
template <class T, bool is_abstract>
|
||||||
static void _register_class(bool p_virtual = false, bool p_exposed = true);
|
static void _register_class(bool p_virtual = false, bool p_exposed = true);
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static GDExtensionObjectPtr _create_instance_func(void *data) {
|
||||||
|
if constexpr (!std::is_abstract_v<T>) {
|
||||||
|
T *new_object = memnew(T);
|
||||||
|
return new_object->_owner;
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
|
||||||
|
if constexpr (!std::is_abstract_v<T>) {
|
||||||
|
#ifdef HOT_RELOAD_ENABLED
|
||||||
|
T *new_instance = (T *)memalloc(sizeof(T));
|
||||||
|
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance };
|
||||||
|
Wrapped::recreate_instance = &recreate_data;
|
||||||
|
memnew_placement(new_instance, T);
|
||||||
|
return new_instance;
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <class T>
|
template <class T>
|
||||||
static void register_class(bool p_virtual = false);
|
static void register_class(bool p_virtual = false);
|
||||||
|
@ -202,9 +229,9 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
||||||
T::to_string_bind, // GDExtensionClassToString to_string_func;
|
T::to_string_bind, // GDExtensionClassToString to_string_func;
|
||||||
nullptr, // GDExtensionClassReference reference_func;
|
nullptr, // GDExtensionClassReference reference_func;
|
||||||
nullptr, // GDExtensionClassUnreference unreference_func;
|
nullptr, // GDExtensionClassUnreference unreference_func;
|
||||||
T::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
&_create_instance_func<T>, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||||
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||||
T::recreate, // GDExtensionClassRecreateInstance recreate_instance_func;
|
&_recreate_instance_func<T>, // GDExtensionClassRecreateInstance recreate_instance_func;
|
||||||
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
|
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
|
||||||
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
||||||
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
|
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
|
||||||
|
|
|
@ -198,11 +198,22 @@ protected:
|
||||||
static void _bind_methods() {}
|
static void _bind_methods() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExampleAbstract : public Object {
|
class ExampleAbstractBase : public Object {
|
||||||
GDCLASS(ExampleAbstract, Object);
|
GDCLASS(ExampleAbstractBase, Object);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods() {}
|
static void _bind_methods() {}
|
||||||
|
|
||||||
|
virtual int test_function() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExampleConcrete : public ExampleAbstractBase {
|
||||||
|
GDCLASS(ExampleConcrete, ExampleAbstractBase);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {}
|
||||||
|
|
||||||
|
virtual int test_function() override { return 25; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // EXAMPLE_CLASS_H
|
#endif // EXAMPLE_CLASS_H
|
||||||
|
|
|
@ -25,7 +25,8 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
|
||||||
ClassDB::register_class<ExampleMin>();
|
ClassDB::register_class<ExampleMin>();
|
||||||
ClassDB::register_class<Example>();
|
ClassDB::register_class<Example>();
|
||||||
ClassDB::register_class<ExampleVirtual>(true);
|
ClassDB::register_class<ExampleVirtual>(true);
|
||||||
ClassDB::register_abstract_class<ExampleAbstract>();
|
ClassDB::register_abstract_class<ExampleAbstractBase>();
|
||||||
|
ClassDB::register_class<ExampleConcrete>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninitialize_example_module(ModuleInitializationLevel p_level) {
|
void uninitialize_example_module(ModuleInitializationLevel p_level) {
|
||||||
|
|
Loading…
Reference in New Issue