diff --git a/core/SCsub b/core/SCsub index 59fe63b4b36..b9f06d12aee 100644 --- a/core/SCsub +++ b/core/SCsub @@ -3,7 +3,6 @@ Import("env") import core_builders -import make_binders env.core_sources = [] @@ -87,11 +86,7 @@ if env["builtin_zlib"]: # Minizip library, could be unbundled in theory # However, our version has some custom modifications, so it won't compile with the system one thirdparty_minizip_dir = "#thirdparty/minizip/" -thirdparty_minizip_sources = [ - "ioapi.c", - "unzip.c", - "zip.c", -] +thirdparty_minizip_sources = ["ioapi.c", "unzip.c", "zip.c"] thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources] env_thirdparty.add_source_files(env.core_sources, thirdparty_minizip_sources) @@ -152,27 +147,16 @@ env.CommandNoCache( env.Run(core_builders.make_certs_header, "Building ca-certificates header."), ) -# Make binders -env.CommandNoCache( - ["method_bind.gen.inc", "method_bind_ext.gen.inc", "method_bind_free_func.gen.inc"], - "make_binders.py", - env.Run(make_binders.run, "Generating method binders."), -) - # Authors env.Depends("#core/authors.gen.h", "../AUTHORS.md") env.CommandNoCache( - "#core/authors.gen.h", - "../AUTHORS.md", - env.Run(core_builders.make_authors_header, "Generating authors header."), + "#core/authors.gen.h", "../AUTHORS.md", env.Run(core_builders.make_authors_header, "Generating authors header.") ) # Donors env.Depends("#core/donors.gen.h", "../DONORS.md") env.CommandNoCache( - "#core/donors.gen.h", - "../DONORS.md", - env.Run(core_builders.make_donors_header, "Generating donors header."), + "#core/donors.gen.h", "../DONORS.md", env.Run(core_builders.make_donors_header, "Generating donors header.") ) # License diff --git a/core/array.cpp b/core/array.cpp index 3c6c8e768bf..c6e90d71ec8 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -31,8 +31,8 @@ #include "array.h" #include "container_type_validate.h" +#include "core/class_db.h" #include "core/hashfuncs.h" -#include "core/object.h" #include "core/script_language.h" #include "core/variant.h" #include "core/vector.h" diff --git a/core/binder_common.h b/core/binder_common.h new file mode 100644 index 00000000000..0fbfa56230a --- /dev/null +++ b/core/binder_common.h @@ -0,0 +1,657 @@ +/*************************************************************************/ +/* binder_common.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 BINDER_COMMON_H +#define BINDER_COMMON_H + +#include "core/list.h" +#include "core/method_ptrcall.h" +#include "core/object.h" +#include "core/simple_type.h" +#include "core/type_info.h" +#include "core/typedefs.h" +#include "core/variant.h" +#include "core/variant_internal.h" + +#include + +template +struct VariantCaster { + static _FORCE_INLINE_ T cast(const Variant &p_variant) { + return p_variant; + } +}; + +template +struct VariantCaster { + static _FORCE_INLINE_ T cast(const Variant &p_variant) { + return p_variant; + } +}; + +template +struct VariantCaster { + static _FORCE_INLINE_ T cast(const Variant &p_variant) { + return p_variant; + } +}; + +#ifdef PTRCALL_ENABLED + +#define VARIANT_ENUM_CAST(m_enum) \ + MAKE_ENUM_TYPE_INFO(m_enum) \ + template <> \ + struct VariantCaster { \ + static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ + return (m_enum)p_variant.operator int(); \ + } \ + }; \ + template <> \ + struct PtrToArg { \ + _FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \ + return m_enum(*reinterpret_cast(p_ptr)); \ + } \ + _FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \ + *(int *)p_ptr = p_val; \ + } \ + }; + +#else + +#define VARIANT_ENUM_CAST(m_enum) \ + MAKE_ENUM_TYPE_INFO(m_enum) \ + template <> \ + struct VariantCaster { \ + static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ + return (m_enum)p_variant.operator int(); \ + } \ + }; + +#endif + +// Object enum casts must go here +VARIANT_ENUM_CAST(Object::ConnectFlags); + +VARIANT_ENUM_CAST(Vector3::Axis); + +VARIANT_ENUM_CAST(Error); +VARIANT_ENUM_CAST(Margin); +VARIANT_ENUM_CAST(Corner); +VARIANT_ENUM_CAST(Orientation); +VARIANT_ENUM_CAST(HAlign); +VARIANT_ENUM_CAST(VAlign); +VARIANT_ENUM_CAST(PropertyHint); +VARIANT_ENUM_CAST(PropertyUsageFlags); +VARIANT_ENUM_CAST(Variant::Type); +VARIANT_ENUM_CAST(Variant::Operator); + +template <> +struct VariantCaster { + static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) { + return (char32_t)p_variant.operator int(); + } +}; +#ifdef PTRCALL_ENABLED +template <> +struct PtrToArg { + _FORCE_INLINE_ static char32_t convert(const void *p_ptr) { + return char32_t(*reinterpret_cast(p_ptr)); + } + _FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) { + *(int *)p_ptr = p_val; + } +}; +#endif + +template +struct VariantObjectClassChecker { + static _FORCE_INLINE_ bool check(const Variant &p_variant) { + return true; + } +}; + +template <> +struct VariantObjectClassChecker { + static _FORCE_INLINE_ bool check(const Variant &p_variant) { + Object *obj = p_variant; + Node *node = p_variant; + return node || !obj; + } +}; + +template <> +struct VariantObjectClassChecker { + static _FORCE_INLINE_ bool check(const Variant &p_variant) { + Object *obj = p_variant; + Control *control = p_variant; + return control || !obj; + } +}; + +#ifdef DEBUG_METHODS_ENABLED + +template +struct VariantCasterAndValidate { + static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { + Variant::Type argtype = GetTypeInfo::VARIANT_TYPE; + if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || + !VariantObjectClassChecker::check(p_args[p_arg_idx])) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = p_arg_idx; + r_error.expected = argtype; + } + + return VariantCaster::cast(*p_args[p_arg_idx]); + } +}; + +template +struct VariantCasterAndValidate { + static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { + Variant::Type argtype = GetTypeInfo::VARIANT_TYPE; + if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || + !VariantObjectClassChecker::check(p_args[p_arg_idx])) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = p_arg_idx; + r_error.expected = argtype; + } + + return VariantCaster::cast(*p_args[p_arg_idx]); + } +}; + +template +struct VariantCasterAndValidate { + static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { + Variant::Type argtype = GetTypeInfo::VARIANT_TYPE; + if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || + !VariantObjectClassChecker::check(p_args[p_arg_idx])) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = p_arg_idx; + r_error.expected = argtype; + } + + return VariantCaster::cast(*p_args[p_arg_idx]); + } +}; + +#endif // DEBUG_METHODS_ENABLED + +template +void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + (p_instance->*p_method)(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); +#else + (p_instance->*p_method)(VariantCaster

::cast(*p_args[Is])...); +#endif + (void)(p_args); //avoid warning +} + +template +void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + (p_instance->*p_method)(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); +#else + (p_instance->*p_method)(VariantCaster

::cast(*p_args[Is])...); +#endif + (void)(p_args); //avoid warning +} + +#ifdef PTRCALL_ENABLED + +template +void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const void **p_args, IndexSequence) { + (p_instance->*p_method)(PtrToArg

::convert(p_args[Is])...); +} + +template +void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const void **p_args, IndexSequence) { + (p_instance->*p_method)(PtrToArg

::convert(p_args[Is])...); +} + +template +void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret, IndexSequence) { + PtrToArg::encode((p_instance->*p_method)(PtrToArg

::convert(p_args[Is])...), r_ret); +} + +template +void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret, IndexSequence) { + PtrToArg::encode((p_instance->*p_method)(PtrToArg

::convert(p_args[Is])...), r_ret); +} + +template +void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret, IndexSequence) { + PtrToArg::encode(p_method(p_instance, PtrToArg

::convert(p_args[Is])...), r_ret); +} + +#endif // PTRCALL_ENABLED + +template +void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence) { + (p_instance->*p_method)((VariantInternalAccessor::type_t>::get(p_args[Is]))...); +} + +template +void call_with_validated_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, IndexSequence) { + (p_instance->*p_method)((VariantInternalAccessor::type_t>::get(p_args[Is]))...); +} + +template +void call_with_validated_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence) { + VariantInternalAccessor::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor::type_t>::get(p_args[Is]))...)); +} + +template +void call_with_validated_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret, IndexSequence) { + VariantInternalAccessor::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor::type_t>::get(p_args[Is]))...)); +} + +template +void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret, IndexSequence) { + VariantInternalAccessor::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor::type_t>::get(p_args[Is]))...)); +} + +template +void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_helper(p_instance, p_method, p_args, r_error, BuildIndexSequence{}); +} + +template +void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::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 = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + 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)]; + } + } + + call_with_variant_args_helper(p_instance, p_method, args, r_error, BuildIndexSequence{}); +} + +template +void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_helper(p_instance, p_method, p_args, r_error, BuildIndexSequence{}); +} + +template +void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::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 = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + 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)]; + } + } + + call_with_variant_argsc_helper(p_instance, p_method, args, r_error, BuildIndexSequence{}); +} + +template +void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::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 = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + 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)]; + } + } + + call_with_variant_args_ret_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence{}); +} + +template +void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::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 = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + 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)]; + } + } + + call_with_variant_args_retc_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence{}); +} + +#ifdef PTRCALL_ENABLED + +template +void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const void **p_args) { + call_with_ptr_args_helper(p_instance, p_method, p_args, BuildIndexSequence{}); +} + +template +void call_with_ptr_argsc(T *p_instance, void (T::*p_method)(P...) const, const void **p_args) { + call_with_ptr_argsc_helper(p_instance, p_method, p_args, BuildIndexSequence{}); +} + +template +void call_with_ptr_args_ret(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret) { + call_with_ptr_args_ret_helper(p_instance, p_method, p_args, r_ret, BuildIndexSequence{}); +} + +template +void call_with_ptr_args_retc(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret) { + call_with_ptr_args_retc_helper(p_instance, p_method, p_args, r_ret, BuildIndexSequence{}); +} + +template +void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret) { + call_with_ptr_args_static_retc_helper(p_instance, p_method, p_args, r_ret, BuildIndexSequence{}); +} + +#endif // PTRCALL_ENABLED + +template +void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) { + call_with_validated_variant_args_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, BuildIndexSequence{}); +} + +template +void call_with_validated_variant_args_ret(Variant *base, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_ret_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence{}); +} + +template +void call_with_validated_variant_args_retc(Variant *base, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_retc_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence{}); +} + +template +void call_with_validated_variant_args_static_retc(Variant *base, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_static_retc_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence{}); +} + +// 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 + +#ifdef DEBUG_METHODS_ENABLED + +template +void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) { + if (p_arg == index) { + type = GetTypeInfo::VARIANT_TYPE; + } + index++; +} + +template +Variant::Type call_get_argument_type(int p_arg) { + Variant::Type type = Variant::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_arg, index, type), 0)... }; + (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. + (void)index; // Suppress GCC warning. + return type; +} + +template +void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) { + if (p_arg == index) { + info = GetTypeInfo::get_class_info(); + } + index++; +} + +template +void call_get_argument_type_info(int p_arg, PropertyInfo &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_arg, index, info), 0)... }; + (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. + (void)index; // Suppress GCC warning. +} + +template +void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Metadata &md) { + if (p_arg == index) { + md = GetTypeInfo::METADATA; + } + index++; +} + +template +GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) { + GodotTypeInfo::Metadata md = GodotTypeInfo::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_arg, index, md), 0)... }; + (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. + (void)index; + return md; +} + +#else + +template +Variant::Type call_get_argument_type(int p_arg) { + return Variant::NIL; +} + +#endif // DEBUG_METHODS_ENABLED + +////////////////////// + +template +void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + r_ret = (p_instance->*p_method)(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); +#else + r_ret = (p_instance->*p_method)(VariantCaster

