Add support for `_notification`, `_set`, `_get`, `_get_property_list`, `_property_can_revert`, `_property_get_revert`, and `_to_string` methods.
parent
f454253005
commit
270ad28931
|
@ -33,6 +33,10 @@
|
||||||
|
|
||||||
#include <godot_cpp/core/memory.hpp>
|
#include <godot_cpp/core/memory.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/core/property_info.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/templates/list.hpp>
|
||||||
|
|
||||||
#include <godot_cpp/godot.hpp>
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
@ -48,6 +52,26 @@ protected:
|
||||||
virtual const char *_get_extension_class() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
|
virtual const char *_get_extension_class() const; // 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;
|
virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const = 0;
|
||||||
|
|
||||||
|
void _notification(int p_what){};
|
||||||
|
bool _set(const StringName &p_name, const Variant &p_property) { return false; };
|
||||||
|
bool _get(const StringName &p_name, Variant &r_property) const { return false; };
|
||||||
|
void _get_property_list(List<PropertyInfo> *p_list) const {};
|
||||||
|
bool _property_can_revert(const StringName &p_name) const { return false; };
|
||||||
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; };
|
||||||
|
String _to_string() const { return "[" + String(get_class_static()) + ":" + itos(get_instance_id()) + "]"; }
|
||||||
|
|
||||||
|
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what) {}
|
||||||
|
static GDNativeBool set_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value) { return false; }
|
||||||
|
static GDNativeBool get_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret) { return false; }
|
||||||
|
static const GDNativePropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { return nullptr; }
|
||||||
|
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list) {}
|
||||||
|
static GDNativeBool property_can_revert_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name) { return false; }
|
||||||
|
static GDNativeBool property_get_revert_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret) { return false; }
|
||||||
|
static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr r_out) {}
|
||||||
|
|
||||||
|
GDNativePropertyInfo *plist = nullptr;
|
||||||
|
uint32_t plist_size = 0;
|
||||||
|
|
||||||
void _postinitialize();
|
void _postinitialize();
|
||||||
|
|
||||||
Wrapped(const char *p_godot_class);
|
Wrapped(const char *p_godot_class);
|
||||||
|
@ -58,82 +82,231 @@ public:
|
||||||
return "Wrapped";
|
return "Wrapped";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t get_instance_id() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static _FORCE_INLINE_ char *_alloc_and_copy_cstr(const char *p_str) {
|
||||||
|
size_t size = strlen(p_str) + 1;
|
||||||
|
char *ret = reinterpret_cast<char *>(memalloc(size));
|
||||||
|
memcpy(ret, p_str, size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Must be public but you should not touch this.
|
// Must be public but you should not touch this.
|
||||||
GodotObject *_owner = nullptr;
|
GodotObject *_owner = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
||||||
#define GDCLASS(m_class, m_inherits) \
|
#define GDCLASS(m_class, m_inherits) \
|
||||||
private: \
|
private: \
|
||||||
void operator=(const m_class &p_rval) {} \
|
void operator=(const m_class &p_rval) {} \
|
||||||
friend class ::godot::ClassDB; \
|
friend class ::godot::ClassDB; \
|
||||||
\
|
\
|
||||||
protected: \
|
protected: \
|
||||||
virtual const char *_get_extension_class() const override { \
|
virtual const char *_get_extension_class() const override { \
|
||||||
return get_class_static(); \
|
return get_class_static(); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
||||||
return &___binding_callbacks; \
|
return &___binding_callbacks; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static void (*_get_bind_methods())() { \
|
static void (*_get_bind_methods())() { \
|
||||||
return &m_class::_bind_methods; \
|
return &m_class::_bind_methods; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
template <class T> \
|
static void (Wrapped::*_get_notification())(int) { \
|
||||||
static void register_virtuals() { \
|
return (void(Wrapped::*)(int)) & m_class::_notification; \
|
||||||
m_inherits::register_virtuals<T>(); \
|
} \
|
||||||
} \
|
\
|
||||||
\
|
static bool (Wrapped::*_get_set())(const StringName &p_name, const Variant &p_property) { \
|
||||||
public: \
|
return (bool(Wrapped::*)(const StringName &p_name, const Variant &p_property)) & m_class::_set; \
|
||||||
static void initialize_class() { \
|
} \
|
||||||
static bool initialized = false; \
|
\
|
||||||
if (initialized) { \
|
static bool (Wrapped::*_get_get())(const StringName &p_name, Variant &r_ret) { \
|
||||||
return; \
|
return (bool(Wrapped::*)(const StringName &p_name, Variant &r_ret)) & m_class::_set; \
|
||||||
} \
|
} \
|
||||||
m_inherits::initialize_class(); \
|
\
|
||||||
if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \
|
static void (Wrapped::*_get_get_property_list())(List<PropertyInfo> * p_list) { \
|
||||||
_bind_methods(); \
|
return (void(Wrapped::*)(List<PropertyInfo> * p_list)) & m_class::_get_property_list; \
|
||||||
m_inherits::register_virtuals<m_class>(); \
|
} \
|
||||||
} \
|
\
|
||||||
initialized = true; \
|
static bool (Wrapped::*_get_property_can_revert())(const StringName &p_name) { \
|
||||||
} \
|
return (bool(Wrapped::*)(const StringName &p_name)) & m_class::_property_can_revert; \
|
||||||
\
|
} \
|
||||||
static const char *get_class_static() { \
|
\
|
||||||
return #m_class; \
|
static bool (Wrapped::*_get_property_get_revert())(const StringName &p_name, Variant &) { \
|
||||||
} \
|
return (bool(Wrapped::*)(const StringName &p_name, Variant &)) & m_class::_property_get_revert; \
|
||||||
\
|
} \
|
||||||
static const char *get_parent_class_static() { \
|
\
|
||||||
return m_inherits::get_class_static(); \
|
static String (Wrapped::*_get_to_string())() { \
|
||||||
} \
|
return (String(Wrapped::*)()) & m_class::_to_string; \
|
||||||
\
|
} \
|
||||||
static GDNativeObjectPtr create(void *data) { \
|
\
|
||||||
m_class *new_object = memnew(m_class); \
|
template <class T> \
|
||||||
return new_object->_owner; \
|
static void register_virtuals() { \
|
||||||
} \
|
m_inherits::register_virtuals<T>(); \
|
||||||
\
|
} \
|
||||||
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
|
\
|
||||||
if (ptr) { \
|
public: \
|
||||||
m_class *cls = reinterpret_cast<m_class *>(ptr); \
|
static void initialize_class() { \
|
||||||
cls->~m_class(); \
|
static bool initialized = false; \
|
||||||
::godot::Memory::free_static(cls); \
|
if (initialized) { \
|
||||||
} \
|
return; \
|
||||||
} \
|
} \
|
||||||
\
|
m_inherits::initialize_class(); \
|
||||||
static void *___binding_create_callback(void *p_token, void *p_instance) { \
|
if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \
|
||||||
return nullptr; \
|
_bind_methods(); \
|
||||||
} \
|
m_inherits::register_virtuals<m_class>(); \
|
||||||
static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
|
} \
|
||||||
} \
|
initialized = true; \
|
||||||
static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) { \
|
} \
|
||||||
return true; \
|
\
|
||||||
} \
|
static const char *get_class_static() { \
|
||||||
static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = { \
|
return #m_class; \
|
||||||
___binding_create_callback, \
|
} \
|
||||||
___binding_free_callback, \
|
\
|
||||||
___binding_reference_callback, \
|
static const char *get_parent_class_static() { \
|
||||||
|
return m_inherits::get_class_static(); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static GDNativeObjectPtr create(void *data) { \
|
||||||
|
m_class *new_object = memnew(m_class); \
|
||||||
|
return new_object->_owner; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what) { \
|
||||||
|
if (p_instance && m_class::_get_notification()) { \
|
||||||
|
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
return cls->_notification(p_what); \
|
||||||
|
} \
|
||||||
|
m_inherits::notification_bind(p_instance, p_what); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static GDNativeBool set_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value) { \
|
||||||
|
if (p_instance && m_class::_get_set()) { \
|
||||||
|
if (m_class::_get_set() != m_inherits::_get_set()) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
return cls->_set(*reinterpret_cast<const StringName *>(p_name), *reinterpret_cast<const Variant *>(p_value)); \
|
||||||
|
} \
|
||||||
|
return m_inherits::set_bind(p_instance, p_name, p_value); \
|
||||||
|
} \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static GDNativeBool get_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret) { \
|
||||||
|
if (p_instance && m_class::_get_get()) { \
|
||||||
|
if (m_class::_get_get() != m_inherits::_get_get()) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
return cls->_get(*reinterpret_cast<const StringName *>(p_name), *reinterpret_cast<Variant *>(r_ret)); \
|
||||||
|
} \
|
||||||
|
return m_inherits::get_bind(p_instance, p_name, r_ret); \
|
||||||
|
} \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static const GDNativePropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { \
|
||||||
|
if (p_instance && m_class::_get_get_property_list()) { \
|
||||||
|
if (m_class::_get_get_property_list() != m_inherits::_get_get_property_list()) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
List<PropertyInfo> list; \
|
||||||
|
cls->_get_property_list(&list); \
|
||||||
|
ERR_FAIL_COND_V_MSG(cls->plist != nullptr || cls->plist_size != 0, nullptr, "Internal error, property list was not freed by engine!"); \
|
||||||
|
cls->plist = reinterpret_cast<GDNativePropertyInfo *>(memalloc(sizeof(GDNativePropertyInfo) * list.size())); \
|
||||||
|
cls->plist_size = 0; \
|
||||||
|
for (const PropertyInfo &E : list) { \
|
||||||
|
cls->plist[cls->plist_size].type = E.type; \
|
||||||
|
cls->plist[cls->plist_size].name = _alloc_and_copy_cstr(E.name); \
|
||||||
|
cls->plist[cls->plist_size].hint = E.hint; \
|
||||||
|
cls->plist[cls->plist_size].hint_string = _alloc_and_copy_cstr(E.hint_string); \
|
||||||
|
cls->plist[cls->plist_size].class_name = _alloc_and_copy_cstr(E.class_name); \
|
||||||
|
cls->plist[cls->plist_size].usage = E.usage; \
|
||||||
|
cls->plist_size++; \
|
||||||
|
} \
|
||||||
|
if (r_count) \
|
||||||
|
*r_count = cls->plist_size; \
|
||||||
|
return cls->plist; \
|
||||||
|
} \
|
||||||
|
return m_inherits::get_property_list_bind(p_instance, r_count); \
|
||||||
|
} \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list) { \
|
||||||
|
if (p_instance) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
ERR_FAIL_COND_MSG(cls->plist == nullptr, "Internal error, property list double free!"); \
|
||||||
|
for (size_t i = 0; i < cls->plist_size; i++) { \
|
||||||
|
memfree(const_cast<char *>(cls->plist[i].name)); \
|
||||||
|
memfree(const_cast<char *>(cls->plist[i].class_name)); \
|
||||||
|
memfree(const_cast<char *>(cls->plist[i].hint_string)); \
|
||||||
|
} \
|
||||||
|
memfree(cls->plist); \
|
||||||
|
cls->plist = nullptr; \
|
||||||
|
cls->plist_size = 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static GDNativeBool property_can_revert_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name) { \
|
||||||
|
if (p_instance && m_class::_get_property_can_revert()) { \
|
||||||
|
if (m_class::_get_property_can_revert() != m_inherits::_get_property_can_revert()) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
return cls->_property_can_revert(*reinterpret_cast<const StringName *>(p_name)); \
|
||||||
|
} \
|
||||||
|
return m_inherits::property_can_revert_bind(p_instance, p_name); \
|
||||||
|
} \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static GDNativeBool property_get_revert_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret) { \
|
||||||
|
if (p_instance && m_class::_get_property_get_revert()) { \
|
||||||
|
if (m_class::_get_property_get_revert() != m_inherits::_get_property_get_revert()) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
return cls->_property_get_revert(*reinterpret_cast<const StringName *>(p_name), *reinterpret_cast<Variant *>(r_ret)); \
|
||||||
|
} \
|
||||||
|
return m_inherits::property_get_revert_bind(p_instance, p_name, r_ret); \
|
||||||
|
} \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr r_out) { \
|
||||||
|
if (p_instance && m_class::_get_to_string()) { \
|
||||||
|
if (m_class::_get_to_string() != m_inherits::_get_to_string()) { \
|
||||||
|
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||||
|
*reinterpret_cast<String *>(r_out) = cls->_to_string(); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
m_inherits::to_string_bind(p_instance, r_out); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
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.
|
// Don't use this for your classes, use GDCLASS() instead.
|
||||||
|
@ -153,6 +326,34 @@ protected:
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
static void (Wrapped::*_get_notification())(int) { \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static bool (Wrapped::*_get_set())(const StringName &p_name, const Variant &p_property) { \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static bool (Wrapped::*_get_get())(const StringName &p_name, Variant &r_ret) { \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void (Wrapped::*_get_get_property_list())(List<PropertyInfo> * p_list) { \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static bool (Wrapped::*_get_property_can_revert())(const StringName &p_name) { \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static bool (Wrapped::*_get_property_get_revert())(const StringName &p_name, Variant &) { \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static String (Wrapped::*_get_to_string())() { \
|
||||||
|
return nullptr; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
public: \
|
public: \
|
||||||
static void initialize_class() {} \
|
static void initialize_class() {} \
|
||||||
\
|
\
|
||||||
|
|
|
@ -158,14 +158,14 @@ void ClassDB::register_class() {
|
||||||
|
|
||||||
// Register this class with Godot
|
// Register this class with Godot
|
||||||
GDNativeExtensionClassCreationInfo class_info = {
|
GDNativeExtensionClassCreationInfo class_info = {
|
||||||
nullptr, // GDNativeExtensionClassSet set_func;
|
T::set_bind, // GDNativeExtensionClassSet set_func;
|
||||||
nullptr, // GDNativeExtensionClassGet get_func;
|
T::get_bind, // GDNativeExtensionClassGet get_func;
|
||||||
nullptr, // GDNativeExtensionClassGetPropertyList get_property_list_func;
|
T::get_property_list_bind, // GDNativeExtensionClassGetPropertyList get_property_list_func;
|
||||||
nullptr, // GDNativeExtensionClassFreePropertyList free_property_list_func;
|
T::free_property_list_bind, // GDNativeExtensionClassFreePropertyList free_property_list_func;
|
||||||
nullptr, // GDNativeExtensionClassPropertyCanRevert property_can_revert_func;
|
T::property_can_revert_bind, // GDNativeExtensionClassPropertyCanRevert property_can_revert_func;
|
||||||
nullptr, // GDNativeExtensionClassPropertyGetRevert property_get_revert_func;
|
T::property_get_revert_bind, // GDNativeExtensionClassPropertyGetRevert property_get_revert_func;
|
||||||
nullptr, // GDNativeExtensionClassNotification notification_func;
|
T::notification_bind, // GDNativeExtensionClassNotification notification_func;
|
||||||
nullptr, // GDNativeExtensionClassToString to_string_func;
|
T::to_string_bind, // GDNativeExtensionClassToString to_string_func;
|
||||||
nullptr, // GDNativeExtensionClassReference reference_func;
|
nullptr, // GDNativeExtensionClassReference reference_func;
|
||||||
nullptr, // GDNativeExtensionClassUnreference unreference_func;
|
nullptr, // GDNativeExtensionClassUnreference unreference_func;
|
||||||
T::create, // GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
T::create, // GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#if !defined(GDN_EXPORT)
|
#if !defined(GDN_EXPORT)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
|
@ -287,7 +287,7 @@ protected:
|
||||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||||
call_get_argument_type_info<P...>(p_arg, pi);
|
call_get_argument_type_info<P...>(p_arg, pi);
|
||||||
} else {
|
} else {
|
||||||
pi = PropertyInfo();
|
pi = GDNativePropertyInfo();
|
||||||
}
|
}
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
@ -363,7 +363,7 @@ protected:
|
||||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||||
call_get_argument_type_info<P...>(p_arg, pi);
|
call_get_argument_type_info<P...>(p_arg, pi);
|
||||||
} else {
|
} else {
|
||||||
pi = PropertyInfo();
|
pi = GDNativePropertyInfo();
|
||||||
}
|
}
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
@ -603,7 +603,7 @@ protected:
|
||||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||||
call_get_argument_type_info<P...>(p_arg, pi);
|
call_get_argument_type_info<P...>(p_arg, pi);
|
||||||
} else {
|
} else {
|
||||||
pi = PropertyInfo();
|
pi = GDNativePropertyInfo();
|
||||||
}
|
}
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,9 @@
|
||||||
#define GODOT_OBJECT_HPP
|
#define GODOT_OBJECT_HPP
|
||||||
|
|
||||||
#include <godot_cpp/core/defs.hpp>
|
#include <godot_cpp/core/defs.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/core/property_info.hpp>
|
||||||
|
|
||||||
#include <godot_cpp/variant/variant.hpp>
|
#include <godot_cpp/variant/variant.hpp>
|
||||||
|
|
||||||
#include <godot_cpp/classes/object.hpp>
|
#include <godot_cpp/classes/object.hpp>
|
||||||
|
@ -49,44 +52,6 @@
|
||||||
|
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
|
||||||
struct PropertyInfo {
|
|
||||||
Variant::Type type = Variant::NIL;
|
|
||||||
const char *name = nullptr;
|
|
||||||
const char *class_name = nullptr;
|
|
||||||
uint32_t hint = 0;
|
|
||||||
const char *hint_string = nullptr;
|
|
||||||
uint32_t usage = 7;
|
|
||||||
|
|
||||||
operator GDNativePropertyInfo() const {
|
|
||||||
GDNativePropertyInfo info;
|
|
||||||
info.type = type;
|
|
||||||
info.name = name;
|
|
||||||
info.hint = hint;
|
|
||||||
info.hint_string = hint_string;
|
|
||||||
info.class_name = class_name;
|
|
||||||
info.usage = usage;
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyInfo() = default;
|
|
||||||
|
|
||||||
PropertyInfo(Variant::Type p_type, const char *p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const char *p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const char *p_class_name = "") :
|
|
||||||
type(p_type),
|
|
||||||
name(p_name),
|
|
||||||
hint(p_hint),
|
|
||||||
hint_string(p_hint_string),
|
|
||||||
usage(p_usage) {
|
|
||||||
if (hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
|
||||||
class_name = hint_string;
|
|
||||||
} else {
|
|
||||||
class_name = p_class_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyInfo(GDNativeVariantType p_type, const char *p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const char *p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const char *p_class_name = "") :
|
|
||||||
PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MethodInfo {
|
struct MethodInfo {
|
||||||
const char *name;
|
const char *name;
|
||||||
PropertyInfo return_val;
|
PropertyInfo return_val;
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* property_info.hpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef GODOT_PROPERTY_INFO_HPP
|
||||||
|
#define GODOT_PROPERTY_INFO_HPP
|
||||||
|
|
||||||
|
#include <godot_cpp/core/defs.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/classes/global_constants.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/variant/variant.hpp>
|
||||||
|
|
||||||
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
|
#include <godot/gdnative_interface.h>
|
||||||
|
|
||||||
|
namespace godot {
|
||||||
|
|
||||||
|
struct PropertyInfo {
|
||||||
|
Variant::Type type = Variant::NIL;
|
||||||
|
const char *name = nullptr;
|
||||||
|
const char *class_name = nullptr;
|
||||||
|
uint32_t hint = 0;
|
||||||
|
const char *hint_string = nullptr;
|
||||||
|
uint32_t usage = 7;
|
||||||
|
|
||||||
|
operator GDNativePropertyInfo() const {
|
||||||
|
GDNativePropertyInfo info;
|
||||||
|
info.type = type;
|
||||||
|
info.name = name;
|
||||||
|
info.hint = hint;
|
||||||
|
info.hint_string = hint_string;
|
||||||
|
info.class_name = class_name;
|
||||||
|
info.usage = usage;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyInfo() = default;
|
||||||
|
|
||||||
|
PropertyInfo(Variant::Type p_type, const char *p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const char *p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const char *p_class_name = "") :
|
||||||
|
type(p_type),
|
||||||
|
name(p_name),
|
||||||
|
hint(p_hint),
|
||||||
|
hint_string(p_hint_string),
|
||||||
|
usage(p_usage) {
|
||||||
|
if (hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||||
|
class_name = hint_string;
|
||||||
|
} else {
|
||||||
|
class_name = p_class_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyInfo(GDNativeVariantType p_type, const char *p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const char *p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const char *p_class_name = "") :
|
||||||
|
PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace godot
|
||||||
|
|
||||||
|
#endif // ! GODOT_OBJECT_HPP
|
|
@ -7,10 +7,20 @@ func _ready():
|
||||||
|
|
||||||
prints("")
|
prints("")
|
||||||
|
|
||||||
|
# To string.
|
||||||
|
prints("To string")
|
||||||
|
prints(" Example --> ", $Example.to_string())
|
||||||
|
prints(" ExampleMin --> ", $Example/ExampleMin.to_string())
|
||||||
|
|
||||||
# Call static methods.
|
# Call static methods.
|
||||||
prints("Static method calls")
|
prints("Static method calls")
|
||||||
prints(" static (109)", Example.test_static(9, 100));
|
prints(" static (109)", Example.test_static(9, 100));
|
||||||
Example.test_static2();
|
Example.test_static2();
|
||||||
|
|
||||||
|
# Property list.
|
||||||
|
prints("Property list")
|
||||||
|
$Example.property_from_list = Vector3(100, 200, 300)
|
||||||
|
prints(" property value ", $Example.property_from_list)
|
||||||
|
|
||||||
# Call methods.
|
# Call methods.
|
||||||
prints("Instance method calls")
|
prints("Instance method calls")
|
||||||
|
|
|
@ -7,6 +7,8 @@ script = ExtResource( "1_c326s" )
|
||||||
|
|
||||||
[node name="Example" type="Example" parent="."]
|
[node name="Example" type="Example" parent="."]
|
||||||
|
|
||||||
|
[node name="ExampleMin" type="ExampleMin" parent="Example"]
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Example"]
|
[node name="Label" type="Label" parent="Example"]
|
||||||
offset_left = 194.0
|
offset_left = 194.0
|
||||||
offset_top = -2.0
|
offset_top = -2.0
|
||||||
|
|
|
@ -58,6 +58,51 @@ int Example::def_args(int p_a, int p_b) {
|
||||||
return p_a + p_b;
|
return p_a + p_b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Example::_notification(int p_what) {
|
||||||
|
UtilityFunctions::print("Notification: ", String::num(p_what));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Example::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
|
if (p_name == StringName("property_from_list")) {
|
||||||
|
property_from_list = p_value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Example::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
|
if (p_name == StringName("property_from_list")) {
|
||||||
|
r_ret = property_from_list;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Example::_to_string() const {
|
||||||
|
return "[ GDExtension::Example <--> Instance ID:" + itos(get_instance_id()) + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Example::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
|
p_list->push_back(PropertyInfo(Variant::VECTOR3, "property_from_list"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Example::_property_can_revert(const StringName &p_name) const {
|
||||||
|
if (p_name == StringName("property_from_list") && property_from_list != Vector3(42, 42, 42)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool Example::_property_get_revert(const StringName &p_name, Variant &r_property) const {
|
||||||
|
if (p_name == StringName("property_from_list")) {
|
||||||
|
r_property = Vector3(42, 42, 42);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void Example::_bind_methods() {
|
void Example::_bind_methods() {
|
||||||
// Methods.
|
// Methods.
|
||||||
ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
|
ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
|
||||||
|
|
|
@ -56,14 +56,31 @@ public:
|
||||||
~ExampleRef();
|
~ExampleRef();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ExampleMin : public Control {
|
||||||
|
GDCLASS(ExampleMin, Control);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods(){};
|
||||||
|
};
|
||||||
|
|
||||||
class Example : public Control {
|
class Example : public Control {
|
||||||
GDCLASS(Example, Control);
|
GDCLASS(Example, Control);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
void _notification(int p_what);
|
||||||
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||||
|
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||||
|
bool _property_can_revert(const StringName &p_name) const;
|
||||||
|
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
|
||||||
|
|
||||||
|
String _to_string() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector2 custom_position;
|
Vector2 custom_position;
|
||||||
|
Vector3 property_from_list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constants.
|
// Constants.
|
||||||
|
|
|
@ -46,6 +46,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDB::register_class<ExampleRef>();
|
ClassDB::register_class<ExampleRef>();
|
||||||
|
ClassDB::register_class<ExampleMin>();
|
||||||
ClassDB::register_class<Example>();
|
ClassDB::register_class<Example>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue