summaryrefslogtreecommitdiffstats
path: root/include/godot_cpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/godot_cpp')
-rw-r--r--include/godot_cpp/classes/ref.hpp2
-rw-r--r--include/godot_cpp/classes/wrapped.hpp263
-rw-r--r--include/godot_cpp/core/memory.hpp22
-rw-r--r--include/godot_cpp/core/method_bind.hpp2
4 files changed, 175 insertions, 114 deletions
diff --git a/include/godot_cpp/classes/ref.hpp b/include/godot_cpp/classes/ref.hpp
index 2140ef3..2ca5f83 100644
--- a/include/godot_cpp/classes/ref.hpp
+++ b/include/godot_cpp/classes/ref.hpp
@@ -199,7 +199,7 @@ public:
}
void instantiate() {
- ref(memnew(T));
+ ref(memnew(T()));
}
Ref() {}
diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp
index 8402e9c..2a0422a 100644
--- a/include/godot_cpp/classes/wrapped.hpp
+++ b/include/godot_cpp/classes/wrapped.hpp
@@ -33,10 +33,8 @@
#include <godot_cpp/core/memory.hpp>
+#include <godot_cpp/godot.hpp>
namespace godot {
-namespace internal {
-struct empty_constructor {};
-} // namespace internal
typedef void GodotObject;
@@ -50,124 +48,169 @@ class Wrapped {
protected:
Wrapped() = default;
- Wrapped(internal::empty_constructor empty) {}
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
-#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; \
- } \
- \
- m_class(godot::GodotObject *owner) : m_inherits(godot::internal::empty_constructor()) { \
- _owner = owner; \
- } \
- \
- m_class(godot::internal::empty_constructor empty) : m_inherits(empty) {} \
- \
- 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 (GDExtensionClassInstancePtr)godot::Memory::alloc_static(sizeof(m_class)); \
- } \
- \
- static void free(void *data, GDExtensionClassInstancePtr ptr) { \
- godot::memdelete(reinterpret_cast<m_class *>(ptr)); \
- } \
- \
- static void set_object_instance(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance) { \
- memnew_placement((void *)p_instance, m_class((godot::GodotObject *)p_object_instance)); \
- } \
- \
- static void *___binding_create_callback(void *p_token, void *p_instance) { \
- return memnew(m_class((godot::GodotObject *)p_instance)); \
- } \
- static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
- memdelete((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, \
- }; \
- \
+#ifdef DEBUG_ENABLED
+#define CHECK_CLASS_CONSTRUCTOR(m_constructor, m_class) \
+ if (unlikely(!m_constructor)) { \
+ ERR_PRINT_ONCE("Constructor for class " #m_class "not found. Likely wasn't registered in ClassDB."); \
+ return nullptr; \
+ } else \
+ ((void)0)
+#else
+#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) { \
+ Memory::free_static(reinterpret_cast<m_class *>(ptr)); \
+ } \
+ \
+ static void set_object_instance(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance) { \
+ reinterpret_cast<m_class *>(p_instance)->_owner = reinterpret_cast<GodotObject *>(p_object_instance); \
+ } \
+ \
+ static void *___binding_create_callback(void *p_token, void *p_instance) { \
+ m_class *result = new ("") m_class; \
+ result->_owner = reinterpret_cast<godot::GodotObject *>(p_instance); \
+ return result; \
+ } \
+ 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::interface->classdb_get_constructor(#m_class); \
+ CHECK_CLASS_CONSTRUCTOR(___constructor, m_class); \
+ GDNativeObjectPtr obj = ___constructor(); \
+ return reinterpret_cast<m_class *>(godot::internal::interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \
+ } \
+ \
private:
// 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; \
- } \
- m_class(godot::internal::empty_constructor empty) : m_inherits(empty) {} \
- \
-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 = memnew(m_class(godot::internal::empty_constructor())); \
- obj->_owner = (godot::GodotObject *)p_instance; \
- return obj; \
- } \
- static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
- memdelete((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, \
- }; \
- \
+#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::interface->classdb_get_constructor(#m_class); \
+ CHECK_CLASS_CONSTRUCTOR(___constructor, m_class); \
+ GDNativeObjectPtr obj = ___constructor(); \
+ return reinterpret_cast<m_class *>(godot::internal::interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \
+ } \
+ \
private:
#endif // ! GODOT_CPP_WRAPPED_HPP
diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp
index d95ca40..c493e89 100644
--- a/include/godot_cpp/core/memory.hpp
+++ b/include/godot_cpp/core/memory.hpp
@@ -36,6 +36,9 @@
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/godot.hpp>
+
+#include <type_traits>
void *operator new(size_t p_size, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
@@ -54,6 +57,8 @@ void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_d
namespace godot {
+class Wrapped;
+
class Memory {
Memory();
@@ -63,11 +68,19 @@ public:
static void free_static(void *p_ptr);
};
-#define memnew(m_v) (new ("") m_v)
+#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)
template <class T>
-void memdelete(T *p_class) {
+void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = 0) {
if (!__has_trivial_destructor(T)) {
p_class->~T();
}
@@ -75,6 +88,11 @@ void memdelete(T *p_class) {
Memory::free_static(p_class);
}
+template <class T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true>
+void memdelete(T *p_class) {
+ godot::internal::interface->object_destroy(p_class->_owner);
+}
+
#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count)
template <typename T>
diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp
index 2c3e7b3..176a53c 100644
--- a/include/godot_cpp/core/method_bind.hpp
+++ b/include/godot_cpp/core/method_bind.hpp
@@ -194,7 +194,7 @@ public:
template <class T>
MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
- MethodBindVarArg<T> *a = memnew((MethodBindVarArg<T>));
+ MethodBindVarArg<T> *a = memnew(MethodBindVarArg<T>());
a->set_method(p_method);
a->set_method_info(p_info, p_return_nil_is_variant);
a->set_instance_class(T::get_class_static());