::cast(*p_args[Is])...); +#endif +} + +template +void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_ret_helper(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence{}); +} + +template +void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + r_ret = (p_instance->*p_method)(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); +#else + r_ret = (p_instance->*p_method)(VariantCaster

::cast(*p_args[Is])...); +#endif + (void)p_args; +} + +template +void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_retc_helper(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence{}); +} + +template +void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + r_ret = (p_method)(p_instance, VariantCasterAndValidate

::cast(p_args, Is, r_error)...); +#else + r_ret = (p_method)(p_instance, VariantCaster

::cast(*p_args[Is])...); +#endif + + (void)p_args; +} + +#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // BINDER_COMMON_H diff --git a/core/callable_method_pointer.h b/core/callable_method_pointer.h index a2275452b40..2007b9f338c 100644 --- a/core/callable_method_pointer.h +++ b/core/callable_method_pointer.h @@ -31,12 +31,12 @@ #ifndef CALLABLE_METHOD_POINTER_H #define CALLABLE_METHOD_POINTER_H +#include "core/binder_common.h" #include "core/callable.h" #include "core/hashfuncs.h" #include "core/object.h" #include "core/os/copymem.h" #include "core/simple_type.h" -#include "core/variant_internal.h" class CallableCustomMethodPointerBase : public CallableCustom { uint32_t *comp_ptr; @@ -70,219 +70,6 @@ public: virtual uint32_t hash() const; }; -#ifdef DEBUG_METHODS_ENABLED - -template -struct VariantCasterAndValidate { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { - Variant::Type argtype = GetTypeInfo::VARIANT_TYPE; - if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = p_arg_idx; - r_error.expected = argtype; - } - - return VariantCaster::cast(*p_args[p_arg_idx]); - } -}; - -template -struct VariantCasterAndValidate { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { - Variant::Type argtype = GetTypeInfo::VARIANT_TYPE; - if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = p_arg_idx; - r_error.expected = argtype; - } - - return VariantCaster::cast(*p_args[p_arg_idx]); - } -}; - -template -struct VariantCasterAndValidate { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { - Variant::Type argtype = GetTypeInfo::VARIANT_TYPE; - if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = p_arg_idx; - r_error.expected = argtype; - } - - return VariantCaster::cast(*p_args[p_arg_idx]); - } -}; - -#endif // DEBUG_METHODS_ENABLED - -// GCC raises "parameter 'p_args' set but not used" here, probably using a -// template version that does not have arguments and thus sees it unused, but -// obviously the template can be used for functions with and without them, and -// the optimizer will get rid of it anyway. -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" -#endif - -template -void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence) { - r_error.error = Callable::CallError::CALL_OK; - -#ifdef DEBUG_METHODS_ENABLED - (p_instance->*p_method)(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); -#else - (p_instance->*p_method)(VariantCaster

::cast(*p_args[Is])...); -#endif -} - -#ifdef PTRCALL_ENABLED - -template -void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const void **p_args, IndexSequence) { - (p_instance->*p_method)(PtrToArg

::convert(p_args[Is])...); -} - -template -void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret, IndexSequence) { - PtrToArg::encode((p_instance->*p_method)(PtrToArg

::convert(p_args[Is])...), r_ret); -} - -template -void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret, IndexSequence) { - PtrToArg::encode((p_instance->*p_method)(PtrToArg

::convert(p_args[Is])...), r_ret); -} - -template -void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret, IndexSequence) { - PtrToArg::encode(p_method(p_instance, PtrToArg

::convert(p_args[Is])...), r_ret); -} - -#endif // PTRCALL_ENABLED - -template -void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence) { - (p_instance->*p_method)((VariantInternalAccessor::type_t>::get(p_args[Is]))...); -} - -template -void call_with_validated_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence) { - VariantInternalAccessor::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor::type_t>::get(p_args[Is]))...)); -} - -template -void call_with_validated_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret, IndexSequence) { - VariantInternalAccessor::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor::type_t>::get(p_args[Is]))...)); -} - -template -void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret, IndexSequence) { - VariantInternalAccessor::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor::type_t>::get(p_args[Is]))...)); -} - -template -void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) { -#ifdef DEBUG_METHODS_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } - - if ((size_t)p_argcount < sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } -#endif - call_with_variant_args_helper(p_instance, p_method, p_args, r_error, BuildIndexSequence{}); -} - -#ifdef PTRCALL_ENABLED - -template -void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const void **p_args) { - call_with_ptr_args_helper(p_instance, p_method, p_args, BuildIndexSequence{}); -} - -template -void call_with_ptr_args_ret(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret) { - call_with_ptr_args_ret_helper(p_instance, p_method, p_args, r_ret, BuildIndexSequence{}); -} - -template -void call_with_ptr_args_retc(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret) { - call_with_ptr_args_retc_helper(p_instance, p_method, p_args, r_ret, BuildIndexSequence{}); -} - -template -void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret) { - call_with_ptr_args_static_retc_helper(p_instance, p_method, p_args, r_ret, BuildIndexSequence{}); -} - -#endif // PTRCALL_ENABLED - -template -void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) { - call_with_validated_variant_args_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, BuildIndexSequence{}); -} - -template -void call_with_validated_variant_args_ret(Variant *base, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret) { - call_with_validated_variant_args_ret_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence{}); -} - -template -void call_with_validated_variant_args_retc(Variant *base, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret) { - call_with_validated_variant_args_retc_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence{}); -} - -template -void call_with_validated_variant_args_static_retc(Variant *base, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret) { - call_with_validated_variant_args_static_retc_helper(VariantGetInternalPtr::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence{}); -} - -#ifdef DEBUG_METHODS_ENABLED - -template -void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) { - if (p_arg == index) { - type = GetTypeInfo::VARIANT_TYPE; - } - index++; -} - -// GCC's warnings checker really doesn't like variadic voodoo. -// It sees `index` unused below in some branches, so it raises a warning. -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" -#endif - -template -Variant::Type call_get_argument_type(int p_arg) { - Variant::Type type = Variant::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_arg, index, type), 0)... }; - (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. - return type; -} - -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - -#else - -template -Variant::Type call_get_argument_type(int p_arg) { - return Variant::NIL; -} - -#endif // DEBUG_METHODS_ENABLED - template class CallableCustomMethodPointer : public CallableCustomMethodPointerBase { struct Data { @@ -338,35 +125,6 @@ Callable create_custom_callable_function_pointer(T *p_instance, // VERSION WITH RETURN -template -void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence) { - r_error.error = Callable::CallError::CALL_OK; - -#ifdef DEBUG_METHODS_ENABLED - r_ret = (p_instance->*p_method)(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); -#else - r_ret = (p_instance->*p_method)(VariantCaster

::cast(*p_args[Is])...); -#endif -} - -template -void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { -#ifdef DEBUG_METHODS_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } - - if ((size_t)p_argcount < sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } -#endif - call_with_variant_args_ret_helper(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence{}); -} - template class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { struct Data { @@ -423,35 +181,6 @@ Callable create_custom_callable_function_pointer(T *p_instance, // CONST VERSION WITH RETURN -template -void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence) { - r_error.error = Callable::CallError::CALL_OK; - -#ifdef DEBUG_METHODS_ENABLED - r_ret = (p_instance->*p_method)(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); -#else - r_ret = (p_instance->*p_method)(VariantCaster

::cast(*p_args[Is])...); -#endif -} - -template -void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { -#ifdef DEBUG_METHODS_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } - - if ((size_t)p_argcount < sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } -#endif - call_with_variant_args_retc_helper(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence{}); -} - template class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase { struct Data { @@ -512,19 +241,4 @@ Callable create_custom_callable_function_pointer(T *p_instance, #define callable_mp(I, M) create_custom_callable_function_pointer(I, M) #endif -template -void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence) { - r_error.error = Callable::CallError::CALL_OK; - -#ifdef DEBUG_METHODS_ENABLED - r_ret = (p_method)(p_instance, VariantCasterAndValidate

::cast(p_args, Is, r_error)...); -#else - r_ret = (p_method)(p_instance, VariantCaster

