diff options
| author | Gilles Roudière <gilles.roudiere@gmail.com> | 2021-11-30 14:00:13 +0100 |
|---|---|---|
| committer | Gilles Roudière <gilles.roudiere@gmail.com> | 2021-12-03 15:37:49 +0100 |
| commit | 3fcb8a4d1e2789739ad3f520f65ab4ece1df1d9a (patch) | |
| tree | 5985eeacd444c6f124a42c98bba0c1db6eedf8f4 /include/godot_cpp | |
| parent | 50512f0dee7c95ae9e680133d441e7be49df5aac (diff) | |
| download | redot-cpp-3fcb8a4d1e2789739ad3f520f65ab4ece1df1d9a.tar.gz | |
Make extension instances create the corresponding godot object in their constructor
Diffstat (limited to 'include/godot_cpp')
| -rw-r--r-- | include/godot_cpp/classes/wrapped.hpp | 279 | ||||
| -rw-r--r-- | include/godot_cpp/core/class_db.hpp | 3 | ||||
| -rw-r--r-- | include/godot_cpp/core/memory.hpp | 21 | ||||
| -rw-r--r-- | include/godot_cpp/godot.hpp | 3 |
4 files changed, 140 insertions, 166 deletions
diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index c131f7b..80a9ef1 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -34,6 +34,7 @@ #include <godot_cpp/core/memory.hpp> #include <godot_cpp/godot.hpp> + namespace godot { typedef void GodotObject; @@ -41,46 +42,22 @@ typedef void GodotObject; // Base for all engine classes, to contain the pointer to the engine instance. class Wrapped { friend class GDExtensionBinding; - - // Private constructor, this should not be created directly by users. - Wrapped(GodotObject *p_owner) : - _owner(p_owner) {} + friend void postinitialize_handler(Wrapped *); protected: - Wrapped() = default; + virtual const char *_get_class() const = 0; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. + virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const = 0; + + void _postinitialize(); + + Wrapped(const char *p_godot_class); + Wrapped(GodotObject *p_godot_object); public: // Must be public but you should not touch this. GodotObject *_owner = nullptr; - - static Wrapped *_new() { - return nullptr; - } }; -namespace internal { - -template <class T, class Enable = void> -struct Creator { - static T *_new() { return nullptr; } -}; - -template <class T> -struct Creator<T, typename std::enable_if<std::is_base_of_v<godot::Wrapped, T>>::type> { - static T *_new() { return T::_new(); } -}; - -// template <class T> -// struct Creator<T, std::false_type> { -// }; - -// template <class T> -// struct Creator<T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool>> { -// static T *_new() { return T::_new(); } -// }; - -}; // namespace internal - } // namespace godot #ifdef DEBUG_ENABLED @@ -94,126 +71,126 @@ struct Creator<T, typename std::enable_if<std::is_base_of_v<godot::Wrapped, T>>: #define CHECK_CLASS_CONSTRUCTOR(m_constructor, m_class) #endif -#define GDCLASS(m_class, m_inherits) \ -private: \ - friend class ClassDB; \ - \ - using SelfType = m_class; \ - \ -protected: \ - static void (*_get_bind_methods())() { \ - return &m_class::_bind_methods; \ - } \ - \ - template <class T> \ - static void register_virtuals() { \ - m_inherits::register_virtuals<T>(); \ - } \ - \ -public: \ - static void initialize_class() { \ - static bool initialized = false; \ - if (initialized) { \ - return; \ - } \ - m_inherits::initialize_class(); \ - if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \ - _bind_methods(); \ - m_inherits::register_virtuals<m_class>(); \ - } \ - initialized = true; \ - } \ - \ - static const char *get_class_static() { \ - return #m_class; \ - } \ - \ - static const char *get_parent_class_static() { \ - return #m_inherits; \ - } \ - \ - static GDExtensionClassInstancePtr create(void *data) { \ - return reinterpret_cast<GDExtensionClassInstancePtr>(new ("") m_class); \ - } \ - \ - static void free(void *data, GDExtensionClassInstancePtr ptr) { \ - if (ptr) { \ - m_class *cls = reinterpret_cast<m_class *>(ptr); \ - cls->~m_class(); \ - ::godot::Memory::free_static(cls); \ - } \ - } \ - \ - static void set_object_instance(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance) { \ - godot::internal::gdn_interface->object_set_instance_binding(p_object_instance, godot::internal::token, p_instance, &m_class::___binding_callbacks); \ - reinterpret_cast<m_class *>(p_instance)->_owner = reinterpret_cast<godot::GodotObject *>(p_object_instance); \ - } \ - \ - static void *___binding_create_callback(void *p_token, void *p_instance) { \ - return nullptr; \ - } \ - static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \ - } \ - static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) { \ - return true; \ - } \ - static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = { \ - ___binding_create_callback, \ - ___binding_free_callback, \ - ___binding_reference_callback, \ - }; \ - \ - static m_class *_new() { \ - static GDNativeExtensionPtr ___extension = nullptr; \ - static GDNativeClassConstructor ___constructor = godot::internal::gdn_interface->classdb_get_constructor(#m_class, &___extension); \ - CHECK_CLASS_CONSTRUCTOR(___constructor, m_class); \ - GDNativeObjectPtr obj = godot::internal::gdn_interface->classdb_construct_object(___constructor, ___extension); \ - return reinterpret_cast<m_class *>(godot::internal::gdn_interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \ - } \ - \ -private: +#define GDCLASS(m_class, m_inherits) \ +private: \ + void operator=(const m_class &p_rval) {} \ + friend class ClassDB; \ + \ + using SelfType = m_class; \ + \ +protected: \ + virtual const char *_get_class() const override { \ + return get_class_static(); \ + } \ + \ + virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override { \ + return &___binding_callbacks; \ + } \ + \ + static void (*_get_bind_methods())() { \ + return &m_class::_bind_methods; \ + } \ + \ + template <class T> \ + static void register_virtuals() { \ + m_inherits::register_virtuals<T>(); \ + } \ + \ +public: \ + static void initialize_class() { \ + static bool initialized = false; \ + if (initialized) { \ + return; \ + } \ + m_inherits::initialize_class(); \ + if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \ + _bind_methods(); \ + m_inherits::register_virtuals<m_class>(); \ + } \ + initialized = true; \ + } \ + \ + static const char *get_class_static() { \ + return #m_class; \ + } \ + \ + static const char *get_parent_class_static() { \ + return #m_inherits; \ + } \ + \ + static GDNativeObjectPtr create(void *data) { \ + m_class *new_object = memnew(m_class); \ + return new_object->_owner; \ + } \ + \ + static void free(void *data, GDExtensionClassInstancePtr ptr) { \ + if (ptr) { \ + m_class *cls = reinterpret_cast<m_class *>(ptr); \ + cls->~m_class(); \ + ::godot::Memory::free_static(cls); \ + } \ + } \ + \ + static void *___binding_create_callback(void *p_token, void *p_instance) { \ + return nullptr; \ + } \ + static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \ + } \ + static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) { \ + return true; \ + } \ + static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = { \ + ___binding_create_callback, \ + ___binding_free_callback, \ + ___binding_reference_callback, \ + }; // Don't use this for your classes, use GDCLASS() instead. -#define GDNATIVE_CLASS(m_class, m_inherits) \ -protected: \ - static void (*_get_bind_methods())() { \ - return nullptr; \ - } \ - \ -public: \ - static void initialize_class() {} \ - \ - static const char *get_class_static() { \ - return #m_class; \ - } \ - \ - static const char *get_parent_class_static() { \ - return #m_inherits; \ - } \ - \ - static void *___binding_create_callback(void *p_token, void *p_instance) { \ - m_class *obj = new ("") m_class; \ - obj->_owner = (godot::GodotObject *)p_instance; \ - return obj; \ - } \ - static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \ - Memory::free_static(reinterpret_cast<m_class *>(p_binding)); \ - } \ - static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) { \ - return true; \ - } \ - static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = { \ - ___binding_create_callback, \ - ___binding_free_callback, \ - ___binding_reference_callback, \ - }; \ - static m_class *_new() { \ - static GDNativeClassConstructor ___constructor = godot::internal::gdn_interface->classdb_get_constructor(#m_class, nullptr); \ - CHECK_CLASS_CONSTRUCTOR(___constructor, m_class); \ - GDNativeObjectPtr obj = ___constructor(); \ - return reinterpret_cast<m_class *>(godot::internal::gdn_interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \ - } \ - \ -private: +#define GDNATIVE_CLASS(m_class, m_inherits) \ +private: \ + void operator=(const m_class &p_rval) {} \ + \ +protected: \ + virtual const char *_get_class() const override { \ + return get_class_static(); \ + } \ + \ + virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override { \ + return &___binding_callbacks; \ + } \ + \ + m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \ + m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \ + \ + static void (*_get_bind_methods())() { \ + return nullptr; \ + } \ + \ +public: \ + static void initialize_class() {} \ + \ + static const char *get_class_static() { \ + return #m_class; \ + } \ + \ + static const char *get_parent_class_static() { \ + return #m_inherits; \ + } \ + \ + static void *___binding_create_callback(void *p_token, void *p_instance) { \ + return memnew(m_class((GodotObject *)p_instance)); \ + } \ + static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \ + Memory::free_static(reinterpret_cast<m_class *>(p_binding)); \ + } \ + static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) { \ + return true; \ + } \ + static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = { \ + ___binding_create_callback, \ + ___binding_free_callback, \ + ___binding_reference_callback, \ + }; \ + m_class() : m_class(#m_class) {} #endif // ! GODOT_CPP_WRAPPED_HPP diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index f7233f3..37bc142 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -158,9 +158,8 @@ void ClassDB::register_class() { nullptr, // GDNativeExtensionClassUnreference T::create, // GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ T::free, // GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ - T::set_object_instance, // GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */ &ClassDB::get_virtual_func, // GDNativeExtensionClassGetVirtual get_virtual_func; - (void *)cl.name, //void *class_userdata; + (void *)cl.name, // void *class_userdata; }; internal::gdn_interface->classdb_register_extension_class(internal::library, cl.name, cl.parent_name, &class_info); diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp index 73af71f..9431d4d 100644 --- a/include/godot_cpp/core/memory.hpp +++ b/include/godot_cpp/core/memory.hpp @@ -68,16 +68,17 @@ public: static void free_static(void *p_ptr); }; -#define memnew(m_v) \ - ([&]() { \ - if constexpr (std::is_base_of<godot::Object, decltype(m_v)>::value) { \ - return godot::internal::Creator<decltype(m_v)>::_new(); \ - } else { \ - return new ("") m_v; \ - } \ - }()) - -#define memnew_placement(m_placement, m_class) (new (m_placement, sizeof(m_class), "") m_class) +_ALWAYS_INLINE_ void postinitialize_handler(void *) {} + +template <class T> +_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { + postinitialize_handler(p_obj); + return p_obj; +} + +#define memnew(m_class) _post_initialize(new ("") m_class) + +#define memnew_placement(m_placement, m_class) _post_initialize(new (m_placement, sizeof(m_class), "") m_class) template <class T> void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = 0) { diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index 733892d..5ece787 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -55,9 +55,6 @@ public: static void initialize_level(void *userdata, GDNativeInitializationLevel p_level); static void deinitialize_level(void *userdata, GDNativeInitializationLevel p_level); - static void *create_instance_callback(void *p_token, void *p_instance); - static void free_instance_callback(void *p_token, void *p_instance, void *p_binding); - class InitObject { const GDNativeInterface *gdn_interface; const GDNativeExtensionClassLibraryPtr library; |
