Replace bindgins to work with extensions
This commit is contained in:
committed by
Bastiaan Olij
parent
ee70866894
commit
e4ed48976a
449
include/godot_cpp/core/binder_common.hpp
Normal file
449
include/godot_cpp/core/binder_common.hpp
Normal file
@@ -0,0 +1,449 @@
|
||||
/*************************************************************************/
|
||||
/* binder_common.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_CPP_BINDER_COMMON_HPP
|
||||
#define GODOT_CPP_BINDER_COMMON_HPP
|
||||
|
||||
#include <godot/gdnative_interface.h>
|
||||
|
||||
#include <godot_cpp/core/method_ptrcall.hpp>
|
||||
#include <godot_cpp/core/type_info.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace godot {
|
||||
|
||||
#define VARIANT_ENUM_CAST(m_class, m_enum) \
|
||||
namespace godot { \
|
||||
MAKE_ENUM_TYPE_INFO(m_class, m_enum) \
|
||||
template <> \
|
||||
struct VariantCaster<m_class::m_enum> { \
|
||||
static _FORCE_INLINE_ m_class::m_enum cast(const Variant &p_variant) { \
|
||||
return (m_class::m_enum)p_variant.operator int64_t(); \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct PtrToArg<m_class::m_enum> { \
|
||||
_FORCE_INLINE_ static m_class::m_enum convert(const void *p_ptr) { \
|
||||
return m_class::m_enum(*reinterpret_cast<const int64_t *>(p_ptr)); \
|
||||
} \
|
||||
typedef int64_t EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_class::m_enum p_val, const void *p_ptr) { \
|
||||
*(int64_t *)p_ptr = p_val; \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct VariantCaster {
|
||||
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
|
||||
return p_variant;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct VariantCaster<T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
|
||||
return p_variant;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct VariantCaster<const T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
|
||||
return p_variant;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VariantObjectClassChecker {
|
||||
static _FORCE_INLINE_ bool check(const Variant &p_variant) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Ref;
|
||||
|
||||
template <typename T>
|
||||
struct VariantObjectClassChecker<const Ref<T> &> {
|
||||
static _FORCE_INLINE_ bool check(const Variant &p_variant) {
|
||||
Object *obj = p_variant;
|
||||
const Ref<T> node = p_variant;
|
||||
return node.ptr() || !obj;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct VariantCasterAndValidate {
|
||||
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDNativeCallError &r_error) {
|
||||
GDNativeVariantType argtype = GetTypeInfo<T>::VARIANT_TYPE;
|
||||
if (!internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
|
||||
!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_INVALID_ARGUMENT;
|
||||
r_error.argument = p_arg_idx;
|
||||
r_error.expected = argtype;
|
||||
}
|
||||
|
||||
return VariantCaster<T>::cast(*p_args[p_arg_idx]);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct VariantCasterAndValidate<T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDNativeCallError &r_error) {
|
||||
GDNativeVariantType argtype = GetTypeInfo<T>::VARIANT_TYPE;
|
||||
if (!internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
|
||||
!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_INVALID_ARGUMENT;
|
||||
r_error.argument = p_arg_idx;
|
||||
r_error.expected = argtype;
|
||||
}
|
||||
|
||||
return VariantCaster<T>::cast(*p_args[p_arg_idx]);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct VariantCasterAndValidate<const T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDNativeCallError &r_error) {
|
||||
GDNativeVariantType argtype = GetTypeInfo<T>::VARIANT_TYPE;
|
||||
if (!internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
|
||||
!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_INVALID_ARGUMENT;
|
||||
r_error.argument = p_arg_idx;
|
||||
r_error.expected = argtype;
|
||||
}
|
||||
|
||||
return VariantCaster<T>::cast(*p_args[p_arg_idx]);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const GDNativeTypePtr *p_args, IndexSequence<Is...>) {
|
||||
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
|
||||
}
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const GDNativeTypePtr *p_args, IndexSequence<Is...>) {
|
||||
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
|
||||
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const GDNativeTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
|
||||
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const GDNativeTypePtr *p_args) {
|
||||
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...) const, const GDNativeTypePtr *p_args) {
|
||||
call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret) {
|
||||
call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, const GDNativeTypePtr *p_args, void *r_ret) {
|
||||
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDNativeCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDNATIVE_CALL_OK;
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
|
||||
#else
|
||||
(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
|
||||
#endif
|
||||
(void)(p_args); // Avoid warning.
|
||||
}
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, GDNativeCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDNATIVE_CALL_OK;
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
|
||||
#else
|
||||
(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
|
||||
#endif
|
||||
(void)(p_args); // Avoid warning.
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, GDNativeCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDNATIVE_CALL_OK;
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
|
||||
#else
|
||||
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, GDNativeCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDNATIVE_CALL_OK;
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
|
||||
#else
|
||||
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
|
||||
#endif
|
||||
(void)p_args;
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
|
||||
|
||||
int32_t dvs = default_values.size();
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
|
||||
std::array<const Variant *, sizeof...(P)> argsp;
|
||||
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
|
||||
if (i < p_argcount) {
|
||||
args[i] = p_args[i];
|
||||
} else {
|
||||
args[i] = default_values[i - p_argcount + (dvs - missing)];
|
||||
}
|
||||
argsp[i] = &args[i];
|
||||
}
|
||||
|
||||
call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const GDNativeVariantPtr *p_args, int p_argcount, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
|
||||
|
||||
int32_t dvs = default_values.size();
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
|
||||
std::array<const Variant *, sizeof...(P)> argsp;
|
||||
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
|
||||
if (i < p_argcount) {
|
||||
args[i] = p_args[i];
|
||||
} else {
|
||||
args[i] = default_values[i - p_argcount + (dvs - missing)];
|
||||
}
|
||||
argsp[i] = &args[i];
|
||||
}
|
||||
|
||||
call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, Variant &r_ret, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
|
||||
|
||||
int32_t dvs = default_values.size();
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
|
||||
std::array<const Variant *, sizeof...(P)> argsp;
|
||||
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
|
||||
if (i < p_argcount) {
|
||||
args[i] = p_args[i];
|
||||
} else {
|
||||
args[i] = default_values[i - p_argcount + (dvs - missing)];
|
||||
}
|
||||
argsp[i] = &args[i];
|
||||
}
|
||||
|
||||
call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const GDNativeVariantPtr *p_args, int p_argcount, Variant &r_ret, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
|
||||
|
||||
int32_t dvs = default_values.size();
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
|
||||
std::array<const Variant *, sizeof...(P)> argsp;
|
||||
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
|
||||
if (i < p_argcount) {
|
||||
args[i] = p_args[i];
|
||||
} else {
|
||||
args[i] = default_values[i - p_argcount + (dvs - missing)];
|
||||
}
|
||||
argsp[i] = &args[i];
|
||||
}
|
||||
|
||||
call_with_variant_args_retc_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
// GCC raises "parameter 'p_args' set but not used" when P = {},
|
||||
// it's not clever enough to treat other P values as making this branch valid.
|
||||
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
|
||||
#endif
|
||||
|
||||
template <class Q>
|
||||
void call_get_argument_type_helper(int p_arg, int &index, GDNativeVariantType &type) {
|
||||
if (p_arg == index) {
|
||||
type = GetTypeInfo<Q>::VARIANT_TYPE;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
GDNativeVariantType call_get_argument_type(int p_arg) {
|
||||
GDNativeVariantType type = GDNATIVE_VARIANT_TYPE_NIL;
|
||||
int index = 0;
|
||||
// I think rocket science is simpler than modern C++.
|
||||
using expand_type = int[];
|
||||
expand_type a{ 0, (call_get_argument_type_helper<P>(p_arg, index, type), 0)... };
|
||||
(void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
|
||||
(void)index; // Suppress GCC warning.
|
||||
return type;
|
||||
}
|
||||
|
||||
template <class Q>
|
||||
void call_get_argument_type_info_helper(int p_arg, int &index, GDNativePropertyInfo &info) {
|
||||
if (p_arg == index) {
|
||||
info = GetTypeInfo<Q>::get_class_info();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
void call_get_argument_type_info(int p_arg, GDNativePropertyInfo &info) {
|
||||
int index = 0;
|
||||
// I think rocket science is simpler than modern C++.
|
||||
using expand_type = int[];
|
||||
expand_type a{ 0, (call_get_argument_type_info_helper<P>(p_arg, index, info), 0)... };
|
||||
(void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
|
||||
(void)index; // Suppress GCC warning.
|
||||
}
|
||||
|
||||
template <class Q>
|
||||
void call_get_argument_metadata_helper(int p_arg, int &index, GDNativeExtensionClassMethodArgumentMetadata &md) {
|
||||
if (p_arg == index) {
|
||||
md = GetTypeInfo<Q>::METADATA;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
GDNativeExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
|
||||
GDNativeExtensionClassMethodArgumentMetadata md = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
|
||||
int index = 0;
|
||||
// I think rocket science is simpler than modern C++.
|
||||
using expand_type = int[];
|
||||
expand_type a{ 0, (call_get_argument_metadata_helper<P>(p_arg, index, md), 0)... };
|
||||
(void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
|
||||
(void)index;
|
||||
return md;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_CPP_BINDER_COMMON_HPP
|
||||
80
include/godot_cpp/core/builtin_ptrcall.hpp
Normal file
80
include/godot_cpp/core/builtin_ptrcall.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*************************************************************************/
|
||||
/* builtin_ptrcall.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_CPP_BUILTIN_PTRCALL_HPP
|
||||
#define GODOT_CPP_BUILTIN_PTRCALL_HPP
|
||||
|
||||
#include <godot/gdnative_interface.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace godot {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class... Args>
|
||||
void _call_builtin_constructor(const GDNativePtrConstructor constructor, GDNativeTypePtr base, Args... args) {
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
|
||||
constructor(base, call_args.data());
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
T _call_builtin_method_ptr_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
|
||||
T ret;
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
|
||||
method(base, call_args.data(), &ret, sizeof...(Args));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void _call_builtin_method_ptr_no_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
|
||||
method(base, call_args.data(), nullptr, sizeof...(Args));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T _call_builtin_operator_ptr(const GDNativePtrOperatorEvaluator op, const GDNativeTypePtr left, const GDNativeTypePtr right) {
|
||||
T ret;
|
||||
op(left, right, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T _call_builtin_ptr_getter(const GDNativePtrGetter getter, const GDNativeTypePtr base) {
|
||||
T ret;
|
||||
getter(base, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_CPP_BUILTIN_PTRCALL_HPP
|
||||
187
include/godot_cpp/core/class_db.hpp
Normal file
187
include/godot_cpp/core/class_db.hpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/*************************************************************************/
|
||||
/* class_db.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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 CLASS_DB_HPP
|
||||
#define CLASS_DB_HPP
|
||||
|
||||
#include <godot/gdnative_interface.h>
|
||||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
#include <godot_cpp/core/method_bind.hpp>
|
||||
#include <godot_cpp/core/object.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace godot {
|
||||
|
||||
struct MethodDefinition {
|
||||
const char *name = nullptr;
|
||||
std::list<std::string> args;
|
||||
MethodDefinition() {}
|
||||
MethodDefinition(const char *p_name) :
|
||||
name(p_name) {}
|
||||
};
|
||||
|
||||
MethodDefinition D_METHOD(const char *p_name);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1);
|
||||
template <typename... Args>
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, Args... args) {
|
||||
MethodDefinition md = D_METHOD(p_name, args...);
|
||||
md.args.push_front(p_arg1);
|
||||
return md;
|
||||
}
|
||||
|
||||
class ClassDB {
|
||||
public:
|
||||
struct PropertySetGet {
|
||||
int index;
|
||||
const char *setter;
|
||||
const char *getter;
|
||||
MethodBind *_setptr;
|
||||
MethodBind *_getptr;
|
||||
Variant::Type type;
|
||||
};
|
||||
|
||||
struct ClassInfo {
|
||||
const char *name = nullptr;
|
||||
const char *parent_name = nullptr;
|
||||
GDNativeInitializationLevel level = GDNATIVE_INITIALIZATION_SCENE;
|
||||
std::unordered_map<std::string, MethodBind *> method_map;
|
||||
std::unordered_map<std::string, MethodInfo> signal_map;
|
||||
std::list<MethodBind *> method_order;
|
||||
GDExtensionClassInstancePtr (*constructor)(void *data);
|
||||
std::unordered_map<std::string, GDNativeExtensionClassCallVirtual> virtual_methods;
|
||||
void (*destructor)(void *data, GDExtensionClassInstancePtr ptr);
|
||||
void (*object_instance)(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance);
|
||||
std::unordered_map<std::string, PropertySetGet> property_setget;
|
||||
std::list<PropertyInfo> property_list;
|
||||
std::unordered_map<std::string, std::pair<std::string, GDNativeInt>> constant_map; // String in pair is enum name.
|
||||
std::list<std::string> constant_order;
|
||||
ClassInfo *parent_ptr = nullptr;
|
||||
};
|
||||
|
||||
private:
|
||||
static std::unordered_map<std::string, ClassInfo> classes;
|
||||
|
||||
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount);
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
static void register_class(GDNativeInitializationLevel p_level = GDNATIVE_INITIALIZATION_SCENE);
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method);
|
||||
template <class M>
|
||||
static MethodBind *bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
|
||||
static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1);
|
||||
static void add_signal(const char *p_class, const MethodInfo &p_signal);
|
||||
static void bind_integer_constant(const char *p_class, const char *p_enum, const char *p_name, GDNativeInt p_constant);
|
||||
static void bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call);
|
||||
|
||||
static MethodBind *get_method(const char *p_class, const char *p_method);
|
||||
|
||||
static GDNativeExtensionClassCallVirtual get_virtual_func(void *p_userdata, const char *p_name);
|
||||
|
||||
static void initialize(GDNativeInitializationLevel p_level);
|
||||
static void deinitialize(GDNativeInitializationLevel p_level);
|
||||
};
|
||||
|
||||
#define BIND_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), "", #m_constant, m_constant);
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
|
||||
|
||||
#define BIND_VIRTUAL_METHOD(m_method) \
|
||||
{ \
|
||||
auto ___call##m_method = [](GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) -> void { \
|
||||
call_with_ptr_args(reinterpret_cast<SelfType *>(p_instance), &SelfType::m_method, p_args, p_ret); \
|
||||
}; \
|
||||
ClassDB::bind_virtual_method(get_class_static(), #m_method, ___call##m_method); \
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ClassDB::register_class(GDNativeInitializationLevel p_level) {
|
||||
ClassInfo cl;
|
||||
cl.name = T::get_class_static();
|
||||
cl.parent_name = T::get_parent_class_static();
|
||||
cl.level = p_level;
|
||||
cl.constructor = T::create;
|
||||
cl.destructor = T::free;
|
||||
cl.object_instance = T::set_object_instance;
|
||||
classes[cl.name] = cl;
|
||||
if (classes.find(cl.parent_name) != classes.end()) {
|
||||
cl.parent_ptr = &classes[cl.parent_name];
|
||||
}
|
||||
T::initialize_class();
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
MethodBind *ClassDB::bind_method(N p_method_name, M p_method) {
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
|
||||
return bind_methodfi(0, bind, p_method_name, nullptr, 0);
|
||||
}
|
||||
|
||||
template <class M>
|
||||
MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info, const std::vector<Variant> &p_default_args, bool p_return_nil_is_variant) {
|
||||
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
|
||||
ERR_FAIL_COND_V(!bind, nullptr);
|
||||
|
||||
bind->set_name(p_name);
|
||||
bind->set_default_arguments(p_default_args);
|
||||
|
||||
const char *instance_type = bind->get_instance_class();
|
||||
|
||||
std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(instance_type);
|
||||
if (type_it == classes.end()) {
|
||||
memdelete(bind);
|
||||
ERR_FAIL_V_MSG(nullptr, "Class doesn't exist.");
|
||||
}
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
if (type.method_map.find(p_name) != type.method_map.end()) {
|
||||
memdelete(bind);
|
||||
ERR_FAIL_V_MSG(nullptr, "Binding duplicate method.");
|
||||
}
|
||||
|
||||
type.method_map[p_name] = bind;
|
||||
type.method_order.push_back(bind);
|
||||
|
||||
return bind;
|
||||
}
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! CLASS_DB_HPP
|
||||
106
include/godot_cpp/core/defs.hpp
Normal file
106
include/godot_cpp/core/defs.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*************************************************************************/
|
||||
/* defs.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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 DEFS_H
|
||||
#define DEFS_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GDN_EXPORT __attribute__((visibility("default")))
|
||||
#elif defined(_WIN32)
|
||||
#define GDN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define GDN_EXPORT
|
||||
#endif
|
||||
|
||||
// Turn argument to string constant:
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing
|
||||
#ifndef _STR
|
||||
#define _STR(m_x) #m_x
|
||||
#define _MKSTR(m_x) _STR(m_x)
|
||||
#endif
|
||||
|
||||
// Should always inline no matter what.
|
||||
#ifndef _ALWAYS_INLINE_
|
||||
#if defined(__GNUC__)
|
||||
#define _ALWAYS_INLINE_ __attribute__((always_inline)) inline
|
||||
#elif defined(_MSC_VER)
|
||||
#define _ALWAYS_INLINE_ __forceinline
|
||||
#else
|
||||
#define _ALWAYS_INLINE_ inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Should always inline, except in debug builds because it makes debugging harder.
|
||||
#ifndef _FORCE_INLINE_
|
||||
#ifdef DISABLE_FORCED_INLINE
|
||||
#define _FORCE_INLINE_ inline
|
||||
#else
|
||||
#define _FORCE_INLINE_ _ALWAYS_INLINE_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Windows badly defines a lot of stuff we'll never use. Undefine it.
|
||||
#ifdef _WIN32
|
||||
#undef min // override standard definition
|
||||
#undef max // override standard definition
|
||||
#undef ERROR // override (really stupid) wingdi.h standard definition
|
||||
#undef DELETE // override (another really stupid) winnt.h standard definition
|
||||
#undef MessageBox // override winuser.h standard definition
|
||||
#undef MIN // override standard definition
|
||||
#undef MAX // override standard definition
|
||||
#undef CLAMP // override standard definition
|
||||
#undef Error
|
||||
#undef OK
|
||||
#undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define likely(x) x
|
||||
#define unlikely(x) x
|
||||
#endif
|
||||
|
||||
// Home-made index sequence trick, so it can be used everywhere without the costly include of std::tuple.
|
||||
// https://stackoverflow.com/questions/15014096/c-index-of-type-during-variadic-template-expansion
|
||||
template <size_t... Is>
|
||||
struct IndexSequence {};
|
||||
|
||||
template <size_t N, size_t... Is>
|
||||
struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
|
||||
|
||||
template <size_t... Is>
|
||||
struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
|
||||
|
||||
#endif // ! DEFS_H
|
||||
94
include/godot_cpp/core/engine_ptrcall.hpp
Normal file
94
include/godot_cpp/core/engine_ptrcall.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/*************************************************************************/
|
||||
/* engine_ptrcall.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_CPP_ENGINE_PTRCALL_HPP
|
||||
#define GODOT_CPP_ENGINE_PTRCALL_HPP
|
||||
|
||||
#include <godot/gdnative_interface.h>
|
||||
|
||||
#include <godot_cpp/core/binder_common.hpp>
|
||||
#include <godot_cpp/core/object.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace godot {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class O, class... Args>
|
||||
Object *_call_native_mb_ret_obj(const GDNativeMethodBindPtr mb, void *instance, const Args &...args) {
|
||||
GodotObject *ret = nullptr;
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
|
||||
internal::interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
|
||||
return (Object *)internal::interface->object_get_instance_binding(ret, internal::token, &O::___binding_callbacks);
|
||||
}
|
||||
|
||||
template <class R, class... Args>
|
||||
R _call_native_mb_ret(const GDNativeMethodBindPtr mb, void *instance, const Args &...args) {
|
||||
R ret;
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
|
||||
internal::interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void _call_native_mb_no_ret(const GDNativeMethodBindPtr mb, void *instance, const Args &...args) {
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
|
||||
internal::interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr);
|
||||
}
|
||||
|
||||
template <class R, class... Args>
|
||||
R _call_utility_ret(GDNativePtrUtilityFunction func, const Args &...args) {
|
||||
R ret;
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
|
||||
func(&ret, mb_args.data(), mb_args.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
Object *_call_utility_ret_obj(const GDNativePtrUtilityFunction func, void *instance, const Args &...args) {
|
||||
GodotObject *ret = nullptr;
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
|
||||
func(&ret, mb_args.data(), mb_args.size());
|
||||
return (Object *)internal::interface->object_get_instance_binding(ret, internal::token, &Object::___binding_callbacks);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void _call_utility_no_ret(const GDNativePtrUtilityFunction func, const Args &...args) {
|
||||
std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
|
||||
func(nullptr, mb_args.data(), mb_args.size());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_CPP_ENGINE_PTRCALL_HPP
|
||||
596
include/godot_cpp/core/error_macros.hpp
Normal file
596
include/godot_cpp/core/error_macros.hpp
Normal file
@@ -0,0 +1,596 @@
|
||||
/*************************************************************************/
|
||||
/* error_macros.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_CPP_ERROR_MACROS_HPP
|
||||
#define GODOT_CPP_ERROR_MACROS_HPP
|
||||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_is_warning = false);
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_is_warning = false);
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false);
|
||||
|
||||
// Used to strip debug messages in release mode
|
||||
#ifdef DEBUG_ENABLED
|
||||
#define DEBUG_STR(m_msg) m_msg
|
||||
#else
|
||||
#define DEBUG_STR(m_msg) ""
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
|
||||
#define FUNCTION_STR __FUNCTION__
|
||||
#else
|
||||
#define FUNCTION_STR __FUNCTION__
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/**
|
||||
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
|
||||
*/
|
||||
#define GENERATE_TRAP() __debugbreak()
|
||||
#else
|
||||
/**
|
||||
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
|
||||
*/
|
||||
#define GENERATE_TRAP() __builtin_trap()
|
||||
#endif
|
||||
|
||||
#define ERR_FAIL_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, prints `m_msg` and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, prints `m_msg` and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
|
||||
*
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, prints `m_msg` and the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Unsigned integer index out of bounds error macros.
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, prints `m_msg` and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, prints `m_msg` and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, prints `m_msg` and the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Null reference error macros.
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_NULL_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_NULL(m_param) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, prints `m_msg` and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_NULL_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_V(m_param, m_retval) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, prints `m_msg` and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
* If checking for null use ERR_FAIL_NULL_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_COND(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current function returns.
|
||||
*
|
||||
* If checking for null use ERR_FAIL_NULL_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
|
||||
*/
|
||||
#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_COND_V(m_cond, m_retval) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current function returns `m_retval`.
|
||||
*
|
||||
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
|
||||
*/
|
||||
#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_CONTINUE_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current loop continues.
|
||||
*/
|
||||
#define ERR_CONTINUE(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \
|
||||
continue; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current loop continues.
|
||||
*/
|
||||
#define ERR_CONTINUE_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \
|
||||
continue; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_BREAK_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current loop breaks.
|
||||
*/
|
||||
#define ERR_BREAK(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \
|
||||
break; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current loop breaks.
|
||||
*/
|
||||
#define ERR_BREAK_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \
|
||||
break; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the application crashes.
|
||||
*/
|
||||
#define CRASH_COND(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the application crashes.
|
||||
*/
|
||||
#define CRASH_COND_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Generic error macros.
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* The current function returns.
|
||||
*/
|
||||
#define ERR_FAIL() \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed."); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required.
|
||||
*
|
||||
* Prints `m_msg`, and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_MSG(m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", DEBUG_STR(m_msg)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* The current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_V(m_retval) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required.
|
||||
*
|
||||
* Prints `m_msg`, and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_V_MSG(m_retval, m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG.
|
||||
* Only use this macro at the start of a function that has not been implemented yet, or
|
||||
* if more complex error detection or recovery is required.
|
||||
*
|
||||
* Prints `m_msg`.
|
||||
*/
|
||||
#define ERR_PRINT(m_msg) \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
|
||||
|
||||
/**
|
||||
* Prints `m_msg` once during the application lifetime.
|
||||
*/
|
||||
#define ERR_PRINT_ONCE(m_msg) \
|
||||
if (true) { \
|
||||
static bool first_print = true; \
|
||||
if (first_print) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \
|
||||
first_print = false; \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Print warning message macros.
|
||||
|
||||
/**
|
||||
* Prints `m_msg`.
|
||||
*
|
||||
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
|
||||
*/
|
||||
#define WARN_PRINT(m_msg) \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true)
|
||||
|
||||
/**
|
||||
* Prints `m_msg` once during the application lifetime.
|
||||
*
|
||||
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
|
||||
*/
|
||||
#define WARN_PRINT_ONCE(m_msg) \
|
||||
if (true) { \
|
||||
static bool first_print = true; \
|
||||
if (first_print) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
|
||||
first_print = false; \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Print deprecated warning message macros.
|
||||
|
||||
/**
|
||||
* Warns that the current function is deprecated.
|
||||
*/
|
||||
#define WARN_DEPRECATED \
|
||||
if (true) { \
|
||||
static SafeFlag warning_shown; \
|
||||
if (!warning_shown.is_set()) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", true); \
|
||||
warning_shown.set(); \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Warns that the current function is deprecated and prints `m_msg`.
|
||||
*/
|
||||
#define WARN_DEPRECATED_MSG(m_msg) \
|
||||
if (true) { \
|
||||
static SafeFlag warning_shown; \
|
||||
if (!warning_shown.is_set()) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", DEBUG_STR(m_msg), true); \
|
||||
warning_shown.set(); \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Do not use.
|
||||
* If the application should never reach this point use CRASH_NOW_MSG(m_msg) to explain why.
|
||||
*
|
||||
* The application crashes.
|
||||
*/
|
||||
#define CRASH_NOW() \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Only use if the application should never reach this point.
|
||||
*
|
||||
* Prints `m_msg`, and then the application crashes.
|
||||
*/
|
||||
#define CRASH_NOW_MSG(m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", DEBUG_STR(m_msg)); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
} // namespace godot
|
||||
|
||||
/**
|
||||
* Gives an error message when a method bind is invalid (likely the hash changed).
|
||||
* Avoids crashing the application in this case. It's not free, so it's debug only.
|
||||
*/
|
||||
#ifdef DEBUG_ENABLED
|
||||
#define CHECK_METHOD_BIND_RET(m_mb, m_ret) \
|
||||
if (unlikely(!m_mb)) { \
|
||||
ERR_PRINT_ONCE("Method bind was not found. Likely the engine method changed to an incompatible version."); \
|
||||
return m_ret; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
#define CHECK_METHOD_BIND(m_mb) \
|
||||
if (unlikely(!m_mb)) { \
|
||||
ERR_PRINT_ONCE("Method bind was not found. Likely the engine method changed to an incompatible version."); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
#else
|
||||
#define CHECK_METHOD_BIND_RET(m_mb, m_ret)
|
||||
#define CHECK_METHOD_BIND(m_mb)
|
||||
#endif
|
||||
|
||||
#endif // ! GODOT_CPP_ERROR_MACROS_HPP
|
||||
115
include/godot_cpp/core/memory.hpp
Normal file
115
include/godot_cpp/core/memory.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*************************************************************************/
|
||||
/* memory.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_CPP_MEMORY_HPP
|
||||
#define GODOT_CPP_MEMORY_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
|
||||
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
|
||||
|
||||
_ALWAYS_INLINE_ void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description) {
|
||||
return p_pointer;
|
||||
}
|
||||
|
||||
namespace godot {
|
||||
|
||||
class Memory {
|
||||
Memory();
|
||||
|
||||
public:
|
||||
static void *alloc_static(size_t p_bytes);
|
||||
static void *realloc_static(void *p_memory, size_t p_bytes);
|
||||
static void free_static(void *p_ptr);
|
||||
};
|
||||
|
||||
#define memnew(m_v) (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) {
|
||||
if (!__has_trivial_destructor(T)) {
|
||||
p_class->~T();
|
||||
}
|
||||
|
||||
Memory::free_static(p_class);
|
||||
}
|
||||
|
||||
#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count)
|
||||
|
||||
template <typename T>
|
||||
T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
|
||||
if (p_elements == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
/** overloading operator new[] cannot be done , because it may not return the real allocated address (it may pad the 'element count' before the actual array). Because of that, it must be done by hand. This is the
|
||||
same strategy used by std::vector, and the Vector class, so it should be safe.*/
|
||||
|
||||
size_t len = sizeof(T) * p_elements;
|
||||
uint64_t *mem = (uint64_t *)Memory::alloc_static(len);
|
||||
T *failptr = nullptr; // Get rid of a warning.
|
||||
ERR_FAIL_COND_V(!mem, failptr);
|
||||
*(mem - 1) = p_elements;
|
||||
|
||||
if (!__has_trivial_constructor(T)) {
|
||||
T *elems = (T *)mem;
|
||||
|
||||
/* call operator new */
|
||||
for (size_t i = 0; i < p_elements; i++) {
|
||||
new (&elems[i], sizeof(T), p_descr) T;
|
||||
}
|
||||
}
|
||||
|
||||
return (T *)mem;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void memdelete_arr(T *p_class) {
|
||||
uint64_t *ptr = (uint64_t *)p_class;
|
||||
|
||||
if (!__has_trivial_destructor(T)) {
|
||||
uint64_t elem_count = *(ptr - 1);
|
||||
|
||||
for (uint64_t i = 0; i < elem_count; i++) {
|
||||
p_class[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
Memory::free_static(ptr);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_CPP_MEMORY_HPP
|
||||
539
include/godot_cpp/core/method_bind.hpp
Normal file
539
include/godot_cpp/core/method_bind.hpp
Normal file
@@ -0,0 +1,539 @@
|
||||
/*************************************************************************/
|
||||
/* method_bind.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_CPP_METHOD_BIND_HPP
|
||||
#define GODOT_CPP_METHOD_BIND_HPP
|
||||
|
||||
#include <godot_cpp/core/binder_common.hpp>
|
||||
#include <godot_cpp/core/type_info.hpp>
|
||||
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
|
||||
#include <godot/gdnative_interface.h>
|
||||
|
||||
#include <godot_cpp/classes/global_constants.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class MethodBind {
|
||||
const char *name = nullptr;
|
||||
const char *instance_class = nullptr;
|
||||
int argument_count = 0;
|
||||
uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
|
||||
|
||||
bool _is_const = false;
|
||||
bool _has_return = false;
|
||||
|
||||
std::vector<std::string> argument_names;
|
||||
GDNativeVariantType *argument_types = nullptr;
|
||||
std::vector<Variant> default_arguments;
|
||||
|
||||
protected:
|
||||
virtual GDNativeVariantType gen_argument_type(int p_arg) const = 0;
|
||||
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const = 0;
|
||||
void generate_argument_types(int p_count);
|
||||
void set_const(bool p_const);
|
||||
void set_return(bool p_return);
|
||||
void set_argument_count(int p_count);
|
||||
|
||||
public:
|
||||
const char *get_name() const;
|
||||
void set_name(const char *p_name);
|
||||
_FORCE_INLINE_ int get_default_argument_count() const { return default_arguments.size(); }
|
||||
_FORCE_INLINE_ const std::vector<Variant> &get_default_arguments() const { return default_arguments; }
|
||||
_FORCE_INLINE_ Variant has_default_argument(int p_arg) const {
|
||||
int idx = p_arg - (argument_count - default_arguments.size());
|
||||
|
||||
if (idx < 0 || idx >= default_arguments.size()) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_FORCE_INLINE_ Variant get_default_argument(int p_arg) const {
|
||||
int idx = p_arg - (argument_count - default_arguments.size());
|
||||
|
||||
if (idx < 0 || idx >= default_arguments.size()) {
|
||||
return Variant();
|
||||
} else {
|
||||
return default_arguments[idx];
|
||||
}
|
||||
}
|
||||
_FORCE_INLINE_ const char *get_instance_class() const { return instance_class; }
|
||||
_FORCE_INLINE_ void set_instance_class(const char *p_class) { instance_class = p_class; }
|
||||
|
||||
_FORCE_INLINE_ int get_argument_count() const { return argument_count; };
|
||||
_FORCE_INLINE_ bool is_const() const { return _is_const; }
|
||||
_FORCE_INLINE_ bool has_return() const { return _has_return; }
|
||||
_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags; }
|
||||
_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
|
||||
void set_argument_names(const std::vector<std::string> &p_names);
|
||||
std::vector<std::string> get_argument_names() const;
|
||||
void set_default_arguments(const std::vector<Variant> &p_default_arguments) { default_arguments = p_default_arguments; }
|
||||
|
||||
_FORCE_INLINE_ GDNativeVariantType get_argument_type(int p_argument) const {
|
||||
ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, GDNATIVE_VARIANT_TYPE_NIL);
|
||||
return argument_types[p_argument + 1];
|
||||
}
|
||||
|
||||
GDNativePropertyInfo get_argument_info(int p_argument) const;
|
||||
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0;
|
||||
|
||||
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const = 0;
|
||||
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const = 0;
|
||||
|
||||
// Extension info.
|
||||
static GDNativeVariantType bind_get_argument_type(void *p_method_userdata, int32_t p_argument);
|
||||
static void bind_get_argument_info(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info);
|
||||
static GDNativeExtensionClassMethodArgumentMetadata bind_get_argument_metadata(void *p_method_userdata, int32_t p_argument);
|
||||
|
||||
static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
|
||||
static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return);
|
||||
|
||||
virtual ~MethodBind();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class MethodBindVarArg : public MethodBind {
|
||||
public:
|
||||
typedef Variant (T::*NativeCall)(const Variant **, GDNativeInt, GDNativeCallError &);
|
||||
|
||||
protected:
|
||||
NativeCall call_method = nullptr;
|
||||
MethodInfo arguments;
|
||||
|
||||
public:
|
||||
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
|
||||
if (p_arg < 0) {
|
||||
return arguments.return_val;
|
||||
} else if (p_arg < arguments.arguments.size()) {
|
||||
return arguments.arguments[p_arg];
|
||||
} else {
|
||||
return PropertyInfo(Variant::NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||
}
|
||||
}
|
||||
|
||||
virtual GDNativeVariantType gen_argument_type(int p_arg) const {
|
||||
return static_cast<GDNativeVariantType>(gen_argument_type_info(p_arg).type);
|
||||
}
|
||||
|
||||
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int) const {
|
||||
return GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
}
|
||||
|
||||
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
|
||||
T *instance = static_cast<T *>(p_instance);
|
||||
return (instance->*call_method)((const Variant **)p_args, p_argument_count, r_error);
|
||||
}
|
||||
|
||||
void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) {
|
||||
set_argument_count(p_info.arguments.size());
|
||||
if (p_info.arguments.size()) {
|
||||
std::vector<std::string> names;
|
||||
names.reserve(p_info.arguments.size());
|
||||
for (int i = 0; i < p_info.arguments.size(); i++) {
|
||||
names.push_back(p_info.arguments[i].name);
|
||||
}
|
||||
|
||||
set_argument_names(names);
|
||||
}
|
||||
|
||||
arguments = p_info;
|
||||
|
||||
if (p_return_nil_is_variant) {
|
||||
arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
|
||||
}
|
||||
generate_argument_types(p_info.arguments.size());
|
||||
}
|
||||
|
||||
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const {
|
||||
ERR_FAIL(); // Can't call.
|
||||
}
|
||||
|
||||
void set_method(NativeCall p_method) { call_method = p_method; }
|
||||
virtual bool is_const() const { return false; }
|
||||
|
||||
virtual bool is_vararg() const { return true; }
|
||||
|
||||
MethodBindVarArg() {
|
||||
set_return(true);
|
||||
}
|
||||
};
|
||||
|
||||
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>));
|
||||
a->set_method(p_method);
|
||||
a->set_method_info(p_info, p_return_nil_is_variant);
|
||||
a->set_instance_class(T::get_class_static());
|
||||
return a;
|
||||
}
|
||||
|
||||
#ifndef TYPED_METHOD_BIND
|
||||
class ___UnexistingClass;
|
||||
#define MB_T ___UnexistingClass
|
||||
#else
|
||||
#define MB_T T
|
||||
#endif
|
||||
|
||||
// No return, not const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class... P>
|
||||
#else
|
||||
template <class... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindT : public MethodBind {
|
||||
void (MB_T::*method)(P...);
|
||||
|
||||
protected:
|
||||
// GCC raises warnings in the case P = {} as the comparison is always false...
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlogical-op"
|
||||
#endif
|
||||
virtual GDNativeVariantType gen_argument_type(int p_arg) const {
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
return call_get_argument_type<P...>(p_arg);
|
||||
} else {
|
||||
return GDNATIVE_VARIANT_TYPE_NIL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
|
||||
GDNativePropertyInfo pi;
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
call_get_argument_type_info<P...>(p_arg, pi);
|
||||
} else {
|
||||
pi = PropertyInfo();
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
|
||||
return call_get_argument_metadata<P...>(p_argument);
|
||||
}
|
||||
|
||||
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_variant_args_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
|
||||
#else
|
||||
call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
|
||||
#endif
|
||||
return Variant();
|
||||
}
|
||||
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args);
|
||||
#else
|
||||
call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args);
|
||||
#endif // TYPED_METHOD_BIND
|
||||
}
|
||||
|
||||
MethodBindT(void (MB_T::*p_method)(P...)) {
|
||||
method = p_method;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
generate_argument_types(sizeof...(P));
|
||||
#endif // DEBUG_METHODS_ENABLED
|
||||
set_argument_count(sizeof...(P));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... P>
|
||||
MethodBind *create_method_bind(void (T::*p_method)(P...)) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
|
||||
#else
|
||||
MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method)));
|
||||
#endif // TYPED_METHOD_BIND
|
||||
a->set_instance_class(T::get_class_static());
|
||||
return a;
|
||||
}
|
||||
|
||||
// No return, const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class... P>
|
||||
#else
|
||||
template <class... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindTC : public MethodBind {
|
||||
void (MB_T::*method)(P...) const;
|
||||
|
||||
protected:
|
||||
// GCC raises warnings in the case P = {} as the comparison is always false...
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlogical-op"
|
||||
#endif
|
||||
virtual GDNativeVariantType gen_argument_type(int p_arg) const {
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
return call_get_argument_type<P...>(p_arg);
|
||||
} else {
|
||||
return GDNATIVE_VARIANT_TYPE_NIL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
|
||||
GDNativePropertyInfo pi;
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
call_get_argument_type_info<P...>(p_arg, pi);
|
||||
} else {
|
||||
pi = PropertyInfo();
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
|
||||
return call_get_argument_metadata<P...>(p_argument);
|
||||
}
|
||||
|
||||
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_variant_argsc_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
|
||||
#else
|
||||
call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
|
||||
#endif
|
||||
return Variant();
|
||||
}
|
||||
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args);
|
||||
#else
|
||||
call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args);
|
||||
#endif // TYPED_METHOD_BIND
|
||||
}
|
||||
|
||||
MethodBindTC(void (MB_T::*p_method)(P...) const) {
|
||||
method = p_method;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
generate_argument_types(sizeof...(P));
|
||||
#endif // DEBUG_METHODS_ENABLED
|
||||
set_argument_count(sizeof...(P));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... P>
|
||||
MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
|
||||
#else
|
||||
MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method)));
|
||||
#endif // TYPED_METHOD_BIND
|
||||
a->set_instance_class(T::get_class_static());
|
||||
return a;
|
||||
}
|
||||
|
||||
// Return, not const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class R, class... P>
|
||||
#else
|
||||
template <class R, class... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindTR : public MethodBind {
|
||||
R(MB_T::*method)
|
||||
(P...);
|
||||
|
||||
protected:
|
||||
// GCC raises warnings in the case P = {} as the comparison is always false...
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlogical-op"
|
||||
#endif
|
||||
virtual GDNativeVariantType gen_argument_type(int p_arg) const {
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
return call_get_argument_type<P...>(p_arg);
|
||||
} else {
|
||||
return GetTypeInfo<R>::VARIANT_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
GDNativePropertyInfo pi;
|
||||
call_get_argument_type_info<P...>(p_arg, pi);
|
||||
return pi;
|
||||
} else {
|
||||
return GetTypeInfo<R>::get_class_info();
|
||||
}
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
|
||||
if (p_argument >= 0) {
|
||||
return call_get_argument_metadata<P...>(p_argument);
|
||||
} else {
|
||||
return GetTypeInfo<R>::METADATA;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
|
||||
Variant ret;
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_variant_args_ret_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, ret, r_error, get_default_arguments());
|
||||
#else
|
||||
call_with_variant_args_ret_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
|
||||
#else
|
||||
call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
|
||||
#endif // TYPED_METHOD_BIND
|
||||
}
|
||||
|
||||
MethodBindTR(R (MB_T::*p_method)(P...)) {
|
||||
method = p_method;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
generate_argument_types(sizeof...(P));
|
||||
#endif // DEBUG_METHODS_ENABLED
|
||||
set_argument_count(sizeof...(P));
|
||||
set_return(true);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R, class... P>
|
||||
MethodBind *create_method_bind(R (T::*p_method)(P...)) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
|
||||
#else
|
||||
MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method)));
|
||||
#endif // TYPED_METHOD_BIND
|
||||
a->set_instance_class(T::get_class_static());
|
||||
return a;
|
||||
}
|
||||
|
||||
// Return, const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class R, class... P>
|
||||
#else
|
||||
template <class R, class... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindTRC : public MethodBind {
|
||||
R(MB_T::*method)
|
||||
(P...) const;
|
||||
|
||||
protected:
|
||||
// GCC raises warnings in the case P = {} as the comparison is always false...
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlogical-op"
|
||||
#endif
|
||||
virtual GDNativeVariantType gen_argument_type(int p_arg) const {
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
return call_get_argument_type<P...>(p_arg);
|
||||
} else {
|
||||
return GetTypeInfo<R>::VARIANT_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
|
||||
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
|
||||
GDNativePropertyInfo pi;
|
||||
call_get_argument_type_info<P...>(p_arg, pi);
|
||||
return pi;
|
||||
} else {
|
||||
return GetTypeInfo<R>::get_class_info();
|
||||
}
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
|
||||
if (p_argument >= 0) {
|
||||
return call_get_argument_metadata<P...>(p_argument);
|
||||
} else {
|
||||
return GetTypeInfo<R>::METADATA;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
|
||||
Variant ret;
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_variant_args_retc_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, ret, r_error, get_default_arguments());
|
||||
#else
|
||||
call_with_variant_args_retc_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
|
||||
#else
|
||||
call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
|
||||
#endif // TYPED_METHOD_BIND
|
||||
}
|
||||
|
||||
MethodBindTRC(R (MB_T::*p_method)(P...) const) {
|
||||
method = p_method;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
generate_argument_types(sizeof...(P));
|
||||
#endif // DEBUG_METHODS_ENABLED
|
||||
set_argument_count(sizeof...(P));
|
||||
set_return(true);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R, class... P>
|
||||
MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
|
||||
#else
|
||||
MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method)));
|
||||
#endif // TYPED_METHOD_BIND
|
||||
a->set_instance_class(T::get_class_static());
|
||||
return a;
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_CPP_METHOD_BIND_HPP
|
||||
189
include/godot_cpp/core/method_ptrcall.hpp
Normal file
189
include/godot_cpp/core/method_ptrcall.hpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/*************************************************************************/
|
||||
/* method_ptrcall.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_CPP_METHOD_PTRCALL_HPP
|
||||
#define GODOT_CPP_METHOD_PTRCALL_HPP
|
||||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
struct PtrToArg {};
|
||||
|
||||
#define MAKE_PTRARG(m_type) \
|
||||
template <> \
|
||||
struct PtrToArg<m_type> { \
|
||||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct PtrToArg<const m_type &> { \
|
||||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAKE_PTRARGCONV(m_type, m_conv) \
|
||||
template <> \
|
||||
struct PtrToArg<m_type> { \
|
||||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
|
||||
} \
|
||||
typedef m_conv EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
|
||||
} \
|
||||
_FORCE_INLINE_ static m_conv encode_arg(m_type p_val) { \
|
||||
return static_cast<m_conv>(p_val); \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct PtrToArg<const m_type &> { \
|
||||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
|
||||
} \
|
||||
typedef m_conv EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
|
||||
*((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
|
||||
} \
|
||||
_FORCE_INLINE_ static m_conv encode_arg(m_type p_val) { \
|
||||
return static_cast<m_conv>(p_val); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAKE_PTRARG_BY_REFERENCE(m_type) \
|
||||
template <> \
|
||||
struct PtrToArg<m_type> { \
|
||||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct PtrToArg<const m_type &> { \
|
||||
_FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
|
||||
return *reinterpret_cast<const m_type *>(p_ptr); \
|
||||
} \
|
||||
typedef m_type EncodeT; \
|
||||
_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
|
||||
*((m_type *)p_ptr) = p_val; \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_PTRARGCONV(bool, uint8_t);
|
||||
// Integer types.
|
||||
MAKE_PTRARGCONV(uint8_t, int64_t);
|
||||
MAKE_PTRARGCONV(int8_t, int64_t);
|
||||
MAKE_PTRARGCONV(uint16_t, int64_t);
|
||||
MAKE_PTRARGCONV(int16_t, int64_t);
|
||||
MAKE_PTRARGCONV(uint32_t, int64_t);
|
||||
MAKE_PTRARGCONV(int32_t, int64_t);
|
||||
MAKE_PTRARG(int64_t);
|
||||
MAKE_PTRARG(uint64_t);
|
||||
// Float types
|
||||
MAKE_PTRARGCONV(float, double);
|
||||
MAKE_PTRARG(double);
|
||||
|
||||
MAKE_PTRARG(String);
|
||||
MAKE_PTRARG(Vector2);
|
||||
MAKE_PTRARG(Vector2i);
|
||||
MAKE_PTRARG(Rect2);
|
||||
MAKE_PTRARG(Rect2i);
|
||||
MAKE_PTRARG_BY_REFERENCE(Vector3);
|
||||
MAKE_PTRARG_BY_REFERENCE(Vector3i);
|
||||
MAKE_PTRARG(Transform2D);
|
||||
MAKE_PTRARG_BY_REFERENCE(Plane);
|
||||
MAKE_PTRARG(Quaternion);
|
||||
MAKE_PTRARG_BY_REFERENCE(AABB);
|
||||
MAKE_PTRARG_BY_REFERENCE(Basis);
|
||||
MAKE_PTRARG_BY_REFERENCE(Transform3D);
|
||||
MAKE_PTRARG_BY_REFERENCE(Color);
|
||||
MAKE_PTRARG(StringName);
|
||||
MAKE_PTRARG(NodePath);
|
||||
MAKE_PTRARG(RID);
|
||||
// Object doesn't need this.
|
||||
MAKE_PTRARG(Callable);
|
||||
MAKE_PTRARG(Signal);
|
||||
MAKE_PTRARG(Dictionary);
|
||||
MAKE_PTRARG(Array);
|
||||
MAKE_PTRARG(PackedByteArray);
|
||||
MAKE_PTRARG(PackedInt32Array);
|
||||
MAKE_PTRARG(PackedInt64Array);
|
||||
MAKE_PTRARG(PackedFloat32Array);
|
||||
MAKE_PTRARG(PackedFloat64Array);
|
||||
MAKE_PTRARG(PackedStringArray);
|
||||
MAKE_PTRARG(PackedVector2Array);
|
||||
MAKE_PTRARG(PackedVector3Array);
|
||||
MAKE_PTRARG(PackedColorArray);
|
||||
MAKE_PTRARG_BY_REFERENCE(Variant);
|
||||
|
||||
// This is for Object.
|
||||
|
||||
template <class T>
|
||||
struct PtrToArg<T *> {
|
||||
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
|
||||
return reinterpret_cast<T *>(godot::internal::interface->object_get_instance_binding(p_ptr, godot::internal::token, T::___binding_callbacks));
|
||||
}
|
||||
typedef Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
p_ptr = p_var->_owner;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct PtrToArg<const T *> {
|
||||
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
|
||||
return reinterpret_cast<const T *>(godot::internal::interface->object_get_instance_binding(p_ptr, godot::internal::token, T::___binding_callbacks));
|
||||
}
|
||||
typedef const Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
p_ptr = p_var->_owner;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_CPP_METHOD_PTRCALL_HPP
|
||||
146
include/godot_cpp/core/object.hpp
Normal file
146
include/godot_cpp/core/object.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*************************************************************************/
|
||||
/* object.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_OBJECT_HPP
|
||||
#define GODOT_OBJECT_HPP
|
||||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
#include <godot_cpp/classes/object.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot/gdnative_interface.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define ADD_SIGNAL(m_signal) ClassDB::add_signal(get_class_static(), m_signal)
|
||||
#define ADD_PROPERTY(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter)
|
||||
|
||||
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 {
|
||||
const char *name;
|
||||
PropertyInfo return_val;
|
||||
uint32_t flags;
|
||||
int id = 0;
|
||||
std::vector<PropertyInfo> arguments;
|
||||
std::vector<Variant> default_arguments;
|
||||
|
||||
inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; }
|
||||
inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }
|
||||
|
||||
operator Dictionary() const;
|
||||
|
||||
static MethodInfo from_dict(const Dictionary &p_dict);
|
||||
|
||||
MethodInfo();
|
||||
MethodInfo(const char *p_name);
|
||||
template <class... Args>
|
||||
MethodInfo(const char *p_name, const Args &...args);
|
||||
MethodInfo(Variant::Type ret);
|
||||
MethodInfo(Variant::Type ret, const char *p_name);
|
||||
template <class... Args>
|
||||
MethodInfo(Variant::Type ret, const char *p_name, const Args &...args);
|
||||
MethodInfo(const PropertyInfo &p_ret, const char *p_name);
|
||||
template <class... Args>
|
||||
MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...);
|
||||
};
|
||||
|
||||
template <class... Args>
|
||||
MethodInfo::MethodInfo(const char *p_name, const Args &...args) :
|
||||
name(p_name), flags(METHOD_FLAG_NORMAL) {
|
||||
arguments = { args... };
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
MethodInfo::MethodInfo(Variant::Type ret, const char *p_name, const Args &...args) :
|
||||
name(p_name), flags(METHOD_FLAG_NORMAL) {
|
||||
return_val.type = ret;
|
||||
arguments = { args... };
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...args) :
|
||||
name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) {
|
||||
arguments = { args... };
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *Object::cast_to(Object *p_object) {
|
||||
GDNativeObjectPtr casted = internal::interface->object_cast_to(p_object->_owner, internal::interface->classdb_get_class_tag(T::get_class_static()));
|
||||
if (casted == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<T *>(internal::interface->object_get_instance_binding(casted, internal::token, &T::___binding_callbacks));
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_OBJECT_HPP
|
||||
178
include/godot_cpp/core/type_info.hpp
Normal file
178
include/godot_cpp/core/type_info.hpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*************************************************************************/
|
||||
/* type_info.hpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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_TYPE_INFO_HPP
|
||||
#define GODOT_TYPE_INFO_HPP
|
||||
|
||||
#include <godot_cpp/core/object.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
#include <godot/gdnative_interface.h>
|
||||
|
||||
namespace godot {
|
||||
|
||||
// If the compiler fails because it's trying to instantiate the primary 'GetTypeInfo' template
|
||||
// instead of one of the specializations, it's most likely because the type 'T' is not supported.
|
||||
// If 'T' is a class that inherits 'Object', make sure it can see the actual class declaration
|
||||
// instead of a forward declaration. You can always forward declare 'T' in a header file, and then
|
||||
// include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated.
|
||||
|
||||
template <class T, typename = void>
|
||||
struct GetTypeInfo;
|
||||
|
||||
#define MAKE_TYPE_INFO(m_type, m_var_type) \
|
||||
template <> \
|
||||
struct GetTypeInfo<m_type> { \
|
||||
static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \
|
||||
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline GDNativePropertyInfo get_class_info() { \
|
||||
return PropertyInfo(VARIANT_TYPE, ""); \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct GetTypeInfo<const m_type &> { \
|
||||
static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \
|
||||
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline GDNativePropertyInfo get_class_info() { \
|
||||
return PropertyInfo(VARIANT_TYPE, ""); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define MAKE_TYPE_INFO_WITH_META(m_type, m_var_type, m_metadata) \
|
||||
template <> \
|
||||
struct GetTypeInfo<m_type> { \
|
||||
static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \
|
||||
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = m_metadata; \
|
||||
static inline GDNativePropertyInfo get_class_info() { \
|
||||
return PropertyInfo(VARIANT_TYPE, ""); \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct GetTypeInfo<const m_type &> { \
|
||||
static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \
|
||||
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = m_metadata; \
|
||||
static inline GDNativePropertyInfo get_class_info() { \
|
||||
return PropertyInfo(VARIANT_TYPE, ""); \
|
||||
} \
|
||||
};
|
||||
|
||||
MAKE_TYPE_INFO(bool, GDNATIVE_VARIANT_TYPE_BOOL)
|
||||
MAKE_TYPE_INFO_WITH_META(uint8_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8)
|
||||
MAKE_TYPE_INFO_WITH_META(int8_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8)
|
||||
MAKE_TYPE_INFO_WITH_META(uint16_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16)
|
||||
MAKE_TYPE_INFO_WITH_META(int16_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16)
|
||||
MAKE_TYPE_INFO_WITH_META(uint32_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32)
|
||||
MAKE_TYPE_INFO_WITH_META(int32_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32)
|
||||
MAKE_TYPE_INFO_WITH_META(uint64_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64)
|
||||
MAKE_TYPE_INFO_WITH_META(int64_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64)
|
||||
MAKE_TYPE_INFO(char16_t, GDNATIVE_VARIANT_TYPE_INT)
|
||||
MAKE_TYPE_INFO(char32_t, GDNATIVE_VARIANT_TYPE_INT)
|
||||
MAKE_TYPE_INFO_WITH_META(float, GDNATIVE_VARIANT_TYPE_FLOAT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT)
|
||||
MAKE_TYPE_INFO_WITH_META(double, GDNATIVE_VARIANT_TYPE_FLOAT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE)
|
||||
|
||||
MAKE_TYPE_INFO(String, GDNATIVE_VARIANT_TYPE_STRING)
|
||||
MAKE_TYPE_INFO(Vector2, GDNATIVE_VARIANT_TYPE_VECTOR2)
|
||||
MAKE_TYPE_INFO(Vector2i, GDNATIVE_VARIANT_TYPE_VECTOR2I)
|
||||
MAKE_TYPE_INFO(Rect2, GDNATIVE_VARIANT_TYPE_RECT2)
|
||||
MAKE_TYPE_INFO(Rect2i, GDNATIVE_VARIANT_TYPE_RECT2I)
|
||||
MAKE_TYPE_INFO(Vector3, GDNATIVE_VARIANT_TYPE_VECTOR3)
|
||||
MAKE_TYPE_INFO(Vector3i, GDNATIVE_VARIANT_TYPE_VECTOR3I)
|
||||
MAKE_TYPE_INFO(Transform2D, GDNATIVE_VARIANT_TYPE_TRANSFORM2D)
|
||||
MAKE_TYPE_INFO(Plane, GDNATIVE_VARIANT_TYPE_PLANE)
|
||||
MAKE_TYPE_INFO(Quaternion, GDNATIVE_VARIANT_TYPE_QUATERNION)
|
||||
MAKE_TYPE_INFO(AABB, GDNATIVE_VARIANT_TYPE_AABB)
|
||||
MAKE_TYPE_INFO(Basis, GDNATIVE_VARIANT_TYPE_BASIS)
|
||||
MAKE_TYPE_INFO(Transform3D, GDNATIVE_VARIANT_TYPE_TRANSFORM3D)
|
||||
MAKE_TYPE_INFO(Color, GDNATIVE_VARIANT_TYPE_COLOR)
|
||||
MAKE_TYPE_INFO(StringName, GDNATIVE_VARIANT_TYPE_STRING_NAME)
|
||||
MAKE_TYPE_INFO(NodePath, GDNATIVE_VARIANT_TYPE_NODE_PATH)
|
||||
MAKE_TYPE_INFO(RID, GDNATIVE_VARIANT_TYPE_RID)
|
||||
MAKE_TYPE_INFO(Callable, GDNATIVE_VARIANT_TYPE_CALLABLE)
|
||||
MAKE_TYPE_INFO(Signal, GDNATIVE_VARIANT_TYPE_SIGNAL)
|
||||
MAKE_TYPE_INFO(Dictionary, GDNATIVE_VARIANT_TYPE_DICTIONARY)
|
||||
MAKE_TYPE_INFO(Array, GDNATIVE_VARIANT_TYPE_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedByteArray, GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedInt32Array, GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedInt64Array, GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedFloat32Array, GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedFloat64Array, GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedStringArray, GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedVector2Array, GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedVector3Array, GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedColorArray, GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY)
|
||||
|
||||
// For variant.
|
||||
template <>
|
||||
struct GetTypeInfo<Variant> {
|
||||
static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_NIL;
|
||||
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static inline GDNativePropertyInfo get_class_info() {
|
||||
return PropertyInfo(GDNATIVE_VARIANT_TYPE_NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GetTypeInfo<const Variant &> {
|
||||
static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_NIL;
|
||||
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static inline GDNativePropertyInfo get_class_info() {
|
||||
return PropertyInfo(GDNATIVE_VARIANT_TYPE_NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||
}
|
||||
};
|
||||
|
||||
#define TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_impl) \
|
||||
template <> \
|
||||
struct GetTypeInfo<m_impl> { \
|
||||
static const Variant::Type VARIANT_TYPE = Variant::INT; \
|
||||
static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline GDNativePropertyInfo get_class_info() { \
|
||||
return PropertyInfo(GDNATIVE_VARIANT_TYPE_INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, #m_class "." #m_enum); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define MAKE_ENUM_TYPE_INFO(m_class, m_enum) \
|
||||
TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_class::m_enum) \
|
||||
TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_class::m_enum const) \
|
||||
TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_class::m_enum &) \
|
||||
TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, const m_class::m_enum &)
|
||||
|
||||
template <typename T>
|
||||
inline const char *__constant_get_enum_name(T param, const char *p_constant) {
|
||||
if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
|
||||
ERR_PRINT(("Missing VARIANT_ENUM_CAST for constant's enum: " + String(p_constant)).utf8().get_data());
|
||||
}
|
||||
return GetTypeInfo<T>::get_class_info().class_name;
|
||||
}
|
||||
|
||||
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // ! GODOT_TYPE_INFO_HPP
|
||||
Reference in New Issue
Block a user