::cast(*p_args[Is])...); -#endif -} - -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - #endif // CALLABLE_METHOD_POINTER_H diff --git a/core/class_db.cpp b/core/class_db.cpp index 88f1df3457f..ad85cd0d623 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -1343,7 +1343,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c defvals.resize(p_defcount); for (int i = 0; i < p_defcount; i++) { - defvals.write[i] = *p_defs[p_defcount - i - 1]; + defvals.write[i] = *p_defs[i]; } p_bind->set_default_arguments(defvals); diff --git a/core/class_db.h b/core/class_db.h index 86ac2aa0010..4734b06c7a6 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -36,7 +36,7 @@ #include "core/print_string.h" /** To bind more then 6 parameters include this: - * #include "core/method_bind_ext.gen.inc" + * */ // Makes callable_mp readily available in all classes connecting signals. diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index dc7e4436e1e..320ee15996f 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -32,10 +32,10 @@ #define REMOTE_DEBUGGER_H #include "core/array.h" +#include "core/class_db.h" #include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/remote_debugger_peer.h" -#include "core/object.h" #include "core/string_name.h" #include "core/ustring.h" diff --git a/core/global_constants.cpp b/core/global_constants.cpp index b30685539ac..064c3023415 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -30,8 +30,8 @@ #include "global_constants.h" +#include "core/class_db.h" #include "core/input/input_event.h" -#include "core/object.h" #include "core/os/keyboard.h" #include "core/variant.h" diff --git a/core/input/input_map.h b/core/input/input_map.h index 548553ed318..755df269844 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -31,8 +31,8 @@ #ifndef INPUT_MAP_H #define INPUT_MAP_H +#include "core/class_db.h" #include "core/input/input_event.h" -#include "core/object.h" class InputMap : public Object { GDCLASS(InputMap, Object); diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 92cdbc41514..fb4dc181db4 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -31,8 +31,8 @@ #ifndef PACKET_PEER_H #define PACKET_PEER_H +#include "core/class_db.h" #include "core/io/stream_peer.h" -#include "core/object.h" #include "core/ring_buffer.h" class PacketPeer : public Reference { diff --git a/core/make_binders.py b/core/make_binders.py deleted file mode 100644 index 7d0d08cde62..00000000000 --- a/core/make_binders.py +++ /dev/null @@ -1,390 +0,0 @@ -# -*- coding: ibm850 -*- - -template_typed = """ -#ifdef TYPED_METHOD_BIND -template -class MethodBind$argc$$ifret R$$ifconst C$ : public MethodBind { -public: - - $ifret R$ $ifnoret void$ (T::*method)($arg, P@$) $ifconst const$; -#ifdef DEBUG_METHODS_ENABLED - virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { - $ifret if (p_arg==-1) return GetTypeInfo::METADATA;$ - $arg if (p_arg==(@-1)) return GetTypeInfo::METADATA; - $ - return GodotTypeInfo::METADATA_NONE; - } - Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo::VARIANT_TYPE;$ - $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo::VARIANT_TYPE; - $ - return Variant::NIL; - } - virtual PropertyInfo _gen_argument_type_info(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo::get_class_info();$ - $arg if (p_argument==(@-1)) return GetTypeInfo::get_class_info(); - $ - return PropertyInfo(); - } -#endif - virtual String get_instance_class() const { - return T::get_class_static(); - } - - virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Callable::CallError& r_error) { - - T *instance=Object::cast_to(p_object); - r_error.error=Callable::CallError::CALL_OK; -#ifdef DEBUG_METHODS_ENABLED - - ERR_FAIL_COND_V(!instance,Variant()); - if (p_arg_count>get_argument_count()) { - r_error.error=Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument=get_argument_count(); - return Variant(); - - } - if (p_arg_count<(get_argument_count()-get_default_argument_count())) { - - r_error.error=Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument=get_argument_count()-get_default_argument_count(); - return Variant(); - } - $arg CHECK_ARG(@); - $ -#endif - $ifret Variant ret = $(instance->*method)($arg, _VC(@)$); - $ifret return Variant(ret);$ - $ifnoret return Variant();$ - } - -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) { - - T *instance=Object::cast_to(p_object); - $ifret PtrToArg::encode( $ (instance->*method)($arg, PtrToArg::convert(p_args[@-1])$) $ifret ,r_ret)$ ; - } -#endif - MethodBind$argc$$ifret R$$ifconst C$ () { -#ifdef DEBUG_METHODS_ENABLED - _set_const($ifconst true$$ifnoconst false$); - _generate_argument_types($argc$); -#else - set_argument_count($argc$); -#endif - - $ifret _set_returns(true); $ - } -}; - -template -MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$) $ifconst const$ ) { - - MethodBind$argc$$ifret R$$ifconst C$ * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$) ); - a->method=p_method; - return a; -} -#endif -""" - -template = """ -#ifndef TYPED_METHOD_BIND -$iftempl template<$ $ifret class R$ $ifretargs ,$ $arg, class P@$ $iftempl >$ -class MethodBind$argc$$ifret R$$ifconst C$ : public MethodBind { - -public: - - StringName type_name; - $ifret R$ $ifnoret void$ (__UnexistingClass::*method)($arg, P@$) $ifconst const$; - -#ifdef DEBUG_METHODS_ENABLED - virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { - $ifret if (p_arg==-1) return GetTypeInfo::METADATA;$ - $arg if (p_arg==(@-1)) return GetTypeInfo::METADATA; - $ - return GodotTypeInfo::METADATA_NONE; - } - - Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo::VARIANT_TYPE;$ - $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo::VARIANT_TYPE; - $ - return Variant::NIL; - } - - virtual PropertyInfo _gen_argument_type_info(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo::get_class_info();$ - $arg if (p_argument==(@-1)) return GetTypeInfo::get_class_info(); - $ - return PropertyInfo(); - } - -#endif - virtual String get_instance_class() const { - return type_name; - } - - virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Callable::CallError& r_error) { - - __UnexistingClass *instance = (__UnexistingClass*)p_object; - - r_error.error=Callable::CallError::CALL_OK; -#ifdef DEBUG_METHODS_ENABLED - - ERR_FAIL_COND_V(!instance,Variant()); - if (p_arg_count>get_argument_count()) { - r_error.error=Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument=get_argument_count(); - return Variant(); - } - - if (p_arg_count<(get_argument_count()-get_default_argument_count())) { - - r_error.error=Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument=get_argument_count()-get_default_argument_count(); - return Variant(); - } - - $arg CHECK_ARG(@); - $ -#endif - $ifret Variant ret = $(instance->*method)($arg, _VC(@)$); - $ifret return Variant(ret);$ - $ifnoret return Variant();$ - } -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) { - __UnexistingClass *instance = (__UnexistingClass*)p_object; - $ifret PtrToArg::encode( $ (instance->*method)($arg, PtrToArg::convert(p_args[@-1])$) $ifret ,r_ret) $ ; - } -#endif - MethodBind$argc$$ifret R$$ifconst C$ () { -#ifdef DEBUG_METHODS_ENABLED - _set_const($ifconst true$$ifnoconst false$); - _generate_argument_types($argc$); -#else - set_argument_count($argc$); -#endif - $ifret _set_returns(true); $ - - - } -}; - -template -MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$) $ifconst const$ ) { - - MethodBind$argc$$ifret R$$ifconst C$ $iftempl <$ $ifret R$ $ifretargs ,$ $arg, P@$ $iftempl >$ * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$ $iftempl <$ $ifret R$ $ifretargs ,$ $arg, P@$ $iftempl >$) ); - union { - - $ifret R$ $ifnoret void$ (T::*sm)($arg, P@$) $ifconst const$; - $ifret R$ $ifnoret void$ (__UnexistingClass::*dm)($arg, P@$) $ifconst const$; - } u; - u.sm=p_method; - a->method=u.dm; - a->type_name=T::get_class_static(); - return a; -} -#endif -""" - - -template_typed_free_func = """ -#ifdef TYPED_METHOD_BIND -template -class FunctionBind$argc$$ifret R$$ifconst C$ : public MethodBind { -public: - - $ifret R$ $ifnoret void$ (*method) ($ifconst const$ T *$ifargs , $$arg, P@$); -#ifdef DEBUG_METHODS_ENABLED - virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { - $ifret if (p_arg==-1) return GetTypeInfo::METADATA;$ - $arg if (p_arg==(@-1)) return GetTypeInfo::METADATA; - $ - return GodotTypeInfo::METADATA_NONE; - } - Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo::VARIANT_TYPE;$ - $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo::VARIANT_TYPE; - $ - return Variant::NIL; - } - virtual PropertyInfo _gen_argument_type_info(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo::get_class_info();$ - $arg if (p_argument==(@-1)) return GetTypeInfo::get_class_info(); - $ - return PropertyInfo(); - } -#endif - virtual String get_instance_class() const { - return T::get_class_static(); - } - - virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Callable::CallError& r_error) { - - T *instance=Object::cast_to(p_object); - r_error.error=Callable::CallError::CALL_OK; -#ifdef DEBUG_METHODS_ENABLED - - ERR_FAIL_COND_V(!instance,Variant()); - if (p_arg_count>get_argument_count()) { - r_error.error=Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument=get_argument_count(); - return Variant(); - - } - if (p_arg_count<(get_argument_count()-get_default_argument_count())) { - - r_error.error=Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument=get_argument_count()-get_default_argument_count(); - return Variant(); - } - $arg CHECK_ARG(@); - $ -#endif - $ifret Variant ret = $(method)(instance$ifargs , $$arg, _VC(@)$); - $ifret return Variant(ret);$ - $ifnoret return Variant();$ - } - -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) { - - T *instance=Object::cast_to(p_object); - $ifret PtrToArg::encode( $ (method)(instance$ifargs , $$arg, PtrToArg::convert(p_args[@-1])$) $ifret ,r_ret)$ ; - } -#endif - FunctionBind$argc$$ifret R$$ifconst C$ () { -#ifdef DEBUG_METHODS_ENABLED - _set_const($ifconst true$$ifnoconst false$); - _generate_argument_types($argc$); -#else - set_argument_count($argc$); -#endif - - $ifret _set_returns(true); $ - } -}; - -template -MethodBind* create_method_bind($ifret R$ $ifnoret void$ (*p_method)($ifconst const$ T *$ifargs , $$arg, P@$) ) { - - FunctionBind$argc$$ifret R$$ifconst C$ * a = memnew( (FunctionBind$argc$$ifret R$$ifconst C$) ); - a->method=p_method; - return a; -} -#endif -""" - - -def make_version(template, nargs, argmax, const, ret): - - intext = template - from_pos = 0 - outtext = "" - - while True: - to_pos = intext.find("$", from_pos) - if to_pos == -1: - outtext += intext[from_pos:] - break - else: - outtext += intext[from_pos:to_pos] - end = intext.find("$", to_pos + 1) - if end == -1: - break # ignore - macro = intext[to_pos + 1 : end] - cmd = "" - data = "" - - if macro.find(" ") != -1: - cmd = macro[0 : macro.find(" ")] - data = macro[macro.find(" ") + 1 :] - else: - cmd = macro - - if cmd == "argc": - outtext += str(nargs) - if cmd == "ifret" and ret: - outtext += data - if cmd == "ifargs" and nargs: - outtext += data - if cmd == "ifretargs" and nargs and ret: - outtext += data - if cmd == "ifconst" and const: - outtext += data - elif cmd == "ifnoconst" and not const: - outtext += data - elif cmd == "ifnoret" and not ret: - outtext += data - elif cmd == "iftempl" and (nargs > 0 or ret): - outtext += data - elif cmd == "arg,": - for i in range(1, nargs + 1): - if i > 1: - outtext += ", " - outtext += data.replace("@", str(i)) - elif cmd == "arg": - for i in range(1, nargs + 1): - outtext += data.replace("@", str(i)) - elif cmd == "noarg": - for i in range(nargs + 1, argmax + 1): - outtext += data.replace("@", str(i)) - - from_pos = end + 1 - - return outtext - - -def run(target, source, env): - - versions = 15 - versions_ext = 6 - text = "" - text_ext = "" - text_free_func = "#ifndef METHOD_BIND_FREE_FUNC_H\n#define METHOD_BIND_FREE_FUNC_H\n" - text_free_func += "\n//including this header file allows method binding to use free functions\n" - text_free_func += ( - "//note that the free function must have a pointer to an instance of the class as its first parameter\n" - ) - - for i in range(0, versions + 1): - - t = "" - t += make_version(template, i, versions, False, False) - t += make_version(template_typed, i, versions, False, False) - t += make_version(template, i, versions, False, True) - t += make_version(template_typed, i, versions, False, True) - t += make_version(template, i, versions, True, False) - t += make_version(template_typed, i, versions, True, False) - t += make_version(template, i, versions, True, True) - t += make_version(template_typed, i, versions, True, True) - if i >= versions_ext: - text_ext += t - else: - text += t - - text_free_func += make_version(template_typed_free_func, i, versions, False, False) - text_free_func += make_version(template_typed_free_func, i, versions, False, True) - text_free_func += make_version(template_typed_free_func, i, versions, True, False) - text_free_func += make_version(template_typed_free_func, i, versions, True, True) - - text_free_func += "#endif" - - with open(target[0], "w") as f: - f.write(text) - - with open(target[1], "w") as f: - f.write(text_ext) - - with open(target[2], "w") as f: - f.write(text_free_func) - - -if __name__ == "__main__": - from platform_methods import subprocess_main - - subprocess_main(globals()) diff --git a/core/message_queue.h b/core/message_queue.h index 710a6053719..5d39ceee03c 100644 --- a/core/message_queue.h +++ b/core/message_queue.h @@ -31,7 +31,7 @@ #ifndef MESSAGE_QUEUE_H #define MESSAGE_QUEUE_H -#include "core/object.h" +#include "core/class_db.h" #include "core/os/thread_safe.h" class MessageQueue { diff --git a/core/method_bind.h b/core/method_bind.h index 942e2e0036e..d43186257b4 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -31,18 +31,7 @@ #ifndef METHOD_BIND_H #define METHOD_BIND_H -#ifdef DEBUG_ENABLED -#define DEBUG_METHODS_ENABLED -#endif - -#include "core/list.h" -#include "core/method_ptrcall.h" -#include "core/object.h" -#include "core/type_info.h" -#include "core/typedefs.h" -#include "core/variant.h" - -#include +#include "core/binder_common.h" enum MethodFlags { @@ -57,151 +46,15 @@ enum MethodFlags { METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL, }; -template -struct VariantCaster { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; - } -}; - -template -struct VariantCaster { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; - } -}; - -template -struct VariantCaster { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; - } -}; - -#define _VC(m_idx) \ - (VariantCaster::cast((m_idx - 1) >= p_arg_count ? get_default_argument(m_idx - 1) : *p_args[m_idx - 1])) - -#ifdef PTRCALL_ENABLED - -#define VARIANT_ENUM_CAST(m_enum) \ - MAKE_ENUM_TYPE_INFO(m_enum) \ - template <> \ - struct VariantCaster { \ - static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ - return (m_enum)p_variant.operator int(); \ - } \ - }; \ - template <> \ - struct PtrToArg { \ - _FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \ - return m_enum(*reinterpret_cast(p_ptr)); \ - } \ - _FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \ - *(int *)p_ptr = p_val; \ - } \ - }; - -#else - -#define VARIANT_ENUM_CAST(m_enum) \ - MAKE_ENUM_TYPE_INFO(m_enum) \ - template <> \ - struct VariantCaster { \ - static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ - return (m_enum)p_variant.operator int(); \ - } \ - }; - -#endif - -// Object enum casts must go here -VARIANT_ENUM_CAST(Object::ConnectFlags); - -template -struct VariantObjectClassChecker { - static _FORCE_INLINE_ bool check(const Variant &p_variant) { - return true; - } -}; - -template <> -struct VariantObjectClassChecker { - static _FORCE_INLINE_ bool check(const Variant &p_variant) { - Object *obj = p_variant; - Node *node = p_variant; - return node || !obj; - } -}; - -template <> -struct VariantObjectClassChecker { - static _FORCE_INLINE_ bool check(const Variant &p_variant) { - Object *obj = p_variant; - Control *control = p_variant; - return control || !obj; - } -}; - -#define CHECK_ARG(m_arg) \ - if ((m_arg - 1) < p_arg_count) { \ - Variant::Type argtype = get_argument_type(m_arg - 1); \ - if (!Variant::can_convert_strict(p_args[m_arg - 1]->get_type(), argtype) || \ - !VariantObjectClassChecker::check(*p_args[m_arg - 1])) { \ - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \ - r_error.argument = m_arg - 1; \ - r_error.expected = argtype; \ - return Variant(); \ - } \ - } - -#define CHECK_NOARG(m_arg) \ - { \ - if (p_arg##m_arg.get_type() != Variant::NIL) { \ - if (r_argerror) { \ - *r_argerror = (m_arg - 1); \ - } \ - return CALL_ERROR_EXTRA_ARGUMENT; \ - } \ - } +VARIANT_ENUM_CAST(MethodFlags) // some helpers -VARIANT_ENUM_CAST(Vector3::Axis); - -VARIANT_ENUM_CAST(Error); -VARIANT_ENUM_CAST(Margin); -VARIANT_ENUM_CAST(Corner); -VARIANT_ENUM_CAST(Orientation); -VARIANT_ENUM_CAST(HAlign); -VARIANT_ENUM_CAST(VAlign); -VARIANT_ENUM_CAST(PropertyHint); -VARIANT_ENUM_CAST(PropertyUsageFlags); -VARIANT_ENUM_CAST(MethodFlags); -VARIANT_ENUM_CAST(Variant::Type); -VARIANT_ENUM_CAST(Variant::Operator); - -template <> -struct VariantCaster { - static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) { - return (char32_t)p_variant.operator int(); - } -}; -#ifdef PTRCALL_ENABLED -template <> -struct PtrToArg { - _FORCE_INLINE_ static char32_t convert(const void *p_ptr) { - return char32_t(*reinterpret_cast(p_ptr)); - } - _FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) { - *(int *)p_ptr = p_val; - } -}; -#endif - class MethodBind { int method_id; uint32_t hint_flags = METHOD_FLAGS_DEFAULT; StringName name; + StringName instance_class; Vector default_arguments; int default_argument_count = 0; int argument_count = 0; @@ -225,11 +78,11 @@ protected: void set_argument_count(int p_count) { argument_count = p_count; } public: - Vector get_default_arguments() const { return default_arguments; } + _FORCE_INLINE_ const Vector &get_default_arguments() const { return default_arguments; } _FORCE_INLINE_ int get_default_argument_count() const { return default_argument_count; } _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { - int idx = argument_count - p_arg - 1; + int idx = p_arg - (argument_count - default_arguments.size()); if (idx < 0 || idx >= default_arguments.size()) { return false; @@ -239,7 +92,7 @@ public: } _FORCE_INLINE_ Variant get_default_argument(int p_arg) const { - int idx = argument_count - p_arg - 1; + int idx = p_arg - (argument_count - default_arguments.size()); if (idx < 0 || idx >= default_arguments.size()) { return Variant(); @@ -249,7 +102,6 @@ public: } #ifdef DEBUG_METHODS_ENABLED - _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL); return argument_types[p_argument + 1]; @@ -258,15 +110,16 @@ public: PropertyInfo get_argument_info(int p_argument) const; PropertyInfo get_return_info() const; - void set_argument_names(const Vector &p_names); //set by class, db, can't be inferred otherwise + void set_argument_names(const Vector &p_names); // Set by ClassDB, can't be inferred otherwise. Vector get_argument_names() const; virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const = 0; - #endif + void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; } uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); } - virtual String get_instance_class() const = 0; + _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } + _FORCE_INLINE_ void set_instance_class(const StringName &p_class) { instance_class = p_class; } _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; @@ -302,7 +155,6 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { if (p_arg < 0) { return arguments.return_val; @@ -320,14 +172,12 @@ public: virtual GodotTypeInfo::Metadata get_argument_meta(int) const { return GodotTypeInfo::METADATA_NONE; } - #else - virtual Variant::Type _gen_argument_type(int p_arg) const { return Variant::NIL; } - #endif + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { T *instance = static_cast(p_object); return (instance->*call_method)(p_args, p_arg_count, r_error); @@ -364,7 +214,6 @@ public: void set_method(NativeCall p_method) { call_method = p_method; } virtual bool is_const() const { return false; } - virtual String get_instance_class() const { return T::get_class_static(); } virtual bool is_vararg() const { return true; } @@ -378,16 +227,365 @@ MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, i MethodBindVarArg *a = memnew((MethodBindVarArg)); 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; } -/** This amazing hack is based on the FastDelegates theory */ +/**** VARIADIC TEMPLATES ****/ -// tale of an amazing hack.. // - -// if you declare a nonexistent class.. +#ifndef TYPED_METHOD_BIND class __UnexistingClass; +#define MB_T __UnexistingClass +#else +#define MB_T T +#endif -#include "method_bind.gen.inc" +// no return, not const +#ifdef TYPED_METHOD_BIND +template +#else +template +#endif +class MethodBindT : public MethodBind { + void (MB_T::*method)(P...); + +protected: +#ifdef DEBUG_METHODS_ENABLED +// 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 Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type(p_arg); + } else { + return Variant::NIL; + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + PropertyInfo pi; + call_get_argument_type_info(p_arg, pi); + return pi; + } +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + return call_get_argument_metadata(p_arg); + } + +#endif + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +#ifdef TYPED_METHOD_BIND + call_with_variant_args_dv(static_cast(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#else + call_with_variant_args_dv((MB_T *)(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#endif + return Variant(); + } + +#ifdef PTRCALL_ENABLED + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_args(static_cast(p_object), method, p_args); +#else + call_with_ptr_args((MB_T *)(p_object), method, p_args); +#endif + } +#endif + + MethodBindT(void (MB_T::*p_method)(P...)) { + method = p_method; +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template +MethodBind *create_method_bind(void (T::*p_method)(P...)) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindT)(p_method)); +#else + MethodBind *a = memnew((MethodBindT)(reinterpret_cast(p_method))); +#endif + a->set_instance_class(T::get_class_static()); + return a; +} + +// no return, not const + +#ifdef TYPED_METHOD_BIND +template +#else +template +#endif +class MethodBindTC : public MethodBind { + void (MB_T::*method)(P...) const; + +protected: +#ifdef DEBUG_METHODS_ENABLED +// 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 Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type(p_arg); + } else { + return Variant::NIL; + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + PropertyInfo pi; + call_get_argument_type_info(p_arg, pi); + return pi; + } +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + return call_get_argument_metadata(p_arg); + } + +#endif + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +#ifdef TYPED_METHOD_BIND + call_with_variant_argsc_dv(static_cast(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#else + call_with_variant_argsc_dv((MB_T *)(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#endif + return Variant(); + } + +#ifdef PTRCALL_ENABLED + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_argsc(static_cast(p_object), method, p_args); +#else + call_with_ptr_argsc((MB_T *)(p_object), method, p_args); +#endif + } +#endif + + MethodBindTC(void (MB_T::*p_method)(P...) const) { + method = p_method; + _set_const(true); +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template +MethodBind *create_method_bind(void (T::*p_method)(P...) const) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindTC)(p_method)); +#else + MethodBind *a = memnew((MethodBindTC)(reinterpret_cast(p_method))); +#endif + a->set_instance_class(T::get_class_static()); + return a; +} + +// return, not const + +#ifdef TYPED_METHOD_BIND +template +#else +template +#endif +class MethodBindTR : public MethodBind { + R(MB_T::*method) + (P...); + +protected: +#ifdef DEBUG_METHODS_ENABLED +// 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 Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type(p_arg); + } else { + return GetTypeInfo::VARIANT_TYPE; + } + } + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + PropertyInfo pi; + call_get_argument_type_info(p_arg, pi); + return pi; + } else { + return GetTypeInfo::get_class_info(); + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + if (p_arg >= 0) { + return call_get_argument_metadata(p_arg); + } else { + return GetTypeInfo::METADATA; + } + } +#endif + + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + Variant ret; +#ifdef TYPED_METHOD_BIND + call_with_variant_args_ret_dv(static_cast(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#else + call_with_variant_args_ret_dv((MB_T *)p_object, method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#endif + return ret; + } + +#ifdef PTRCALL_ENABLED + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_args_ret(static_cast(p_object), method, p_args, r_ret); +#else + call_with_ptr_args_ret((MB_T *)(p_object), method, p_args, r_ret); +#endif + } +#endif + + MethodBindTR(R (MB_T::*p_method)(P...)) { + method = p_method; + _set_returns(true); +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template +MethodBind *create_method_bind(R (T::*p_method)(P...)) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindTR)(p_method)); +#else + MethodBind *a = memnew((MethodBindTR)(reinterpret_cast(p_method))); +#endif + + a->set_instance_class(T::get_class_static()); + return a; +} + +// return, const + +#ifdef TYPED_METHOD_BIND +template +#else +template +#endif +class MethodBindTRC : public MethodBind { + R(MB_T::*method) + (P...) const; + +protected: +#ifdef DEBUG_METHODS_ENABLED +// 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 Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type(p_arg); + } else { + return GetTypeInfo::VARIANT_TYPE; + } + } + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + PropertyInfo pi; + call_get_argument_type_info(p_arg, pi); + return pi; + } else { + return GetTypeInfo::get_class_info(); + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + if (p_arg >= 0) { + return call_get_argument_metadata(p_arg); + } else { + return GetTypeInfo::METADATA; + } + } +#endif + + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + Variant ret; +#ifdef TYPED_METHOD_BIND + call_with_variant_args_retc_dv(static_cast(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#else + call_with_variant_args_retc_dv((MB_T *)(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#endif + return ret; + } + +#ifdef PTRCALL_ENABLED + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_args_retc(static_cast(p_object), method, p_args, r_ret); +#else + call_with_ptr_args_retc((MB_T *)(p_object), method, p_args, r_ret); +#endif + } +#endif + + MethodBindTRC(R (MB_T::*p_method)(P...) const) { + method = p_method; + _set_returns(true); + _set_const(true); +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template +MethodBind *create_method_bind(R (T::*p_method)(P...) const) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindTRC)(p_method)); +#else + MethodBind *a = memnew((MethodBindTRC)(reinterpret_cast(p_method))); +#endif + a->set_instance_class(T::get_class_static()); + return a; +} #endif // METHOD_BIND_H diff --git a/core/object.h b/core/object.h index f600e597ec2..765fb63c6ea 100644 --- a/core/object.h +++ b/core/object.h @@ -812,7 +812,4 @@ public: static int get_object_count(); }; -//needed by macros -#include "core/class_db.h" - #endif // OBJECT_H diff --git a/core/project_settings.h b/core/project_settings.h index 6cbb02d30e2..9a1d9cee971 100644 --- a/core/project_settings.h +++ b/core/project_settings.h @@ -31,7 +31,7 @@ #ifndef PROJECT_SETTINGS_H #define PROJECT_SETTINGS_H -#include "core/object.h" +#include "core/class_db.h" #include "core/os/thread_safe.h" #include "core/set.h" diff --git a/core/reference.h b/core/reference.h index f5794b0b67f..868894aad4b 100644 --- a/core/reference.h +++ b/core/reference.h @@ -32,7 +32,6 @@ #define REFERENCE_H #include "core/class_db.h" -#include "core/object.h" #include "core/safe_refcount.h" class Reference : public Object { diff --git a/core/resource.h b/core/resource.h index 7699d487354..41707f216d7 100644 --- a/core/resource.h +++ b/core/resource.h @@ -32,7 +32,6 @@ #define RESOURCE_H #include "core/class_db.h" -#include "core/object.h" #include "core/reference.h" #include "core/safe_refcount.h" #include "core/self_list.h" diff --git a/core/type_info.h b/core/type_info.h index 3c7f59bb84c..b9ae88d97c7 100644 --- a/core/type_info.h +++ b/core/type_info.h @@ -31,7 +31,7 @@ #ifndef TYPE_INFO_H #define TYPE_INFO_H -#ifdef DEBUG_METHODS_ENABLED +#include "core/typedefs.h" template struct EnableIf { @@ -267,11 +267,4 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) { #define CLASS_INFO(m_type) (GetTypeInfo::get_class_info()) -#else - -#define MAKE_ENUM_TYPE_INFO(m_enum) -#define CLASS_INFO(m_type) - -#endif // DEBUG_METHODS_ENABLED - #endif // TYPE_INFO_H diff --git a/core/typedefs.h b/core/typedefs.h index 4bfa5debaca..2472e5fcd91 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -263,4 +263,8 @@ struct BuildIndexSequence : BuildIndexSequence {}; template struct BuildIndexSequence<0, Is...> : IndexSequence {}; +#ifdef DEBUG_ENABLED +#define DEBUG_METHODS_ENABLED +#endif + #endif // TYPEDEFS_H diff --git a/core/undo_redo.h b/core/undo_redo.h index b46f7ff867d..68a553efd4d 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -31,7 +31,7 @@ #ifndef UNDO_REDO_H #define UNDO_REDO_H -#include "core/object.h" +#include "core/class_db.h" #include "core/resource.h" class UndoRedo : public Object { diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 06d4cf63b8e..66c1987a583 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -30,13 +30,13 @@ #include "variant.h" +#include "core/class_db.h" #include "core/color_names.inc" #include "core/core_string_names.h" #include "core/crypto/crypto_core.h" #include "core/debugger/engine_debugger.h" #include "core/io/compression.h" #include "core/oa_hash_map.h" -#include "core/object.h" #include "core/os/os.h" _FORCE_INLINE_ void sarray_add_str(Vector &arr) { @@ -96,44 +96,7 @@ struct _VariantCall { } virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { - const Variant **args = p_args; -#ifdef DEBUG_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } -#endif - if ((size_t)p_argcount < sizeof...(P)) { - size_t missing = sizeof...(P) - (size_t)p_argcount; - if (missing <= (size_t)default_values.size()) { - args = (const Variant **)alloca(sizeof...(P) * sizeof(const Variant *)); - // GCC fails to see that `sizeof...(P)` cannot be 0 here given the previous - // conditions, so it raises a warning on the potential use of `i < 0` as the - // execution condition. -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" -#endif - for (size_t i = 0; i < sizeof...(P); i++) { - if (i < (size_t)p_argcount) { - args[i] = p_args[i]; - } else { - args[i] = &default_values[i - p_argcount + (default_values.size() - missing)]; - } - } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - } else { -#ifdef DEBUG_ENABLED - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); -#endif - return; - } - } - call_with_variant_args_helper(VariantGetInternalPtr::get_ptr(base), method, args, r_error, BuildIndexSequence{}); + call_with_variant_args_dv(VariantGetInternalPtr::get_ptr(base), method, p_args, p_argcount, r_error, default_values); } virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) { @@ -187,11 +150,7 @@ struct _VariantCall { } virtual Variant::Type get_return_type() const { -#ifdef DEBUG_METHODS_ENABLED return GetTypeInfo::VARIANT_TYPE; -#else - return Variant::NIL; -#endif } virtual uint32_t get_flags() const { uint32_t f = 0; @@ -202,41 +161,7 @@ struct _VariantCall { } virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { - const Variant **args = p_args; -#ifdef DEBUG_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } -#endif - if ((size_t)p_argcount < sizeof...(P)) { - size_t missing = sizeof...(P) - (size_t)p_argcount; - if (missing <= (size_t)default_values.size()) { - args = (const Variant **)alloca(sizeof...(P) * sizeof(const Variant *)); -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" -#endif - for (size_t i = 0; i < sizeof...(P); i++) { - if (i < (size_t)p_argcount) { - args[i] = p_args[i]; - } else { - args[i] = &default_values[i - p_argcount + (default_values.size() - missing)]; - } - } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - } else { -#ifdef DEBUG_ENABLED - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); -#endif - return; - } - } - call_with_variant_args_ret_helper(VariantGetInternalPtr::get_ptr(base), method, args, r_ret, r_error, BuildIndexSequence{}); + call_with_variant_args_ret_dv(VariantGetInternalPtr::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, default_values); } virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) { @@ -288,11 +213,7 @@ struct _VariantCall { } virtual Variant::Type get_return_type() const { -#ifdef DEBUG_METHODS_ENABLED return GetTypeInfo::VARIANT_TYPE; -#else - return Variant::NIL; -#endif } virtual uint32_t get_flags() const { uint32_t f = FLAG_IS_CONST; @@ -303,44 +224,7 @@ struct _VariantCall { } virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { - const Variant **args = p_args; -#ifdef DEBUG_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } -#endif - if ((size_t)p_argcount < sizeof...(P)) { - size_t missing = sizeof...(P) - (size_t)p_argcount; - if (missing <= (size_t)default_values.size()) { - args = (const Variant **)alloca(sizeof...(P) * sizeof(const Variant *)); - // GCC fails to see that `sizeof...(P)` cannot be 0 here given the previous - // conditions, so it raises a warning on the potential use of `i < 0` as the - // execution condition. -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" -#endif - for (size_t i = 0; i < sizeof...(P); i++) { - if (i < (size_t)p_argcount) { - args[i] = p_args[i]; - } else { - args[i] = &default_values[i - p_argcount + (default_values.size() - missing)]; - } - } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - } else { -#ifdef DEBUG_ENABLED - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); -#endif - return; - } - } - call_with_variant_args_retc_helper(VariantGetInternalPtr::get_ptr(base), method, args, r_ret, r_error, BuildIndexSequence{}); + call_with_variant_args_retc_dv(VariantGetInternalPtr::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, default_values); } virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) { @@ -392,11 +276,7 @@ struct _VariantCall { } virtual Variant::Type get_return_type() const { -#ifdef DEBUG_METHODS_ENABLED return GetTypeInfo::VARIANT_TYPE; -#else - return Variant::NIL; -#endif } virtual uint32_t get_flags() const { uint32_t f = 0; @@ -552,12 +432,8 @@ struct _VariantCall { Variant::InternalMethod *m = memnew((InternalMethod)(p_method, p_default_args)); #endif -#ifdef DEBUG_METHODS_ENABLED type_internal_methods[GetTypeInfo::VARIANT_TYPE].insert(p_name, m); type_internal_method_names[GetTypeInfo::VARIANT_TYPE].push_back(p_name); -#else - (void)m; -#endif } template @@ -578,12 +454,8 @@ struct _VariantCall { Variant::InternalMethod *m = memnew((InternalMethodRC)(p_method, p_default_args)); #endif -#ifdef DEBUG_METHODS_ENABLED type_internal_methods[GetTypeInfo::VARIANT_TYPE].insert(p_name, m); type_internal_method_names[GetTypeInfo::VARIANT_TYPE].push_back(p_name); -#else - (void)m; -#endif } template @@ -603,12 +475,8 @@ struct _VariantCall { #else Variant::InternalMethod *m = memnew((InternalMethodR)(p_method, p_default_args)); #endif -#ifdef DEBUG_METHODS_ENABLED type_internal_methods[GetTypeInfo::VARIANT_TYPE].insert(p_name, m); type_internal_method_names[GetTypeInfo::VARIANT_TYPE].push_back(p_name); -#else - (void)m; -#endif } #ifdef DEBUG_ENABLED @@ -641,12 +509,8 @@ struct _VariantCall { Variant::InternalMethod *m = memnew((InternalMethodRS)(p_method, p_default_args)); #endif -#ifdef DEBUG_METHODS_ENABLED type_internal_methods[GetTypeInfo::VARIANT_TYPE].insert(p_name, m); type_internal_method_names[GetTypeInfo::VARIANT_TYPE].push_back(p_name); -#else - (void)m; -#endif } #ifdef DEBUG_ENABLED @@ -1745,6 +1609,7 @@ void register_variant_methods() { bind_method(Color, lightened, sarray("amount"), varray()); bind_method(Color, darkened, sarray("amount"), varray()); bind_method(Color, to_html, sarray("with_alpha"), varray(true)); + bind_method(Color, blend, sarray("over"), varray()); //Color is immutable, need to probably find a way to do this via constructor //ADDFUNC4R(COLOR, COLOR, Color, from_hsv, FLOAT, "h", FLOAT, "s", FLOAT, "v", FLOAT, "a", varray(1.0)); @@ -1888,7 +1753,7 @@ void register_variant_methods() { bind_method(Dictionary, hash, sarray(), varray()); bind_method(Dictionary, keys, sarray(), varray()); bind_method(Dictionary, values, sarray(), varray()); - bind_method(Dictionary, duplicate, sarray("deep"), varray("true")); + bind_method(Dictionary, duplicate, sarray("deep"), varray(false)); bind_method(Dictionary, get, sarray("key", "default"), varray(Variant())); /* Array */ @@ -1919,7 +1784,7 @@ void register_variant_methods() { bind_method(Array, bsearch, sarray("value", "before"), varray(true)); bind_method(Array, bsearch_custom, sarray("value", "obj", "func", "before"), varray(true)); bind_method(Array, invert, sarray(), varray()); - bind_method(Array, duplicate, sarray("deep"), varray(true)); + bind_method(Array, duplicate, sarray("deep"), varray(false)); bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(1, false)); bind_method(Array, max, sarray(), varray()); bind_method(Array, min, sarray(), varray()); @@ -1944,9 +1809,9 @@ void register_variant_methods() { bind_function("get_string_from_utf16", _VariantCall::func_PackedByteArray_get_string_from_utf16, sarray(), varray()); bind_function("get_string_from_utf32", _VariantCall::func_PackedByteArray_get_string_from_utf32, sarray(), varray()); bind_function("hex_encode", _VariantCall::func_PackedByteArray_hex_encode, sarray(), varray()); - bind_function("compress", _VariantCall::func_PackedByteArray_compress, sarray("compression_mode"), varray()); - bind_function("decompress", _VariantCall::func_PackedByteArray_decompress, sarray("buffer_size", "compression_mode"), varray()); - bind_function("decompress_dynamic", _VariantCall::func_PackedByteArray_decompress_dynamic, sarray("max_output_size", "compression_mode"), varray()); + bind_function("compress", _VariantCall::func_PackedByteArray_compress, sarray("compression_mode"), varray(0)); + bind_function("decompress", _VariantCall::func_PackedByteArray_decompress, sarray("buffer_size", "compression_mode"), varray(0)); + bind_function("decompress_dynamic", _VariantCall::func_PackedByteArray_decompress_dynamic, sarray("max_output_size", "compression_mode"), varray(0)); /* Int32 Array */ diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 533b056f91c..47539df856d 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -30,9 +30,9 @@ #include "variant.h" +#include "core/class_db.h" #include "core/core_string_names.h" #include "core/debugger/engine_debugger.h" -#include "core/object.h" #define CASE_TYPE_ALL(PREFIX, OP) \ CASE_TYPE(PREFIX, OP, INT) \ diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 082c3176553..e330713cfbd 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -791,7 +791,7 @@ bool EditorPlugin::build() { return true; } -void EditorPlugin::queue_save_layout() const { +void EditorPlugin::queue_save_layout() { EditorNode::get_singleton()->save_layout(); } diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 40a91cbfb91..dd3bf08678b 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -221,7 +221,7 @@ public: int update_overlays() const; - void queue_save_layout() const; + void queue_save_layout(); void make_bottom_panel_item_visible(Control *p_item); void hide_bottom_panel(); diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 3170ea5ff85..9723ae188b1 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -30,8 +30,6 @@ #include "editor_resource_preview.h" -#include "core/method_bind_ext.gen.inc" - #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/message_queue.h" diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 04bb49bb51c..c1bb7951fae 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -31,8 +31,7 @@ #ifndef EDITOR_SETTINGS_H #define EDITOR_SETTINGS_H -#include "core/object.h" - +#include "core/class_db.h" #include "core/io/config_file.h" #include "core/os/thread_safe.h" #include "core/resource.h" diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h index ee9e51441d6..6ef55f0a46c 100644 --- a/editor/editor_vcs_interface.h +++ b/editor/editor_vcs_interface.h @@ -31,7 +31,7 @@ #ifndef EDITOR_VCS_INTERFACE_H #define EDITOR_VCS_INTERFACE_H -#include "core/object.h" +#include "core/class_db.h" #include "core/ustring.h" #include "scene/gui/panel_container.h" diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h index 9645fbf39ea..eefaa503c15 100644 --- a/editor/fileserver/editor_file_server.h +++ b/editor/fileserver/editor_file_server.h @@ -31,10 +31,10 @@ #ifndef EDITOR_FILE_SERVER_H #define EDITOR_FILE_SERVER_H +#include "core/class_db.h" #include "core/io/file_access_network.h" #include "core/io/packet_peer.h" #include "core/io/tcp_server.h" -#include "core/object.h" #include "core/os/thread.h" class EditorFileServer : public Object { diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 8f1b8838d8a..c88cd8ea5fb 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -164,7 +164,7 @@ void InspectorDock::_resource_file_selected(String p_file) { editor->push_item(res.operator->()); } -void InspectorDock::_save_resource(bool save_as) const { +void InspectorDock::_save_resource(bool save_as) { ObjectID current = EditorNode::get_singleton()->get_editor_history()->get_current(); Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : nullptr; @@ -179,7 +179,7 @@ void InspectorDock::_save_resource(bool save_as) const { } } -void InspectorDock::_unref_resource() const { +void InspectorDock::_unref_resource() { ObjectID current = EditorNode::get_singleton()->get_editor_history()->get_current(); Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : nullptr; @@ -190,7 +190,7 @@ void InspectorDock::_unref_resource() const { editor->edit_current(); } -void InspectorDock::_copy_resource() const { +void InspectorDock::_copy_resource() { ObjectID current = EditorNode::get_singleton()->get_editor_history()->get_current(); Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : nullptr; @@ -201,7 +201,7 @@ void InspectorDock::_copy_resource() const { EditorSettings::get_singleton()->set_resource_clipboard(current_res); } -void InspectorDock::_paste_resource() const { +void InspectorDock::_paste_resource() { RES r = EditorSettings::get_singleton()->get_resource_clipboard(); if (r.is_valid()) { editor->push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String()); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 551d3d16434..b2dabf19c58 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -96,10 +96,10 @@ class InspectorDock : public VBoxContainer { void _load_resource(const String &p_type = ""); void _open_resource_selector() { _load_resource(); }; // just used to call from arg-less signal void _resource_file_selected(String p_file); - void _save_resource(bool save_as) const; - void _unref_resource() const; - void _copy_resource() const; - void _paste_resource() const; + void _save_resource(bool save_as); + void _unref_resource(); + void _copy_resource(); + void _paste_resource(); void _warning_pressed(); void _resource_created(); diff --git a/main/performance.h b/main/performance.h index 5f88a24c0fb..f406433cf2b 100644 --- a/main/performance.h +++ b/main/performance.h @@ -31,7 +31,7 @@ #ifndef PERFORMANCE_H #define PERFORMANCE_H -#include "core/object.h" +#include "core/class_db.h" #include "core/ordered_hash_map.h" #define PERF_WARN_OFFLINE_FUNCTION diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index f1423a69e4d..36b3a9550c7 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -31,9 +31,9 @@ #ifndef COLLISION_OBJECT_BULLET_H #define COLLISION_OBJECT_BULLET_H +#include "core/class_db.h" #include "core/math/transform.h" #include "core/math/vector3.h" -#include "core/object.h" #include "core/vset.h" #include "shape_owner_bullet.h" diff --git a/modules/denoise/lightmap_denoiser.h b/modules/denoise/lightmap_denoiser.h index d01bbd10a56..74a9d8af866 100644 --- a/modules/denoise/lightmap_denoiser.h +++ b/modules/denoise/lightmap_denoiser.h @@ -31,7 +31,7 @@ #ifndef LIGHTMAP_DENOISER_H #define LIGHTMAP_DENOISER_H -#include "core/object.h" +#include "core/class_db.h" #include "scene/3d/lightmapper.h" struct OIDNDeviceImpl; diff --git a/modules/gdnavigation/rvo_agent.h b/modules/gdnavigation/rvo_agent.h index f5c579ba84c..1ad9d3ed765 100644 --- a/modules/gdnavigation/rvo_agent.h +++ b/modules/gdnavigation/rvo_agent.h @@ -31,8 +31,9 @@ #ifndef RVO_AGENT_H #define RVO_AGENT_H -#include "core/object.h" +#include "core/class_db.h" #include "nav_rid.h" + #include /** diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h index e2b7ab09754..6f3f8003e0d 100644 --- a/modules/jsonrpc/jsonrpc.h +++ b/modules/jsonrpc/jsonrpc.h @@ -31,7 +31,7 @@ #ifndef GODOT_JSON_RPC_H #define GODOT_JSON_RPC_H -#include "core/object.h" +#include "core/class_db.h" #include "core/variant.h" class JSONRPC : public Object { diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp index ebcd6d5e9cf..439fb1ab0a8 100644 --- a/modules/mono/glue/base_object_glue.cpp +++ b/modules/mono/glue/base_object_glue.cpp @@ -31,7 +31,6 @@ #ifdef MONO_GLUE_ENABLED #include "core/class_db.h" -#include "core/object.h" #include "core/reference.h" #include "core/string_name.h" diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index c1f1936711f..dc3bf478387 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -64,7 +64,6 @@ void godot_register_glue_header_icalls() { #include "core/engine.h" #include "core/method_bind.h" #include "core/node_path.h" -#include "core/object.h" #include "core/reference.h" #include "core/typedefs.h" #include "core/ustring.h" diff --git a/modules/mono/glue/rid_glue.cpp b/modules/mono/glue/rid_glue.cpp index 6d2e6b559fc..a7b18c36ddd 100644 --- a/modules/mono/glue/rid_glue.cpp +++ b/modules/mono/glue/rid_glue.cpp @@ -30,7 +30,7 @@ #ifdef MONO_GLUE_ENABLED -#include "core/object.h" +#include "core/class_db.h" #include "core/resource.h" #include "core/rid.h" diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h index 038d17f782f..cf7efdecd6c 100644 --- a/modules/mono/mono_gd/gd_mono_internals.h +++ b/modules/mono/mono_gd/gd_mono_internals.h @@ -35,7 +35,7 @@ #include "../utils/macros.h" -#include "core/object.h" +#include "core/class_db.h" namespace GDMonoInternals { diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 5958bf3cc1c..80569cb1c77 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -37,7 +37,7 @@ #include "../utils/macros.h" #include "gd_mono_header.h" -#include "core/object.h" +#include "core/class_db.h" #include "core/reference.h" #define UNHANDLED_EXCEPTION(m_exc) \ diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index b1d8c05d87f..d962d912874 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -30,8 +30,8 @@ #include "visual_script_editor.h" +#include "core/class_db.h" #include "core/input/input.h" -#include "core/object.h" #include "core/os/keyboard.h" #include "core/script_language.h" #include "core/variant.h" diff --git a/platform/iphone/game_center.h b/platform/iphone/game_center.h index 6705674ac60..10c8ef52fb6 100644 --- a/platform/iphone/game_center.h +++ b/platform/iphone/game_center.h @@ -33,7 +33,7 @@ #ifndef GAME_CENTER_H #define GAME_CENTER_H -#include "core/object.h" +#include "core/class_db.h" class GameCenter : public Object { GDCLASS(GameCenter, Object); diff --git a/platform/iphone/icloud.h b/platform/iphone/icloud.h index 381edfa718a..6ca1e6594a4 100644 --- a/platform/iphone/icloud.h +++ b/platform/iphone/icloud.h @@ -33,7 +33,7 @@ #ifndef ICLOUD_H #define ICLOUD_H -#include "core/object.h" +#include "core/class_db.h" class ICloud : public Object { GDCLASS(ICloud, Object); diff --git a/platform/iphone/in_app_store.h b/platform/iphone/in_app_store.h index beb58af2c7b..ccf31876a9b 100644 --- a/platform/iphone/in_app_store.h +++ b/platform/iphone/in_app_store.h @@ -33,7 +33,7 @@ #ifndef IN_APP_STORE_H #define IN_APP_STORE_H -#include "core/object.h" +#include "core/class_db.h" class InAppStore : public Object { GDCLASS(InAppStore, Object); diff --git a/platform/iphone/ios.h b/platform/iphone/ios.h index 2b29e6f2683..6a89cd38cb3 100644 --- a/platform/iphone/ios.h +++ b/platform/iphone/ios.h @@ -31,7 +31,7 @@ #ifndef IOS_H #define IOS_H -#include "core/object.h" +#include "core/class_db.h" class iOS : public Object { GDCLASS(iOS, Object); diff --git a/platform/javascript/api/javascript_eval.h b/platform/javascript/api/javascript_eval.h index 29229de8e3a..26b5b9e4842 100644 --- a/platform/javascript/api/javascript_eval.h +++ b/platform/javascript/api/javascript_eval.h @@ -31,7 +31,7 @@ #ifndef JAVASCRIPT_EVAL_H #define JAVASCRIPT_EVAL_H -#include "core/object.h" +#include "core/class_db.h" class JavaScript : public Object { private: diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 6fc1dc65afd..50e9bd26534 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -139,7 +139,8 @@ def configure(env): env.Append(CPPDEFINES=["__MACPORTS__"]) # hack to fix libvpx MM256_BROADCASTSI128_SI256 define if env["CXX"] == "clang++": - env.Append(CPPDEFINES=["TYPED_METHOD_BIND"]) + # This should now work with clang++, re-enable if there are issues + # env.Append(CPPDEFINES=["TYPED_METHOD_BIND"]) env["CC"] = "clang" env["LINK"] = "clang++" diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index 219174b5096..e9e536837f5 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -29,11 +29,12 @@ /*************************************************************************/ #include "export.h" + #include "core/bind/core_bind.h" +#include "core/class_db.h" #include "core/crypto/crypto_core.h" #include "core/io/marshalls.h" #include "core/io/zip_io.h" -#include "core/object.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/project_settings.h" diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 320b382676d..402eac644fe 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -30,12 +30,11 @@ #include "physics_body_2d.h" +#include "core/class_db.h" #include "core/core_string_names.h" #include "core/engine.h" #include "core/list.h" #include "core/math/math_funcs.h" -#include "core/method_bind_ext.gen.inc" -#include "core/object.h" #include "core/rid.h" #include "scene/scene_string_names.h" diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c2951559a40..94ec0998fa8 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -32,7 +32,6 @@ #include "collision_object_2d.h" #include "core/io/marshalls.h" -#include "core/method_bind_ext.gen.inc" #include "core/os/os.h" #include "scene/2d/area_2d.h" #include "servers/navigation_server_2d.h" diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index ab30d2fec5e..fd592012f84 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -32,7 +32,6 @@ #include "core/os/os.h" -#include "core/method_bind_ext.gen.inc" #include "mesh_instance_3d.h" #include "voxelizer.h" diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index aae81c6a341..579088b835c 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -30,11 +30,10 @@ #include "physics_body_3d.h" +#include "core/class_db.h" #include "core/core_string_names.h" #include "core/engine.h" #include "core/list.h" -#include "core/method_bind_ext.gen.inc" -#include "core/object.h" #include "core/rid.h" #include "scene/3d/collision_shape_3d.h" #include "scene/scene_string_names.h" diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 018a2a7a398..3b5c328e435 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -30,8 +30,8 @@ #include "soft_body_3d.h" +#include "core/class_db.h" #include "core/list.h" -#include "core/object.h" #include "core/os/os.h" #include "core/rid.h" #include "scene/3d/collision_object_3d.h" diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index d7d55b468e4..bb5d5366000 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -32,7 +32,6 @@ #include "animation_blend_tree.h" #include "core/engine.h" -#include "core/method_bind_ext.gen.inc" #include "scene/scene_string_names.h" #include "servers/audio/audio_stream.h" diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index bd4396d6803..1a2a97ada8a 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -30,8 +30,6 @@ #include "tween.h" -#include "core/method_bind_ext.gen.inc" - void Tween::_add_pending_command(StringName p_key, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5, const Variant &p_arg6, const Variant &p_arg7, const Variant &p_arg8, const Variant &p_arg9, const Variant &p_arg10) { // Add a new pending command and reference it pending_commands.push_back(PendingCommand()); diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index a2bafde0394..80e329f1f2d 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -32,7 +32,7 @@ #define SCENE_DEBUGGER_H #include "core/array.h" -#include "core/object.h" +#include "core/class_db.h" #include "core/pair.h" #include "core/ustring.h" diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 38bf31830f4..4454e870171 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -30,8 +30,6 @@ #include "graph_node.h" -#include "core/method_bind_ext.gen.inc" - bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { if (!p_name.operator String().begins_with("slot/")) { return false; diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 0d9d9d63569..718d805bdd4 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -32,7 +32,6 @@ #include "core/input/input.h" #include "core/message_queue.h" -#include "core/method_bind_ext.gen.inc" #include "scene/main/canvas_layer.h" #include "scene/main/viewport.h" #include "scene/main/window.h" diff --git a/scene/main/node.h b/scene/main/node.h index 2928466cd08..09943d06266 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -34,7 +34,6 @@ #include "core/class_db.h" #include "core/map.h" #include "core/node_path.h" -#include "core/object.h" #include "core/project_settings.h" #include "core/script_language.h" #include "core/typed_array.h" diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 7cc39f661d3..b75657c2c25 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -31,7 +31,6 @@ #include "font.h" #include "core/io/resource_loader.h" -#include "core/method_bind_ext.gen.inc" #include "core/os/file_access.h" void Font::draw_halign(RID p_canvas_item, const Point2 &p_pos, HAlign p_align, float p_width, const String &p_text, const Color &p_modulate, const Color &p_outline_modulate) const { diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 1a2dcc84bb1..ff14a5a2920 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -30,8 +30,6 @@ #include "surface_tool.h" -#include "core/method_bind_ext.gen.inc" - #define _VERTEX_SNAP 0.0001 #define EQ_VERTEX_DIST 0.00001 diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 39237e1a33d..6291d2dddb7 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -32,7 +32,6 @@ #include "core/core_string_names.h" #include "core/io/image_loader.h" -#include "core/method_bind_ext.gen.inc" #include "core/os/os.h" #include "mesh.h" #include "scene/resources/bit_map.h" diff --git a/servers/audio_server.h b/servers/audio_server.h index 80e244aacdb..31537e83266 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -31,8 +31,8 @@ #ifndef AUDIO_SERVER_H #define AUDIO_SERVER_H +#include "core/class_db.h" #include "core/math/audio_frame.h" -#include "core/object.h" #include "core/os/os.h" #include "core/variant.h" #include "servers/audio/audio_effect.h" diff --git a/servers/camera_server.h b/servers/camera_server.h index b268553fe58..7723e309747 100644 --- a/servers/camera_server.h +++ b/servers/camera_server.h @@ -31,7 +31,7 @@ #ifndef CAMERA_SERVER_H #define CAMERA_SERVER_H -#include "core/object.h" +#include "core/class_db.h" #include "core/os/thread_safe.h" #include "core/reference.h" #include "core/rid.h" diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 356f4b884a9..e678c6919b8 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -31,7 +31,6 @@ #include "display_server.h" #include "core/input/input.h" -#include "core/method_bind_ext.gen.inc" #include "scene/resources/texture.h" DisplayServer *DisplayServer::singleton = nullptr; diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index d7384bae746..6575426e73a 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -35,7 +35,7 @@ #ifndef NAVIGATION_2D_SERVER_H #define NAVIGATION_2D_SERVER_H -#include "core/object.h" +#include "core/class_db.h" #include "core/rid.h" #include "scene/2d/navigation_region_2d.h" diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index c34bd2391b4..7a3e4f5f8ff 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -35,7 +35,7 @@ #ifndef NAVIGATION_SERVER_H #define NAVIGATION_SERVER_H -#include "core/object.h" +#include "core/class_db.h" #include "core/rid.h" #include "scene/3d/navigation_region_3d.h" diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 0dac08015f0..4338a6938aa 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -30,7 +30,6 @@ #include "physics_server_2d.h" -#include "core/method_bind_ext.gen.inc" #include "core/print_string.h" #include "core/project_settings.h" diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index f609adccf90..40773e4ced1 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -31,7 +31,7 @@ #ifndef PHYSICS_2D_SERVER_H #define PHYSICS_2D_SERVER_H -#include "core/object.h" +#include "core/class_db.h" #include "core/reference.h" #include "core/resource.h" diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 33a2b919025..d0266f95b52 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -30,7 +30,6 @@ #include "physics_server_3d.h" -#include "core/method_bind_ext.gen.inc" #include "core/print_string.h" #include "core/project_settings.h" diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index b779942460e..d79dc6fec00 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -31,7 +31,7 @@ #ifndef PHYSICS_SERVER_H #define PHYSICS_SERVER_H -#include "core/object.h" +#include "core/class_db.h" #include "core/resource.h" class PhysicsDirectSpaceState3D; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 83cbfb85bd1..1259b161bd3 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "rendering_device.h" -#include "core/method_bind_ext.gen.inc" + #include "rendering_device_binds.h" RenderingDevice *RenderingDevice::singleton = nullptr; diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 72afc7c6219..6df66e7b201 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -31,7 +31,7 @@ #ifndef RENDERING_DEVICE_H #define RENDERING_DEVICE_H -#include "core/object.h" +#include "core/class_db.h" #include "core/typed_array.h" #include "servers/display_server.h" diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 9434e377f85..6c962ef8dc8 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -30,7 +30,6 @@ #include "rendering_server.h" -#include "core/method_bind_ext.gen.inc" #include "core/project_settings.h" RenderingServer *RenderingServer::singleton = nullptr; diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 7680dc13905..92f5c0ea765 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -31,10 +31,10 @@ #ifndef RENDERING_SERVER_H #define RENDERING_SERVER_H +#include "core/class_db.h" #include "core/image.h" #include "core/math/geometry_3d.h" #include "core/math/transform_2d.h" -#include "core/object.h" #include "core/rid.h" #include "core/typed_array.h" #include "core/variant.h" diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 60674c79c06..871c7965138 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -42,6 +42,7 @@ #include "test_gui.h" #include "test_list.h" #include "test_math.h" +#include "test_method_bind.h" #include "test_oa_hash_map.h" #include "test_ordered_hash_map.h" #include "test_physics_2d.h" diff --git a/tests/test_method_bind.h b/tests/test_method_bind.h new file mode 100644 index 00000000000..f4004c20908 --- /dev/null +++ b/tests/test_method_bind.h @@ -0,0 +1,165 @@ +/*************************************************************************/ +/* test_method_bind.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 TEST_METHOD_BIND_H +#define TEST_METHOD_BIND_H + +#include "core/class_db.h" + +#include "tests/test_macros.h" + +#include +#include +#include + +namespace TestMethodBind { + +class MethodBindTester : public Object { + GDCLASS(MethodBindTester, Object); + +public: + enum Test { + TEST_METHOD, + TEST_METHOD_ARGS, + TEST_METHODC, + TEST_METHODC_ARGS, + TEST_METHODR, + TEST_METHODR_ARGS, + TEST_METHODRC, + TEST_METHODRC_ARGS, + TEST_METHOD_DEFARGS, + TEST_MAX + }; + + int test_num = 0; + + bool test_valid[TEST_MAX]; + + void test_method() { + test_valid[TEST_METHOD] = true; + } + + void test_method_args(int p_arg) { + test_valid[TEST_METHOD_ARGS] = p_arg == test_num; + } + + void test_methodc() { + test_valid[TEST_METHODC] = true; + } + + void test_methodc_args(int p_arg) { + test_valid[TEST_METHODC_ARGS] = p_arg == test_num; + } + + int test_methodr() { + test_valid[TEST_METHODR] = true; //temporary + return test_num; + } + + int test_methodr_args(int p_arg) { + test_valid[TEST_METHODR_ARGS] = true; //temporary + return p_arg; + } + + int test_methodrc() { + test_valid[TEST_METHODRC] = true; //temporary + return test_num; + } + + int test_methodrc_args(int p_arg) { + test_valid[TEST_METHODRC_ARGS] = true; //temporary + return p_arg; + } + + void test_method_default_args(int p_arg1, int p_arg2, int p_arg3, int p_arg4, int p_arg5) { + test_valid[TEST_METHOD_DEFARGS] = p_arg1 == 1 && p_arg2 == 2 && p_arg3 == 3 && p_arg4 == 4 && p_arg5 == 5; //temporary + } + + static void _bind_methods() { + ClassDB::bind_method(D_METHOD("test_method"), &MethodBindTester::test_method); + ClassDB::bind_method(D_METHOD("test_method_args"), &MethodBindTester::test_method_args); + ClassDB::bind_method(D_METHOD("test_methodc"), &MethodBindTester::test_methodc); + ClassDB::bind_method(D_METHOD("test_methodc_args"), &MethodBindTester::test_methodc_args); + ClassDB::bind_method(D_METHOD("test_methodr"), &MethodBindTester::test_methodr); + ClassDB::bind_method(D_METHOD("test_methodr_args"), &MethodBindTester::test_methodr_args); + ClassDB::bind_method(D_METHOD("test_methodrc"), &MethodBindTester::test_methodrc); + ClassDB::bind_method(D_METHOD("test_methodrc_args"), &MethodBindTester::test_methodrc_args); + ClassDB::bind_method(D_METHOD("test_method_default_args"), &MethodBindTester::test_method_default_args, DEFVAL(9) /* wrong on purpose */, DEFVAL(4), DEFVAL(5)); + } + + virtual void run_tests() { + for (int i = 0; i < TEST_MAX; i++) { + test_valid[i] = false; + } + //regular + test_num = Math::rand(); + call("test_method"); + test_num = Math::rand(); + call("test_method_args", test_num); + test_num = Math::rand(); + call("test_methodc"); + test_num = Math::rand(); + call("test_methodc_args", test_num); + //return + test_num = Math::rand(); + test_valid[TEST_METHODR] = int(call("test_methodr")) == test_num && test_valid[TEST_METHODR]; + test_num = Math::rand(); + test_valid[TEST_METHODR_ARGS] = int(call("test_methodr_args", test_num)) == test_num && test_valid[TEST_METHODR_ARGS]; + test_num = Math::rand(); + test_valid[TEST_METHODRC] = int(call("test_methodrc")) == test_num && test_valid[TEST_METHODRC]; + test_num = Math::rand(); + test_valid[TEST_METHODRC_ARGS] = int(call("test_methodrc_args", test_num)) == test_num && test_valid[TEST_METHODRC_ARGS]; + + call("test_method_default_args", 1, 2, 3, 4); + } +}; + +TEST_CASE("[MethodBind] check all method binds") { + MethodBindTester *mbt = memnew(MethodBindTester); + + print_line("testing method bind"); + mbt->run_tests(); + + CHECK(mbt->test_valid[MethodBindTester::TEST_METHOD]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHOD_ARGS]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHODC]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHODC_ARGS]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHODR]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHODR_ARGS]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHODRC]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHODRC_ARGS]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHOD_DEFARGS]); + + memdelete(mbt); +} + +} // namespace TestMethodBind + +#endif // TEST_METHOD_BIND_H