From 0b25de19fd062bc75de17a8e5e75cc4a88776787 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 2 Apr 2026 22:40:43 -0400 Subject: [PATCH 01/12] Update merged function --- core/variant/method_ptrcall.h | 2 + core/variant/variant_utility.cpp | 899 ++++++++++++++----------------- core/variant/variant_utility.h | 44 +- 3 files changed, 442 insertions(+), 503 deletions(-) diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h index 4caa7bbf367..113f8f5768b 100644 --- a/core/variant/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -241,6 +241,8 @@ template <> struct PtrToArg : Internal::PtrToArgDirect {}; template <> struct PtrToArg : Internal::PtrToArgByReference {}; +// template <> +// struct PtrToArg : Internal::PtrToArgConvert {}; template struct PtrToArg>> : Internal::PtrToArgConvert {}; diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 7ec824f0717..fc89c79fd5b 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -35,7 +35,6 @@ #include "core/io/marshalls.h" #include "core/math/math_funcs.h" #include "core/object/ref_counted.h" -#include "core/object/script_language.h" #include "core/os/os.h" #include "core/templates/a_hash_map.h" #include "core/templates/rid.h" @@ -112,7 +111,7 @@ int64_t VariantUtilityFunctions::posmod(int64_t b, int64_t r) { return Math::posmod(b, r); } -Variant VariantUtilityFunctions::floor(const Variant &x, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::floor(Callable::CallError &r_error, const Variant &x) { r_error.error = Callable::CallError::CALL_OK; switch (x.get_type()) { case Variant::INT: { @@ -156,7 +155,7 @@ int64_t VariantUtilityFunctions::floori(double x) { return int64_t(Math::floor(x)); } -Variant VariantUtilityFunctions::ceil(const Variant &x, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::ceil(Callable::CallError &r_error, const Variant &x) { r_error.error = Callable::CallError::CALL_OK; switch (x.get_type()) { case Variant::INT: { @@ -200,7 +199,7 @@ int64_t VariantUtilityFunctions::ceili(double x) { return int64_t(Math::ceil(x)); } -Variant VariantUtilityFunctions::round(const Variant &x, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::round(Callable::CallError &r_error, const Variant &x) { r_error.error = Callable::CallError::CALL_OK; switch (x.get_type()) { case Variant::INT: { @@ -244,7 +243,7 @@ int64_t VariantUtilityFunctions::roundi(double x) { return int64_t(Math::round(x)); } -Variant VariantUtilityFunctions::abs(const Variant &x, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::abs(Callable::CallError &r_error, const Variant &x) { r_error.error = Callable::CallError::CALL_OK; switch (x.get_type()) { case Variant::INT: { @@ -288,7 +287,7 @@ int64_t VariantUtilityFunctions::absi(int64_t x) { return Math::abs(x); } -Variant VariantUtilityFunctions::sign(const Variant &x, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::sign(Callable::CallError &r_error, const Variant &x) { r_error.error = Callable::CallError::CALL_OK; switch (x.get_type()) { case Variant::INT: { @@ -372,7 +371,7 @@ int VariantUtilityFunctions::step_decimals(float step) { return Math::step_decimals(step); } -Variant VariantUtilityFunctions::snapped(const Variant &x, const Variant &step, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::snapped(Callable::CallError &r_error, const Variant &x, const Variant &step) { switch (x.get_type()) { case Variant::INT: case Variant::FLOAT: @@ -446,7 +445,7 @@ int64_t VariantUtilityFunctions::snappedi(double x, int64_t step) { return Math::snapped(x, step); } -Variant VariantUtilityFunctions::lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::lerp(Callable::CallError &r_error, const Variant &from, const Variant &to, double weight) { switch (from.get_type()) { case Variant::INT: case Variant::FLOAT: @@ -594,7 +593,7 @@ double VariantUtilityFunctions::db_to_linear(double db) { return Math::db_to_linear(db); } -Variant VariantUtilityFunctions::wrap(const Variant &p_x, const Variant &p_min, const Variant &p_max, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::wrap(Callable::CallError &r_error, const Variant &p_x, const Variant &p_min, const Variant &p_max) { Variant::Type x_type = p_x.get_type(); if (x_type != Variant::INT && x_type != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; @@ -668,7 +667,7 @@ double VariantUtilityFunctions::sigmoid_affine_approx(double x, double amplitude return Math::sigmoid_affine_approx(x, amplitude, y_translation); } -Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::max(Callable::CallError &r_error, const Variant **p_args, int p_argcount) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.expected = 2; @@ -712,7 +711,7 @@ int64_t VariantUtilityFunctions::maxi(int64_t x, int64_t y) { return MAX(x, y); } -Variant VariantUtilityFunctions::min(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::min(Callable::CallError &r_error, const Variant **p_args, int p_argcount) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.expected = 2; @@ -756,7 +755,7 @@ int64_t VariantUtilityFunctions::mini(int64_t x, int64_t y) { return MIN(x, y); } -Variant VariantUtilityFunctions::clamp(const Variant &x, const Variant &min, const Variant &max, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::clamp(Callable::CallError &r_error, const Variant &x, const Variant &min, const Variant &max) { Variant value = x; Variant ret; @@ -841,7 +840,7 @@ PackedInt64Array VariantUtilityFunctions::rand_from_seed(int64_t seed) { // Utility -Variant VariantUtilityFunctions::weakref(const Variant &obj, Callable::CallError &r_error) { +Variant VariantUtilityFunctions::weakref(Callable::CallError &r_error, const Variant &obj) { if (obj.get_type() == Variant::OBJECT) { r_error.error = Callable::CallError::CALL_OK; if (obj.is_ref_counted()) { @@ -961,7 +960,7 @@ Variant VariantUtilityFunctions::type_convert(const Variant &p_variant, const Va return p_variant; } -String VariantUtilityFunctions::str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +String VariantUtilityFunctions::str(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.expected = 1; @@ -986,17 +985,17 @@ String VariantUtilityFunctions::type_string(Variant::Type p_type) { return Variant::get_type_name(p_type); } -void VariantUtilityFunctions::print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::print(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { print_line(join_string(p_args, p_arg_count)); r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::print_rich(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::print_rich(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { print_line_rich(join_string(p_args, p_arg_count)); r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::_print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::_print_verbose(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { if (OS::get_singleton()->is_stdout_verbose()) { // No need to use `print_verbose()` as this call already only happens // when verbose mode is enabled. This avoids performing string argument concatenation @@ -1007,12 +1006,12 @@ void VariantUtilityFunctions::_print_verbose(const Variant **p_args, int p_arg_c r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::printerr(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { print_error(join_string(p_args, p_arg_count)); r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::printt(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { String s; for (int i = 0; i < p_arg_count; i++) { if (i) { @@ -1025,7 +1024,7 @@ void VariantUtilityFunctions::printt(const Variant **p_args, int p_arg_count, Ca r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::prints(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { String s; for (int i = 0; i < p_arg_count; i++) { if (i) { @@ -1038,12 +1037,12 @@ void VariantUtilityFunctions::prints(const Variant **p_args, int p_arg_count, Ca r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::printraw(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { print_raw(join_string(p_args, p_arg_count)); r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::push_error(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.expected = 1; @@ -1053,7 +1052,7 @@ void VariantUtilityFunctions::push_error(const Variant **p_args, int p_arg_count r_error.error = Callable::CallError::CALL_OK; } -void VariantUtilityFunctions::push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +void VariantUtilityFunctions::push_warning(Callable::CallError &r_error, const Variant **p_args, int p_arg_count) { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.expected = 1; @@ -1219,6 +1218,12 @@ String VariantUtilityFunctions::join_string(const Variant **p_args, int p_arg_co #define VCALL p_func(VariantCaster

::cast(*p_args[Is])...) #endif // DEBUG_ENABLED +template +static _FORCE_INLINE_ void call_helperpr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { + *ret = p_func(r_error, VariantCasterAndValidate

::cast(p_args, Is, r_error)...); + (void)p_args; // avoid gcc warning +} + template static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { r_error.error = Callable::CallError::CALL_OK; @@ -1233,12 +1238,31 @@ static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(P...), Variant *r (void)p_args; } +template +static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args, IndexSequence) { + Callable::CallError err; + *ret = p_func(err, VariantCaster

::cast(*p_args[Is])...); + (void)p_args; +} + template static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(P...), void *ret, const void **p_args, IndexSequence) { PtrToArg::encode(p_func(PtrToArg

::convert(p_args[Is])...), ret); (void)p_args; } +template +static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(Callable::CallError &, P...), void *ret, const void **p_args, IndexSequence) { + Callable::CallError err; + PtrToArg::encode(p_func(err, PtrToArg

::convert(p_args[Is])...), ret); + (void)p_args; +} + +template +static _FORCE_INLINE_ void call_helperr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { + call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence{}); +} + template static _FORCE_INLINE_ void call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence{}); @@ -1249,21 +1273,41 @@ static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(P...), Variant *re validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); } +template +static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args) { + validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); +} + template static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(P...), void *ret, const void **p_args) { ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); } +template +static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(Callable::CallError &, P...), void *ret, const void **p_args) { + ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); +} + template static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(P...)) { return sizeof...(P); } +template +static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(Callable::CallError &, P...)) { + return sizeof...(P); +} + template static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int p_arg) { return call_get_argument_type(p_arg); } +template +static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(Callable::CallError &, P...), int p_arg) { + return call_get_argument_type(p_arg + 1); +} + template static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) { return GetTypeInfo::VARIANT_TYPE; @@ -1279,6 +1323,34 @@ static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_ (void)r_error; } +// struct CallHelperVoid +// { +// static void call() +// { +// } +// }; +// +// struct CallHelperRet +// { +// static void call() +// { +// } +// }; +// +// template +// static _FORCE_INLINE_ void _call_helper() +// { +// std::conditional::value, CallHelperVoid, CallHelperRet>::call(); +// } +// +// template +// static _FORCE_INLINE_ void call_helperp2(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence) { +// r_error.error = Callable::CallError::CALL_OK; +// p_func(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); +// (void)p_args; +// (void)r_error; +// } + template static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence) { p_func(VariantCaster

::cast(*p_args[Is])...); @@ -1321,319 +1393,10 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) { return Variant::NIL; } -#define FUNCBINDR(m_func, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args, r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - validated_call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - ptr_call_helperr(VariantUtilityFunctions::m_func, ret, p_args); \ - } \ - static int get_argument_count() { \ - return get_arg_count_helperr(VariantUtilityFunctions::m_func); \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return get_arg_type_helperr(VariantUtilityFunctions::m_func, p_arg); \ - } \ - static Variant::Type get_return_type() { \ - return get_ret_type_helperr(VariantUtilityFunctions::m_func); \ - } \ - static bool has_return_type() { \ - return true; \ - } \ - static bool is_vararg() { \ - return false; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) - -#define FUNCBINDVR(m_func, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - r_error.error = Callable::CallError::CALL_OK; \ - *r_ret = VariantUtilityFunctions::m_func(*p_args[0], r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - Callable::CallError ce; \ - *r_ret = VariantUtilityFunctions::m_func(*p_args[0], ce); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - Callable::CallError ce; \ - PtrToArg::encode(VariantUtilityFunctions::m_func(PtrToArg::convert(p_args[0]), ce), ret); \ - } \ - static int get_argument_count() { \ - return 1; \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return Variant::NIL; \ - } \ - static Variant::Type get_return_type() { \ - return Variant::NIL; \ - } \ - static bool has_return_type() { \ - return true; \ - } \ - static bool is_vararg() { \ - return false; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) - -#define FUNCBINDVR2(m_func, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - r_error.error = Callable::CallError::CALL_OK; \ - *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - Callable::CallError ce; \ - *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], ce); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - Callable::CallError ce; \ - Variant r; \ - r = VariantUtilityFunctions::m_func(PtrToArg::convert(p_args[0]), PtrToArg::convert(p_args[1]), ce); \ - PtrToArg::encode(r, ret); \ - } \ - static int get_argument_count() { \ - return 2; \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return Variant::NIL; \ - } \ - static Variant::Type get_return_type() { \ - return Variant::NIL; \ - } \ - static bool has_return_type() { \ - return true; \ - } \ - static bool is_vararg() { \ - return false; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) - -#define FUNCBINDVR3(m_func, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - r_error.error = Callable::CallError::CALL_OK; \ - *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - Callable::CallError ce; \ - *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], ce); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - Callable::CallError ce; \ - Variant r; \ - r = VariantUtilityFunctions::m_func(PtrToArg::convert(p_args[0]), PtrToArg::convert(p_args[1]), PtrToArg::convert(p_args[2]), ce); \ - PtrToArg::encode(r, ret); \ - } \ - static int get_argument_count() { \ - return 3; \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return Variant::NIL; \ - } \ - static Variant::Type get_return_type() { \ - return Variant::NIL; \ - } \ - static bool has_return_type() { \ - return true; \ - } \ - static bool is_vararg() { \ - return false; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) - -#define FUNCBINDVARARG(m_func, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - r_error.error = Callable::CallError::CALL_OK; \ - *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - Callable::CallError c; \ - *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, c); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - Vector args; \ - for (int i = 0; i < p_argcount; i++) { \ - args.push_back(PtrToArg::convert(p_args[i])); \ - } \ - Vector argsp; \ - for (int i = 0; i < p_argcount; i++) { \ - argsp.push_back(&args[i]); \ - } \ - Variant r; \ - validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \ - PtrToArg::encode(r, ret); \ - } \ - static int get_argument_count() { \ - return 2; \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return Variant::NIL; \ - } \ - static Variant::Type get_return_type() { \ - return Variant::NIL; \ - } \ - static bool has_return_type() { \ - return true; \ - } \ - static bool is_vararg() { \ - return true; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) - -#define FUNCBINDVARARGS(m_func, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - r_error.error = Callable::CallError::CALL_OK; \ - *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - Callable::CallError c; \ - *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, c); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - Vector args; \ - for (int i = 0; i < p_argcount; i++) { \ - args.push_back(PtrToArg::convert(p_args[i])); \ - } \ - Vector argsp; \ - for (int i = 0; i < p_argcount; i++) { \ - argsp.push_back(&args[i]); \ - } \ - Variant r; \ - validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \ - PtrToArg::encode(r.operator String(), ret); \ - } \ - static int get_argument_count() { \ - return 1; \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return Variant::NIL; \ - } \ - static Variant::Type get_return_type() { \ - return Variant::STRING; \ - } \ - static bool has_return_type() { \ - return true; \ - } \ - static bool is_vararg() { \ - return true; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) - -#define FUNCBINDVARARGV_CNAME(m_func, m_func_cname, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - r_error.error = Callable::CallError::CALL_OK; \ - VariantUtilityFunctions::m_func_cname(p_args, p_argcount, r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - Callable::CallError c; \ - VariantUtilityFunctions::m_func_cname(p_args, p_argcount, c); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - Vector args; \ - for (int i = 0; i < p_argcount; i++) { \ - args.push_back(PtrToArg::convert(p_args[i])); \ - } \ - Vector argsp; \ - for (int i = 0; i < p_argcount; i++) { \ - argsp.push_back(&args[i]); \ - } \ - Variant r; \ - validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \ - } \ - static int get_argument_count() { \ - return 1; \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return Variant::NIL; \ - } \ - static Variant::Type get_return_type() { \ - return Variant::NIL; \ - } \ - static bool has_return_type() { \ - return false; \ - } \ - static bool is_vararg() { \ - return true; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) - -#define FUNCBINDVARARGV(m_func, m_args, m_category) FUNCBINDVARARGV_CNAME(m_func, m_func, m_args, m_category) - -#define FUNCBIND(m_func, m_args, m_category) \ - class Func_##m_func { \ - public: \ - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ - call_helper(VariantUtilityFunctions::m_func, p_args, r_error); \ - } \ - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ - validated_call_helper(VariantUtilityFunctions::m_func, p_args); \ - } \ - static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ - ptr_call_helper(VariantUtilityFunctions::m_func, p_args); \ - } \ - static int get_argument_count() { \ - return get_arg_count_helper(VariantUtilityFunctions::m_func); \ - } \ - static Variant::Type get_argument_type(int p_arg) { \ - return get_arg_type_helper(VariantUtilityFunctions::m_func, p_arg); \ - } \ - static Variant::Type get_return_type() { \ - return get_ret_type_helper(VariantUtilityFunctions::m_func); \ - } \ - static bool has_return_type() { \ - return false; \ - } \ - static bool is_vararg() { \ - return false; \ - } \ - static Variant::UtilityFunctionType get_type() { \ - return m_category; \ - } \ - }; \ - register_utility_function(#m_func, m_args) +template +static _FORCE_INLINE_ Variant::Type get_ret_type_helper(Variant (*p_func)(P...)) { + return Variant::NIL; +} struct VariantUtilityFunctionInfo { void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = nullptr; @@ -1679,168 +1442,342 @@ static void register_utility_function(const String &p_name, const Vector utility_function_name_table.push_back(sname); } +template +struct Func; + +template +struct Func { + template + struct FuncInner { + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + call_helper(m_func, p_args, r_error); + } + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { + validated_call_helper(m_func, p_args); + } + static void ptrcall(void *ret, const void **p_args, int p_argcount) { + ptr_call_helper(m_func, p_args); + } + static int get_argument_count() { + return get_arg_count_helper(m_func); + } + static Variant::Type get_argument_type(int p_arg) { + return get_arg_type_helper(m_func, p_arg); + } + static Variant::Type get_return_type() { + return get_ret_type_helper(m_func); + } + static bool has_return_type() { + return false; + } + static bool is_vararg() { + return false; + } + static Variant::UtilityFunctionType get_type() { + return m_category; + } + static void register_fn(const String &name, const Vector &args) { + register_utility_function>(name, args); + } + }; +}; + +template <> +struct Func { + template + struct FuncInner { + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + m_func(r_error, p_args, p_argcount); + } + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { + Callable::CallError c; + m_func(c, p_args, p_argcount); + } + static void ptrcall(void *ret, const void **p_args, int p_argcount) { + Vector args; + for (int i = 0; i < p_argcount; i++) { + args.push_back(PtrToArg::convert(p_args[i])); + } + Vector argsp; + for (int i = 0; i < p_argcount; i++) { + argsp.push_back(&args[i]); + } + Variant r; + validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); + } + static int get_argument_count() { + return 1; + } + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + static Variant::Type get_return_type() { + return Variant::NIL; + } + static bool has_return_type() { + return false; + } + static bool is_vararg() { + return true; + } + static Variant::UtilityFunctionType get_type() { + return m_category; + } + static void register_fn(const String &name, const Vector &args) { + register_utility_function>(name, args); + } + }; +}; + +template +struct Func { + template + struct FuncInner { + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + *r_ret = m_func(r_error, p_args, p_argcount); + } + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { + Callable::CallError c; + *r_ret = m_func(c, p_args, p_argcount); + } + static void ptrcall(void *ret, const void **p_args, int p_argcount) { + Vector args; + for (int i = 0; i < p_argcount; i++) { + args.push_back(PtrToArg::convert(p_args[i])); + } + Vector argsp; + for (int i = 0; i < p_argcount; i++) { + argsp.push_back(&args[i]); + } + Variant r; + validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); + PtrToArg::encode(r.operator String(), ret); + } + static int get_argument_count() { + return 1; + } + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + static Variant::Type get_return_type() { + return Variant::STRING; + } + static bool has_return_type() { + return true; + } + static bool is_vararg() { + return true; + } + static Variant::UtilityFunctionType get_type() { + return m_category; + } + static void register_fn(const String &name, const Vector &args) { + register_utility_function>(name, args); + } + }; +}; + +template +struct Func { + template + struct FuncInner { + static void call(Variant *ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + call_helperr(m_func, ret, p_args, r_error); + } + static void validated_call(Variant *ret, const Variant **p_args, int p_argcount) { + validated_call_helperr(m_func, ret, p_args); + } + static void ptrcall(void *ret, const void **p_args, int p_argcount) { + ptr_call_helperr(m_func, ret, p_args); + } + static int get_argument_count() { + return get_arg_count_helperr(m_func); + } + static Variant::Type get_argument_type(int p_arg) { + return get_arg_type_helperr(m_func, p_arg); + } + static Variant::Type get_return_type() { + return get_ret_type_helperr(m_func); + } + static bool has_return_type() { + return true; + } + static bool is_vararg() { + return false; + } + static Variant::UtilityFunctionType get_type() { + return m_category; + } + static void register_fn(const String &name, const Vector &args) { + register_utility_function>(name, args); + } + }; +}; + void Variant::_register_variant_utility_functions() { // Math - FUNCBINDR(sin, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(cos, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(tan, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(sinh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(cosh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(tanh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(asin, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(acos, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(atan, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(atan2, sarray("y", "x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(asinh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(acosh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(atanh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(sqrt, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(fmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(fposmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(posmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR(floor, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(floorf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(floori, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR(ceil, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(ceilf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(ceili, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR(round, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(roundf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(roundi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR(abs, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(absf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(absi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR(sign, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(signf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(signi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR2(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(snappedf, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(snappedi, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(pow, sarray("base", "exp"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(log, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(exp, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(is_nan, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(is_inf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(is_equal_approx, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(is_zero_approx, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(is_finite, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(ease, sarray("x", "curve"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR3(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(lerpf, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(cubic_interpolate, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(cubic_interpolate_angle, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(cubic_interpolate_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(bezier_derivative, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(angle_difference, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(remap, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(remap_default, sarray("value", "istart", "istop", "ostart", "ostop", "default_value"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(rotate_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(deg_to_rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(rad_to_deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(linear_to_db, sarray("lin"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(db_to_linear, sarray("db"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR3(wrap, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(wrapi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(wrapf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVARARG(max, sarray(), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(maxi, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(maxf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVARARG(min, sarray(), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(mini, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(minf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDVR3(clamp, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(clampi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(nearest_po2, sarray("value"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(pingpong, sarray("value", "length"), Variant::UTILITY_FUNC_TYPE_MATH); - - FUNCBINDR(sigmoid, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(sigmoid_approx, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(sigmoid_affine, sarray("x", "amplitude", "y_translation"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(sigmoid_affine_approx, sarray("x", "amplitude", "y_translation"), Variant::UTILITY_FUNC_TYPE_MATH); + Func::FuncInner::register_fn("sin", sarray("angle_rad")); + Func::FuncInner::register_fn("cos", sarray("angle_rad")); + Func::FuncInner::register_fn("tan", sarray("angle_rad")); + + Func::FuncInner::register_fn("sinh", sarray("x")); + Func::FuncInner::register_fn("cosh", sarray("x")); + Func::FuncInner::register_fn("tanh", sarray("x")); + + Func::FuncInner::register_fn("asin", sarray("x")); + Func::FuncInner::register_fn("acos", sarray("x")); + Func::FuncInner::register_fn("atan", sarray("x")); + + Func::FuncInner::register_fn("atan2", sarray("y", "x")); + + Func::FuncInner::register_fn("asinh", sarray("x")); + Func::FuncInner::register_fn("acosh", sarray("x")); + Func::FuncInner::register_fn("atanh", sarray("x")); + + Func::FuncInner::register_fn("sqrt", sarray("x")); + Func::FuncInner::register_fn("fmod", sarray("x", "y")); + Func::FuncInner::register_fn("fposmod", sarray("x", "y")); + Func::FuncInner::register_fn("posmod", sarray("x", "y")); + + Func::FuncInner::register_fn("floor", sarray("x")); + Func::FuncInner::register_fn("floorf", sarray("x")); + Func::FuncInner::register_fn("floori", sarray("x")); + + Func::FuncInner::register_fn("ceil", sarray("x")); + Func::FuncInner::register_fn("ceilf", sarray("x")); + Func::FuncInner::register_fn("ceili", sarray("x")); + + Func::FuncInner::register_fn("round", sarray("x")); + Func::FuncInner::register_fn("roundf", sarray("x")); + Func::FuncInner::register_fn("roundi", sarray("x")); + + Func::FuncInner::register_fn("abs", sarray("x")); + Func::FuncInner::register_fn("absf", sarray("x")); + Func::FuncInner::register_fn("absi", sarray("x")); + + Func::FuncInner::register_fn("sign", sarray("x")); + Func::FuncInner::register_fn("signf", sarray("x")); + Func::FuncInner::register_fn("signi", sarray("x")); + + Func::FuncInner::register_fn("snapped", sarray("x", "step")); + Func::FuncInner::register_fn("snappedf", sarray("x", "step")); + Func::FuncInner::register_fn("snappedi", sarray("x", "step")); + + Func::FuncInner::register_fn("pow", sarray("base", "exp")); + Func::FuncInner::register_fn("log", sarray("x")); + Func::FuncInner::register_fn("exp", sarray("x")); + + Func::FuncInner::register_fn("is_nan", sarray("x")); + Func::FuncInner::register_fn("is_inf", sarray("x")); + + Func::FuncInner::register_fn("is_equal_approx", sarray("a", "b")); + Func::FuncInner::register_fn("is_zero_approx", sarray("x")); + Func::FuncInner::register_fn("is_finite", sarray("x")); + + Func::FuncInner::register_fn("ease", sarray("x", "curve")); + Func::FuncInner::register_fn("step_decimals", sarray("x")); + + Func::FuncInner::register_fn("lerp", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("lerpf", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("cubic_interpolate", sarray("from", "to", "pre", "post", "weight")); + Func::FuncInner::register_fn("cubic_interpolate_angle", sarray("from", "to", "pre", "post", "weight")); + Func::FuncInner::register_fn("cubic_interpolate_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); + Func::FuncInner::register_fn("cubic_interpolate_angle_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); + Func::FuncInner::register_fn("bezier_interpolate", sarray("start", "control_1", "control_2", "end", "t")); + Func::FuncInner::register_fn("bezier_derivative", sarray("start", "control_1", "control_2", "end", "t")); + Func::FuncInner::register_fn("angle_difference", sarray("from", "to")); + Func::FuncInner::register_fn("lerp_angle", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("inverse_lerp", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("remap", sarray("value", "istart", "istop", "ostart", "ostop")); + Func::FuncInner::register_fn("remap_default", sarray("value", "istart", "istop", "ostart", "ostop", "default_value")); + + Func::FuncInner::register_fn("smoothstep", sarray("from", "to", "x")); + Func::FuncInner::register_fn("move_toward", sarray("from", "to", "delta")); + Func::FuncInner::register_fn("rotate_toward", sarray("from", "to", "delta")); + + Func::FuncInner::register_fn("deg_to_rad", sarray("deg")); + Func::FuncInner::register_fn("rad_to_deg", sarray("rad")); + Func::FuncInner::register_fn("linear_to_db", sarray("lin")); + Func::FuncInner::register_fn("db_to_linear", sarray("db")); + + Func::FuncInner::register_fn("wrap", sarray("value", "min", "max")); + Func::FuncInner::register_fn("wrapi", sarray("value", "min", "max")); + Func::FuncInner::register_fn("wrapf", sarray("value", "min", "max")); + + Func::FuncInner::register_fn("max", sarray()); + Func::FuncInner::register_fn("maxi", sarray("a", "b")); + Func::FuncInner::register_fn("maxf", sarray("a", "b")); + + Func::FuncInner::register_fn("min", sarray()); + Func::FuncInner::register_fn("mini", sarray("a", "b")); + Func::FuncInner::register_fn("minf", sarray("a", "b")); + + Func::FuncInner::register_fn("clamp", sarray("value", "min", "max")); + Func::FuncInner::register_fn("clampi", sarray("value", "min", "max")); + Func::FuncInner::register_fn("clampf", sarray("value", "min", "max")); + + Func::FuncInner::register_fn("nearest_po2", sarray("value")); + Func::FuncInner::register_fn("pingpong", sarray("value", "length")); + + Func::FuncInner::register_fn("sigmoid", sarray("x")); + Func::FuncInner::register_fn("sigmoid_approx", sarray("x")); + Func::FuncInner::register_fn("sigmoid_affine", sarray("x", "amplitude", "y_translation")); + Func::FuncInner::register_fn("sigmoid_affine_approx", sarray("x", "amplitude", "y_translation")); // Random - FUNCBIND(randomize, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); - FUNCBINDR(randi, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); - FUNCBINDR(randf, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); - FUNCBINDR(randi_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM); - FUNCBINDR(randf_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM); - FUNCBINDR(randfn, sarray("mean", "deviation"), Variant::UTILITY_FUNC_TYPE_RANDOM); - FUNCBIND(seed, sarray("base"), Variant::UTILITY_FUNC_TYPE_RANDOM); - FUNCBINDR(rand_from_seed, sarray("seed"), Variant::UTILITY_FUNC_TYPE_RANDOM); + Func::FuncInner::register_fn("randomize", sarray()); + Func::FuncInner::register_fn("randi", sarray()); + Func::FuncInner::register_fn("randf", sarray()); + Func::FuncInner::register_fn("randi_range", sarray("from", "to")); + Func::FuncInner::register_fn("randf_range", sarray("from", "to")); + Func::FuncInner::register_fn("randfn", sarray("mean", "deviation")); + Func::FuncInner::register_fn("seed", sarray("base")); + Func::FuncInner::register_fn("rand_from_seed", sarray("seed")); // Utility - FUNCBINDVR(weakref, sarray("obj"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(_typeof, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(type_convert, sarray("variant", "type"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGS(str, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(error_string, sarray("error"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(type_string, sarray("type"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(print, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(print_rich, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(printerr, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(printt, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(prints, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(printraw, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV_CNAME(print_verbose, _print_verbose, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("weakref", sarray("obj")); + Func::FuncInner::register_fn("_typeof", sarray("variable")); + Func::FuncInner::register_fn("type_convert", sarray("variant", "type")); + Func::FuncInner::register_fn("str", sarray()); + Func::FuncInner::register_fn("error_string", sarray("error")); + Func::FuncInner::register_fn("type_string", sarray("type")); + Func::FuncInner::register_fn("print", sarray()); + Func::FuncInner::register_fn("print_rich", sarray()); + Func::FuncInner::register_fn("printerr", sarray()); + Func::FuncInner::register_fn("printt", sarray()); + Func::FuncInner::register_fn("prints", sarray()); + Func::FuncInner::register_fn("printraw", sarray()); + Func::FuncInner::register_fn("print_verbose", sarray()); + Func::FuncInner::register_fn("push_error", sarray()); + Func::FuncInner::register_fn("push_warning", sarray()); - FUNCBINDR(var_to_str, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(str_to_var, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("var_to_str", sarray("variable")); + Func::FuncInner::register_fn("str_to_var", sarray("string")); - FUNCBINDR(var_to_str_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(str_to_var_with_objects, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("var_to_str_with_objects", sarray("variable")); + Func::FuncInner::register_fn("str_to_var_with_objects", sarray("string")); - FUNCBINDR(var_to_bytes, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(bytes_to_var, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("var_to_bytes", sarray("variable")); + Func::FuncInner::register_fn("bytes_to_var", sarray("bytes")); - FUNCBINDR(var_to_bytes_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(bytes_to_var_with_objects, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("var_to_bytes_with_objects", sarray("variable")); + Func::FuncInner::register_fn("bytes_to_var_with_objects", sarray("bytes")); - FUNCBINDR(hash, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("hash", sarray("variable")); - FUNCBINDR(instance_from_id, sarray("instance_id"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(is_instance_id_valid, sarray("id"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(is_instance_valid, sarray("instance"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("instance_from_id", sarray("instance_id")); + Func::FuncInner::register_fn("is_instance_id_valid", sarray("id")); + Func::FuncInner::register_fn("is_instance_valid", sarray("instance")); - FUNCBINDR(rid_allocate_id, Vector(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(rid_from_int64, sarray("base"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("rid_allocate_id", Vector()); + Func::FuncInner::register_fn("rid_from_int64", sarray("base")); - FUNCBINDR(is_same, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_GENERAL); + Func::FuncInner::register_fn("is_same", sarray("a", "b")); } void Variant::_unregister_variant_utility_functions() { diff --git a/core/variant/variant_utility.h b/core/variant/variant_utility.h index 13e1d14c80d..ee2d11fb540 100644 --- a/core/variant/variant_utility.h +++ b/core/variant/variant_utility.h @@ -53,19 +53,19 @@ struct VariantUtilityFunctions { static double fmod(double b, double r); static double fposmod(double b, double r); static int64_t posmod(int64_t b, int64_t r); - static Variant floor(const Variant &x, Callable::CallError &r_error); + static Variant floor(Callable::CallError &r_error, const Variant &x); static double floorf(double x); static int64_t floori(double x); - static Variant ceil(const Variant &x, Callable::CallError &r_error); + static Variant ceil(Callable::CallError &r_error, const Variant &x); static double ceilf(double x); static int64_t ceili(double x); - static Variant round(const Variant &x, Callable::CallError &r_error); + static Variant round(Callable::CallError &r_error, const Variant &x); static double roundf(double x); static int64_t roundi(double x); - static Variant abs(const Variant &x, Callable::CallError &r_error); + static Variant abs(Callable::CallError &r_error, const Variant &x); static double absf(double x); static int64_t absi(int64_t x); - static Variant sign(const Variant &x, Callable::CallError &r_error); + static Variant sign(Callable::CallError &r_error, const Variant &x); static double signf(double x); static int64_t signi(int64_t x); static double pow(double x, double y); @@ -78,10 +78,10 @@ struct VariantUtilityFunctions { static bool is_finite(double x); static double ease(float x, float curve); static int step_decimals(float step); - static Variant snapped(const Variant &x, const Variant &step, Callable::CallError &r_error); + static Variant snapped(Callable::CallError &r_error, const Variant &x, const Variant &step); static double snappedf(double x, double step); static int64_t snappedi(double x, int64_t step); - static Variant lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error); + static Variant lerp(Callable::CallError &r_error, const Variant &from, const Variant &to, double weight); static double lerpf(double from, double to, double weight); static double cubic_interpolate(double from, double to, double pre, double post, double weight); static double cubic_interpolate_angle(double from, double to, double pre, double post, double weight); @@ -103,17 +103,17 @@ struct VariantUtilityFunctions { static double rad_to_deg(double angle_rad); static double linear_to_db(double linear); static double db_to_linear(double db); - static Variant wrap(const Variant &p_x, const Variant &p_min, const Variant &p_max, Callable::CallError &r_error); + static Variant wrap(Callable::CallError &r_error, const Variant &p_x, const Variant &p_min, const Variant &p_max); static int64_t wrapi(int64_t value, int64_t min, int64_t max); static double wrapf(double value, double min, double max); static double pingpong(double value, double length); - static Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error); + static Variant max(Callable::CallError &r_error, const Variant **p_args, int p_argcount); static double maxf(double x, double y); static int64_t maxi(int64_t x, int64_t y); - static Variant min(const Variant **p_args, int p_argcount, Callable::CallError &r_error); + static Variant min(Callable::CallError &r_error, const Variant **p_args, int p_argcount); static double minf(double x, double y); static int64_t mini(int64_t x, int64_t y); - static Variant clamp(const Variant &x, const Variant &min, const Variant &max, Callable::CallError &r_error); + static Variant clamp(Callable::CallError &r_error, const Variant &x, const Variant &min, const Variant &max); static double clampf(double x, double min, double max); static int64_t clampi(int64_t x, int64_t min, int64_t max); static int64_t nearest_po2(int64_t x); @@ -131,21 +131,21 @@ struct VariantUtilityFunctions { static void seed(int64_t s); static PackedInt64Array rand_from_seed(int64_t seed); // Utility - static Variant weakref(const Variant &obj, Callable::CallError &r_error); + static Variant weakref(Callable::CallError &r_error, const Variant &obj); static int64_t _typeof(const Variant &obj); static Variant type_convert(const Variant &p_variant, const Variant::Type p_type); - static String str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); + static String str(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); static String error_string(Error error); static String type_string(Variant::Type p_type); - static void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void print_rich(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void _print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); - static void push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); + static void print(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void print_rich(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void _print_verbose(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void printerr(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void printt(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void prints(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void printraw(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void push_error(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); + static void push_warning(Callable::CallError &r_error, const Variant **p_args, int p_arg_count); static String var_to_str(const Variant &p_var); static String var_to_str_with_objects(const Variant &p_var); static Variant str_to_var(const String &p_var); From 3df70544e1601539ea45b5e6ffb354258d7cc5eb Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Fri, 13 Mar 2026 20:54:43 -0400 Subject: [PATCH 02/12] Fix errant check --- core/variant/variant_utility.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index fc89c79fd5b..ebc6c9b7ab8 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1046,6 +1046,7 @@ void VariantUtilityFunctions::push_error(Callable::CallError &r_error, const Var if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.expected = 1; + return; } ERR_PRINT(join_string(p_args, p_arg_count)); @@ -1056,6 +1057,7 @@ void VariantUtilityFunctions::push_warning(Callable::CallError &r_error, const V if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.expected = 1; + return; } WARN_PRINT(join_string(p_args, p_arg_count)); From c9ef4059869a53bd06460ae91d9e471685337da7 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Fri, 13 Mar 2026 21:04:51 -0400 Subject: [PATCH 03/12] Thank you Code Rabbit --- core/variant/variant_utility.cpp | 54 ++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index ebc6c9b7ab8..6c9312e199d 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1307,7 +1307,7 @@ static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int template static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(Callable::CallError &, P...), int p_arg) { - return call_get_argument_type(p_arg + 1); + return call_get_argument_type(p_arg); } template @@ -1532,6 +1532,55 @@ struct Func { }; }; +template <> +struct Func { + template + struct FuncInner { + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + *r_ret = m_func(r_error, p_args, p_argcount); + } + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { + Callable::CallError c; + *r_ret = m_func(c, p_args, p_argcount); + } + static void ptrcall(void *ret, const void **p_args, int p_argcount) { + Vector args; + for (int i = 0; i < p_argcount; i++) { + args.push_back(PtrToArg::convert(p_args[i])); + } + Vector argsp; + for (int i = 0; i < p_argcount; i++) { + argsp.push_back(&args[i]); + } + Variant r; + validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); + PtrToArg::encode(r.operator String(), ret); + } + static int get_argument_count() { + return 1; + } + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + static Variant::Type get_return_type() { + return Variant::STRING; + } + static bool has_return_type() { + return true; + } + static bool is_vararg() { + return true; + } + static Variant::UtilityFunctionType get_type() { + return m_category; + } + static void register_fn(const String &name, const Vector &args) { + register_utility_function>(name, args); + } + }; +}; + template struct Func { template @@ -1555,7 +1604,6 @@ struct Func { } Variant r; validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); - PtrToArg::encode(r.operator String(), ret); } static int get_argument_count() { return 1; @@ -1564,7 +1612,7 @@ struct Func { return Variant::NIL; } static Variant::Type get_return_type() { - return Variant::STRING; + return Variant::NIL; } static bool has_return_type() { return true; From b74577791e8512ed6d2d5d5dbe4aeb512d485681 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Fri, 13 Mar 2026 21:13:32 -0400 Subject: [PATCH 04/12] Remove commented out code --- core/variant/variant_utility.cpp | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 6c9312e199d..c119ff41648 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1325,34 +1325,6 @@ static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_ (void)r_error; } -// struct CallHelperVoid -// { -// static void call() -// { -// } -// }; -// -// struct CallHelperRet -// { -// static void call() -// { -// } -// }; -// -// template -// static _FORCE_INLINE_ void _call_helper() -// { -// std::conditional::value, CallHelperVoid, CallHelperRet>::call(); -// } -// -// template -// static _FORCE_INLINE_ void call_helperp2(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence) { -// r_error.error = Callable::CallError::CALL_OK; -// p_func(VariantCasterAndValidate

::cast(p_args, Is, r_error)...); -// (void)p_args; -// (void)r_error; -// } - template static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence) { p_func(VariantCaster

::cast(*p_args[Is])...); From 3a74610e61af5323249e1cb87295dccf57da4932 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 2 Apr 2026 22:42:54 -0400 Subject: [PATCH 05/12] Concessions for the... special... compiler :sillybastard: --- core/variant/variant_utility.cpp | 286 +++++++++++++++---------------- 1 file changed, 143 insertions(+), 143 deletions(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index c119ff41648..8bfc686282f 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1641,165 +1641,165 @@ struct Func { void Variant::_register_variant_utility_functions() { // Math - Func::FuncInner::register_fn("sin", sarray("angle_rad")); - Func::FuncInner::register_fn("cos", sarray("angle_rad")); - Func::FuncInner::register_fn("tan", sarray("angle_rad")); - - Func::FuncInner::register_fn("sinh", sarray("x")); - Func::FuncInner::register_fn("cosh", sarray("x")); - Func::FuncInner::register_fn("tanh", sarray("x")); - - Func::FuncInner::register_fn("asin", sarray("x")); - Func::FuncInner::register_fn("acos", sarray("x")); - Func::FuncInner::register_fn("atan", sarray("x")); - - Func::FuncInner::register_fn("atan2", sarray("y", "x")); - - Func::FuncInner::register_fn("asinh", sarray("x")); - Func::FuncInner::register_fn("acosh", sarray("x")); - Func::FuncInner::register_fn("atanh", sarray("x")); - - Func::FuncInner::register_fn("sqrt", sarray("x")); - Func::FuncInner::register_fn("fmod", sarray("x", "y")); - Func::FuncInner::register_fn("fposmod", sarray("x", "y")); - Func::FuncInner::register_fn("posmod", sarray("x", "y")); - - Func::FuncInner::register_fn("floor", sarray("x")); - Func::FuncInner::register_fn("floorf", sarray("x")); - Func::FuncInner::register_fn("floori", sarray("x")); - - Func::FuncInner::register_fn("ceil", sarray("x")); - Func::FuncInner::register_fn("ceilf", sarray("x")); - Func::FuncInner::register_fn("ceili", sarray("x")); - - Func::FuncInner::register_fn("round", sarray("x")); - Func::FuncInner::register_fn("roundf", sarray("x")); - Func::FuncInner::register_fn("roundi", sarray("x")); - - Func::FuncInner::register_fn("abs", sarray("x")); - Func::FuncInner::register_fn("absf", sarray("x")); - Func::FuncInner::register_fn("absi", sarray("x")); - - Func::FuncInner::register_fn("sign", sarray("x")); - Func::FuncInner::register_fn("signf", sarray("x")); - Func::FuncInner::register_fn("signi", sarray("x")); - - Func::FuncInner::register_fn("snapped", sarray("x", "step")); - Func::FuncInner::register_fn("snappedf", sarray("x", "step")); - Func::FuncInner::register_fn("snappedi", sarray("x", "step")); - - Func::FuncInner::register_fn("pow", sarray("base", "exp")); - Func::FuncInner::register_fn("log", sarray("x")); - Func::FuncInner::register_fn("exp", sarray("x")); - - Func::FuncInner::register_fn("is_nan", sarray("x")); - Func::FuncInner::register_fn("is_inf", sarray("x")); - - Func::FuncInner::register_fn("is_equal_approx", sarray("a", "b")); - Func::FuncInner::register_fn("is_zero_approx", sarray("x")); - Func::FuncInner::register_fn("is_finite", sarray("x")); - - Func::FuncInner::register_fn("ease", sarray("x", "curve")); - Func::FuncInner::register_fn("step_decimals", sarray("x")); - - Func::FuncInner::register_fn("lerp", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("lerpf", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("cubic_interpolate", sarray("from", "to", "pre", "post", "weight")); - Func::FuncInner::register_fn("cubic_interpolate_angle", sarray("from", "to", "pre", "post", "weight")); - Func::FuncInner::register_fn("cubic_interpolate_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); - Func::FuncInner::register_fn("cubic_interpolate_angle_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); - Func::FuncInner::register_fn("bezier_interpolate", sarray("start", "control_1", "control_2", "end", "t")); - Func::FuncInner::register_fn("bezier_derivative", sarray("start", "control_1", "control_2", "end", "t")); - Func::FuncInner::register_fn("angle_difference", sarray("from", "to")); - Func::FuncInner::register_fn("lerp_angle", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("inverse_lerp", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("remap", sarray("value", "istart", "istop", "ostart", "ostop")); - Func::FuncInner::register_fn("remap_default", sarray("value", "istart", "istop", "ostart", "ostop", "default_value")); - - Func::FuncInner::register_fn("smoothstep", sarray("from", "to", "x")); - Func::FuncInner::register_fn("move_toward", sarray("from", "to", "delta")); - Func::FuncInner::register_fn("rotate_toward", sarray("from", "to", "delta")); - - Func::FuncInner::register_fn("deg_to_rad", sarray("deg")); - Func::FuncInner::register_fn("rad_to_deg", sarray("rad")); - Func::FuncInner::register_fn("linear_to_db", sarray("lin")); - Func::FuncInner::register_fn("db_to_linear", sarray("db")); - - Func::FuncInner::register_fn("wrap", sarray("value", "min", "max")); - Func::FuncInner::register_fn("wrapi", sarray("value", "min", "max")); - Func::FuncInner::register_fn("wrapf", sarray("value", "min", "max")); - - Func::FuncInner::register_fn("max", sarray()); - Func::FuncInner::register_fn("maxi", sarray("a", "b")); - Func::FuncInner::register_fn("maxf", sarray("a", "b")); - - Func::FuncInner::register_fn("min", sarray()); - Func::FuncInner::register_fn("mini", sarray("a", "b")); - Func::FuncInner::register_fn("minf", sarray("a", "b")); - - Func::FuncInner::register_fn("clamp", sarray("value", "min", "max")); - Func::FuncInner::register_fn("clampi", sarray("value", "min", "max")); - Func::FuncInner::register_fn("clampf", sarray("value", "min", "max")); - - Func::FuncInner::register_fn("nearest_po2", sarray("value")); - Func::FuncInner::register_fn("pingpong", sarray("value", "length")); - - Func::FuncInner::register_fn("sigmoid", sarray("x")); - Func::FuncInner::register_fn("sigmoid_approx", sarray("x")); - Func::FuncInner::register_fn("sigmoid_affine", sarray("x", "amplitude", "y_translation")); - Func::FuncInner::register_fn("sigmoid_affine_approx", sarray("x", "amplitude", "y_translation")); + Func::FuncInner::register_fn("sin", sarray("angle_rad")); + Func::FuncInner::register_fn("cos", sarray("angle_rad")); + Func::FuncInner::register_fn("tan", sarray("angle_rad")); + + Func::FuncInner::register_fn("sinh", sarray("x")); + Func::FuncInner::register_fn("cosh", sarray("x")); + Func::FuncInner::register_fn("tanh", sarray("x")); + + Func::FuncInner::register_fn("asin", sarray("x")); + Func::FuncInner::register_fn("acos", sarray("x")); + Func::FuncInner::register_fn("atan", sarray("x")); + + Func::FuncInner::register_fn("atan2", sarray("y", "x")); + + Func::FuncInner::register_fn("asinh", sarray("x")); + Func::FuncInner::register_fn("acosh", sarray("x")); + Func::FuncInner::register_fn("atanh", sarray("x")); + + Func::FuncInner::register_fn("sqrt", sarray("x")); + Func::FuncInner::register_fn("fmod", sarray("x", "y")); + Func::FuncInner::register_fn("fposmod", sarray("x", "y")); + Func::FuncInner::register_fn("posmod", sarray("x", "y")); + + Func::FuncInner::register_fn("floor", sarray("x")); + Func::FuncInner::register_fn("floorf", sarray("x")); + Func::FuncInner::register_fn("floori", sarray("x")); + + Func::FuncInner::register_fn("ceil", sarray("x")); + Func::FuncInner::register_fn("ceilf", sarray("x")); + Func::FuncInner::register_fn("ceili", sarray("x")); + + Func::FuncInner::register_fn("round", sarray("x")); + Func::FuncInner::register_fn("roundf", sarray("x")); + Func::FuncInner::register_fn("roundi", sarray("x")); + + Func::FuncInner::register_fn("abs", sarray("x")); + Func::FuncInner::register_fn("absf", sarray("x")); + Func::FuncInner::register_fn("absi", sarray("x")); + + Func::FuncInner::register_fn("sign", sarray("x")); + Func::FuncInner::register_fn("signf", sarray("x")); + Func::FuncInner::register_fn("signi", sarray("x")); + + Func::FuncInner::register_fn("snapped", sarray("x", "step")); + Func::FuncInner::register_fn("snappedf", sarray("x", "step")); + Func::FuncInner::register_fn("snappedi", sarray("x", "step")); + + Func::FuncInner::register_fn("pow", sarray("base", "exp")); + Func::FuncInner::register_fn("log", sarray("x")); + Func::FuncInner::register_fn("exp", sarray("x")); + + Func::FuncInner::register_fn("is_nan", sarray("x")); + Func::FuncInner::register_fn("is_inf", sarray("x")); + + Func::FuncInner::register_fn("is_equal_approx", sarray("a", "b")); + Func::FuncInner::register_fn("is_zero_approx", sarray("x")); + Func::FuncInner::register_fn("is_finite", sarray("x")); + + Func::FuncInner::register_fn("ease", sarray("x", "curve")); + Func::FuncInner::register_fn("step_decimals", sarray("x")); + + Func::FuncInner::register_fn("lerp", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("lerpf", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("cubic_interpolate", sarray("from", "to", "pre", "post", "weight")); + Func::FuncInner::register_fn("cubic_interpolate_angle", sarray("from", "to", "pre", "post", "weight")); + Func::FuncInner::register_fn("cubic_interpolate_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); + Func::FuncInner::register_fn("cubic_interpolate_angle_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); + Func::FuncInner::register_fn("bezier_interpolate", sarray("start", "control_1", "control_2", "end", "t")); + Func::FuncInner::register_fn("bezier_derivative", sarray("start", "control_1", "control_2", "end", "t")); + Func::FuncInner::register_fn("angle_difference", sarray("from", "to")); + Func::FuncInner::register_fn("lerp_angle", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("inverse_lerp", sarray("from", "to", "weight")); + Func::FuncInner::register_fn("remap", sarray("value", "istart", "istop", "ostart", "ostop")); + Func::FuncInner::register_fn("remap_default", sarray("value", "istart", "istop", "ostart", "ostop", "default_value")); + + Func::FuncInner::register_fn("smoothstep", sarray("from", "to", "x")); + Func::FuncInner::register_fn("move_toward", sarray("from", "to", "delta")); + Func::FuncInner::register_fn("rotate_toward", sarray("from", "to", "delta")); + + Func::FuncInner::register_fn("deg_to_rad", sarray("deg")); + Func::FuncInner::register_fn("rad_to_deg", sarray("rad")); + Func::FuncInner::register_fn("linear_to_db", sarray("lin")); + Func::FuncInner::register_fn("db_to_linear", sarray("db")); + + Func::FuncInner::register_fn("wrap", sarray("value", "min", "max")); + Func::FuncInner::register_fn("wrapi", sarray("value", "min", "max")); + Func::FuncInner::register_fn("wrapf", sarray("value", "min", "max")); + + Func::FuncInner::register_fn("max", sarray()); + Func::FuncInner::register_fn("maxi", sarray("a", "b")); + Func::FuncInner::register_fn("maxf", sarray("a", "b")); + + Func::FuncInner::register_fn("min", sarray()); + Func::FuncInner::register_fn("mini", sarray("a", "b")); + Func::FuncInner::register_fn("minf", sarray("a", "b")); + + Func::FuncInner::register_fn("clamp", sarray("value", "min", "max")); + Func::FuncInner::register_fn("clampi", sarray("value", "min", "max")); + Func::FuncInner::register_fn("clampf", sarray("value", "min", "max")); + + Func::FuncInner::register_fn("nearest_po2", sarray("value")); + Func::FuncInner::register_fn("pingpong", sarray("value", "length")); + + Func::FuncInner::register_fn("sigmoid", sarray("x")); + Func::FuncInner::register_fn("sigmoid_approx", sarray("x")); + Func::FuncInner::register_fn("sigmoid_affine", sarray("x", "amplitude", "y_translation")); + Func::FuncInner::register_fn("sigmoid_affine_approx", sarray("x", "amplitude", "y_translation")); // Random Func::FuncInner::register_fn("randomize", sarray()); - Func::FuncInner::register_fn("randi", sarray()); - Func::FuncInner::register_fn("randf", sarray()); - Func::FuncInner::register_fn("randi_range", sarray("from", "to")); - Func::FuncInner::register_fn("randf_range", sarray("from", "to")); - Func::FuncInner::register_fn("randfn", sarray("mean", "deviation")); + Func::FuncInner::register_fn("randi", sarray()); + Func::FuncInner::register_fn("randf", sarray()); + Func::FuncInner::register_fn("randi_range", sarray("from", "to")); + Func::FuncInner::register_fn("randf_range", sarray("from", "to")); + Func::FuncInner::register_fn("randfn", sarray("mean", "deviation")); Func::FuncInner::register_fn("seed", sarray("base")); - Func::FuncInner::register_fn("rand_from_seed", sarray("seed")); + Func::FuncInner::register_fn("rand_from_seed", sarray("seed")); // Utility - Func::FuncInner::register_fn("weakref", sarray("obj")); - Func::FuncInner::register_fn("_typeof", sarray("variable")); - Func::FuncInner::register_fn("type_convert", sarray("variant", "type")); - Func::FuncInner::register_fn("str", sarray()); - Func::FuncInner::register_fn("error_string", sarray("error")); - Func::FuncInner::register_fn("type_string", sarray("type")); - Func::FuncInner::register_fn("print", sarray()); - Func::FuncInner::register_fn("print_rich", sarray()); - Func::FuncInner::register_fn("printerr", sarray()); - Func::FuncInner::register_fn("printt", sarray()); - Func::FuncInner::register_fn("prints", sarray()); - Func::FuncInner::register_fn("printraw", sarray()); - Func::FuncInner::register_fn("print_verbose", sarray()); - Func::FuncInner::register_fn("push_error", sarray()); - Func::FuncInner::register_fn("push_warning", sarray()); + Func::FuncInner::register_fn("weakref", sarray("obj")); + Func::FuncInner::register_fn("_typeof", sarray("variable")); + Func::FuncInner::register_fn("type_convert", sarray("variant", "type")); + Func::FuncInner::register_fn("str", sarray()); + Func::FuncInner::register_fn("error_string", sarray("error")); + Func::FuncInner::register_fn("type_string", sarray("type")); + Func::FuncInner::register_fn("print", sarray()); + Func::FuncInner::register_fn("print_rich", sarray()); + Func::FuncInner::register_fn("printerr", sarray()); + Func::FuncInner::register_fn("printt", sarray()); + Func::FuncInner::register_fn("prints", sarray()); + Func::FuncInner::register_fn("printraw", sarray()); + Func::FuncInner::register_fn("print_verbose", sarray()); + Func::FuncInner::register_fn("push_error", sarray()); + Func::FuncInner::register_fn("push_warning", sarray()); - Func::FuncInner::register_fn("var_to_str", sarray("variable")); - Func::FuncInner::register_fn("str_to_var", sarray("string")); + Func::FuncInner::register_fn("var_to_str", sarray("variable")); + Func::FuncInner::register_fn("str_to_var", sarray("string")); - Func::FuncInner::register_fn("var_to_str_with_objects", sarray("variable")); - Func::FuncInner::register_fn("str_to_var_with_objects", sarray("string")); + Func::FuncInner::register_fn("var_to_str_with_objects", sarray("variable")); + Func::FuncInner::register_fn("str_to_var_with_objects", sarray("string")); - Func::FuncInner::register_fn("var_to_bytes", sarray("variable")); - Func::FuncInner::register_fn("bytes_to_var", sarray("bytes")); + Func::FuncInner::register_fn("var_to_bytes", sarray("variable")); + Func::FuncInner::register_fn("bytes_to_var", sarray("bytes")); - Func::FuncInner::register_fn("var_to_bytes_with_objects", sarray("variable")); - Func::FuncInner::register_fn("bytes_to_var_with_objects", sarray("bytes")); + Func::FuncInner::register_fn("var_to_bytes_with_objects", sarray("variable")); + Func::FuncInner::register_fn("bytes_to_var_with_objects", sarray("bytes")); - Func::FuncInner::register_fn("hash", sarray("variable")); + Func::FuncInner::register_fn("hash", sarray("variable")); - Func::FuncInner::register_fn("instance_from_id", sarray("instance_id")); - Func::FuncInner::register_fn("is_instance_id_valid", sarray("id")); - Func::FuncInner::register_fn("is_instance_valid", sarray("instance")); + Func::FuncInner::register_fn("instance_from_id", sarray("instance_id")); + Func::FuncInner::register_fn("is_instance_id_valid", sarray("id")); + Func::FuncInner::register_fn("is_instance_valid", sarray("instance")); - Func::FuncInner::register_fn("rid_allocate_id", Vector()); - Func::FuncInner::register_fn("rid_from_int64", sarray("base")); + Func::FuncInner::register_fn("rid_allocate_id", Vector()); + Func::FuncInner::register_fn("rid_from_int64", sarray("base")); - Func::FuncInner::register_fn("is_same", sarray("a", "b")); + Func::FuncInner::register_fn("is_same", sarray("a", "b")); } void Variant::_unregister_variant_utility_functions() { From a822429a138f916ee86548421125ac39863ea8f5 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 2 Apr 2026 22:43:42 -0400 Subject: [PATCH 06/12] Tuck things behind a macro --- core/variant/variant_utility.cpp | 299 ++++++++++++++++--------------- 1 file changed, 154 insertions(+), 145 deletions(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 8bfc686282f..8ded362c8e7 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1638,168 +1638,177 @@ struct Func { }; }; +// This can't handle overloads. If you are handling an overloaded function, +// just use the template directly +#define bind_fn(fn, category, name, ...) \ + Func::FuncInner::register_fn(name, sarray(__VA_ARGS__)) + +// This only handles functions in the `VariantUtilityFunctions` struct +#define bind_fn_vuf(fn, category, ...) \ + Func::FuncInner::register_fn(#fn, sarray(__VA_ARGS__)) + void Variant::_register_variant_utility_functions() { // Math - Func::FuncInner::register_fn("sin", sarray("angle_rad")); - Func::FuncInner::register_fn("cos", sarray("angle_rad")); - Func::FuncInner::register_fn("tan", sarray("angle_rad")); - - Func::FuncInner::register_fn("sinh", sarray("x")); - Func::FuncInner::register_fn("cosh", sarray("x")); - Func::FuncInner::register_fn("tanh", sarray("x")); - - Func::FuncInner::register_fn("asin", sarray("x")); - Func::FuncInner::register_fn("acos", sarray("x")); - Func::FuncInner::register_fn("atan", sarray("x")); - - Func::FuncInner::register_fn("atan2", sarray("y", "x")); - - Func::FuncInner::register_fn("asinh", sarray("x")); - Func::FuncInner::register_fn("acosh", sarray("x")); - Func::FuncInner::register_fn("atanh", sarray("x")); - - Func::FuncInner::register_fn("sqrt", sarray("x")); - Func::FuncInner::register_fn("fmod", sarray("x", "y")); - Func::FuncInner::register_fn("fposmod", sarray("x", "y")); - Func::FuncInner::register_fn("posmod", sarray("x", "y")); - - Func::FuncInner::register_fn("floor", sarray("x")); - Func::FuncInner::register_fn("floorf", sarray("x")); - Func::FuncInner::register_fn("floori", sarray("x")); - - Func::FuncInner::register_fn("ceil", sarray("x")); - Func::FuncInner::register_fn("ceilf", sarray("x")); - Func::FuncInner::register_fn("ceili", sarray("x")); - - Func::FuncInner::register_fn("round", sarray("x")); - Func::FuncInner::register_fn("roundf", sarray("x")); - Func::FuncInner::register_fn("roundi", sarray("x")); - - Func::FuncInner::register_fn("abs", sarray("x")); - Func::FuncInner::register_fn("absf", sarray("x")); - Func::FuncInner::register_fn("absi", sarray("x")); - - Func::FuncInner::register_fn("sign", sarray("x")); - Func::FuncInner::register_fn("signf", sarray("x")); - Func::FuncInner::register_fn("signi", sarray("x")); - - Func::FuncInner::register_fn("snapped", sarray("x", "step")); - Func::FuncInner::register_fn("snappedf", sarray("x", "step")); - Func::FuncInner::register_fn("snappedi", sarray("x", "step")); - - Func::FuncInner::register_fn("pow", sarray("base", "exp")); - Func::FuncInner::register_fn("log", sarray("x")); - Func::FuncInner::register_fn("exp", sarray("x")); - - Func::FuncInner::register_fn("is_nan", sarray("x")); - Func::FuncInner::register_fn("is_inf", sarray("x")); - - Func::FuncInner::register_fn("is_equal_approx", sarray("a", "b")); - Func::FuncInner::register_fn("is_zero_approx", sarray("x")); - Func::FuncInner::register_fn("is_finite", sarray("x")); - - Func::FuncInner::register_fn("ease", sarray("x", "curve")); - Func::FuncInner::register_fn("step_decimals", sarray("x")); - - Func::FuncInner::register_fn("lerp", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("lerpf", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("cubic_interpolate", sarray("from", "to", "pre", "post", "weight")); - Func::FuncInner::register_fn("cubic_interpolate_angle", sarray("from", "to", "pre", "post", "weight")); - Func::FuncInner::register_fn("cubic_interpolate_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); - Func::FuncInner::register_fn("cubic_interpolate_angle_in_time", sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t")); - Func::FuncInner::register_fn("bezier_interpolate", sarray("start", "control_1", "control_2", "end", "t")); - Func::FuncInner::register_fn("bezier_derivative", sarray("start", "control_1", "control_2", "end", "t")); - Func::FuncInner::register_fn("angle_difference", sarray("from", "to")); - Func::FuncInner::register_fn("lerp_angle", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("inverse_lerp", sarray("from", "to", "weight")); - Func::FuncInner::register_fn("remap", sarray("value", "istart", "istop", "ostart", "ostop")); - Func::FuncInner::register_fn("remap_default", sarray("value", "istart", "istop", "ostart", "ostop", "default_value")); - - Func::FuncInner::register_fn("smoothstep", sarray("from", "to", "x")); - Func::FuncInner::register_fn("move_toward", sarray("from", "to", "delta")); - Func::FuncInner::register_fn("rotate_toward", sarray("from", "to", "delta")); - - Func::FuncInner::register_fn("deg_to_rad", sarray("deg")); - Func::FuncInner::register_fn("rad_to_deg", sarray("rad")); - Func::FuncInner::register_fn("linear_to_db", sarray("lin")); - Func::FuncInner::register_fn("db_to_linear", sarray("db")); - - Func::FuncInner::register_fn("wrap", sarray("value", "min", "max")); - Func::FuncInner::register_fn("wrapi", sarray("value", "min", "max")); - Func::FuncInner::register_fn("wrapf", sarray("value", "min", "max")); - - Func::FuncInner::register_fn("max", sarray()); - Func::FuncInner::register_fn("maxi", sarray("a", "b")); - Func::FuncInner::register_fn("maxf", sarray("a", "b")); - - Func::FuncInner::register_fn("min", sarray()); - Func::FuncInner::register_fn("mini", sarray("a", "b")); - Func::FuncInner::register_fn("minf", sarray("a", "b")); - - Func::FuncInner::register_fn("clamp", sarray("value", "min", "max")); - Func::FuncInner::register_fn("clampi", sarray("value", "min", "max")); - Func::FuncInner::register_fn("clampf", sarray("value", "min", "max")); - - Func::FuncInner::register_fn("nearest_po2", sarray("value")); - Func::FuncInner::register_fn("pingpong", sarray("value", "length")); - - Func::FuncInner::register_fn("sigmoid", sarray("x")); - Func::FuncInner::register_fn("sigmoid_approx", sarray("x")); - Func::FuncInner::register_fn("sigmoid_affine", sarray("x", "amplitude", "y_translation")); - Func::FuncInner::register_fn("sigmoid_affine_approx", sarray("x", "amplitude", "y_translation")); + bind_fn_vuf(sin, Variant::UTILITY_FUNC_TYPE_MATH, "angle_rad"); + bind_fn_vuf(cos, Variant::UTILITY_FUNC_TYPE_MATH, "angle_rad"); + bind_fn_vuf(tan, Variant::UTILITY_FUNC_TYPE_MATH, "angle_rad"); + + bind_fn_vuf(sinh, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(cosh, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(tanh, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(asin, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(acos, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(atan, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(atan2, Variant::UTILITY_FUNC_TYPE_MATH, "y", "x"); + + bind_fn_vuf(asinh, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(acosh, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(atanh, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(sqrt, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(fmod, Variant::UTILITY_FUNC_TYPE_MATH, "x", "y"); + bind_fn_vuf(fposmod, Variant::UTILITY_FUNC_TYPE_MATH, "x", "y"); + bind_fn_vuf(posmod, Variant::UTILITY_FUNC_TYPE_MATH, "x", "y"); + + bind_fn_vuf(floor, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(floorf, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(floori, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(ceil, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(ceilf, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(ceili, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(round, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(roundf, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(roundi, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(abs, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(absf, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(absi, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(sign, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(signf, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(signi, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(snapped, Variant::UTILITY_FUNC_TYPE_MATH, "x", "step"); + bind_fn_vuf(snappedf, Variant::UTILITY_FUNC_TYPE_MATH, "x", "step"); + bind_fn_vuf(snappedi, Variant::UTILITY_FUNC_TYPE_MATH, "x", "step"); + + bind_fn_vuf(pow, Variant::UTILITY_FUNC_TYPE_MATH, "base", "exp"); + bind_fn_vuf(log, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(exp, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(is_nan, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(is_inf, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(is_equal_approx, Variant::UTILITY_FUNC_TYPE_MATH, "a", "b"); + bind_fn_vuf(is_zero_approx, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(is_finite, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(ease, Variant::UTILITY_FUNC_TYPE_MATH, "x", "curve"); + bind_fn_vuf(step_decimals, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + + bind_fn_vuf(lerp, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "weight"); + bind_fn_vuf(lerpf, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "weight"); + bind_fn_vuf(cubic_interpolate, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "pre", "post", "weight"); + bind_fn_vuf(cubic_interpolate_angle, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "pre", "post", "weight"); + bind_fn_vuf(cubic_interpolate_in_time, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"); + bind_fn_vuf(cubic_interpolate_angle_in_time, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"); + bind_fn_vuf(bezier_interpolate, Variant::UTILITY_FUNC_TYPE_MATH, "start", "control_1", "control_2", "end", "t"); + bind_fn_vuf(bezier_derivative, Variant::UTILITY_FUNC_TYPE_MATH, "start", "control_1", "control_2", "end", "t"); + bind_fn_vuf(angle_difference, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to"); + bind_fn_vuf(lerp_angle, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "weight"); + bind_fn_vuf(inverse_lerp, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "weight"); + bind_fn_vuf(remap, Variant::UTILITY_FUNC_TYPE_MATH, "value", "istart", "istop", "ostart", "ostop"); + bind_fn_vuf(remap_default, Variant::UTILITY_FUNC_TYPE_MATH, "value", "istart", "istop", "ostart", "ostop", "default_value"); + + bind_fn_vuf(smoothstep, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "x"); + bind_fn_vuf(move_toward, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "delta"); + bind_fn_vuf(rotate_toward, Variant::UTILITY_FUNC_TYPE_MATH, "from", "to", "delta"); + + bind_fn_vuf(deg_to_rad, Variant::UTILITY_FUNC_TYPE_MATH, "deg"); + bind_fn_vuf(rad_to_deg, Variant::UTILITY_FUNC_TYPE_MATH, "rad"); + bind_fn_vuf(linear_to_db, Variant::UTILITY_FUNC_TYPE_MATH, "lin"); + bind_fn_vuf(db_to_linear, Variant::UTILITY_FUNC_TYPE_MATH, "db"); + + bind_fn_vuf(wrap, Variant::UTILITY_FUNC_TYPE_MATH, "value", "min", "max"); + bind_fn_vuf(wrapi, Variant::UTILITY_FUNC_TYPE_MATH, "value", "min", "max"); + bind_fn_vuf(wrapf, Variant::UTILITY_FUNC_TYPE_MATH, "value", "min", "max"); + + bind_fn_vuf(max, Variant::UTILITY_FUNC_TYPE_MATH, ); + bind_fn_vuf(maxi, Variant::UTILITY_FUNC_TYPE_MATH, "a", "b"); + bind_fn_vuf(maxf, Variant::UTILITY_FUNC_TYPE_MATH, "a", "b"); + + bind_fn_vuf(min, Variant::UTILITY_FUNC_TYPE_MATH, ); + bind_fn_vuf(mini, Variant::UTILITY_FUNC_TYPE_MATH, "a", "b"); + bind_fn_vuf(minf, Variant::UTILITY_FUNC_TYPE_MATH, "a", "b"); + + bind_fn_vuf(clamp, Variant::UTILITY_FUNC_TYPE_MATH, "value", "min", "max"); + bind_fn_vuf(clampi, Variant::UTILITY_FUNC_TYPE_MATH, "value", "min", "max"); + bind_fn_vuf(clampf, Variant::UTILITY_FUNC_TYPE_MATH, "value", "min", "max"); + + bind_fn_vuf(nearest_po2, Variant::UTILITY_FUNC_TYPE_MATH, "value"); + bind_fn_vuf(pingpong, Variant::UTILITY_FUNC_TYPE_MATH, "value", "length"); + + bind_fn_vuf(sigmoid, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(sigmoid_approx, Variant::UTILITY_FUNC_TYPE_MATH, "x"); + bind_fn_vuf(sigmoid_affine, Variant::UTILITY_FUNC_TYPE_MATH, "x", "amplitude", "y_translation"); + bind_fn_vuf(sigmoid_affine_approx, Variant::UTILITY_FUNC_TYPE_MATH, "x", "amplitude", "y_translation"); // Random - Func::FuncInner::register_fn("randomize", sarray()); - Func::FuncInner::register_fn("randi", sarray()); - Func::FuncInner::register_fn("randf", sarray()); - Func::FuncInner::register_fn("randi_range", sarray("from", "to")); - Func::FuncInner::register_fn("randf_range", sarray("from", "to")); - Func::FuncInner::register_fn("randfn", sarray("mean", "deviation")); - Func::FuncInner::register_fn("seed", sarray("base")); - Func::FuncInner::register_fn("rand_from_seed", sarray("seed")); + bind_fn_vuf(randomize, Variant::UTILITY_FUNC_TYPE_RANDOM); + bind_fn_vuf(randi, Variant::UTILITY_FUNC_TYPE_RANDOM); + bind_fn_vuf(randf, Variant::UTILITY_FUNC_TYPE_RANDOM); + bind_fn_vuf(randi_range, Variant::UTILITY_FUNC_TYPE_RANDOM, "from", "to"); + bind_fn_vuf(randf_range, Variant::UTILITY_FUNC_TYPE_RANDOM, "from", "to"); + bind_fn_vuf(randfn, Variant::UTILITY_FUNC_TYPE_RANDOM, "mean", "deviation"); + bind_fn_vuf(seed, Variant::UTILITY_FUNC_TYPE_RANDOM, "base"); + bind_fn_vuf(rand_from_seed, Variant::UTILITY_FUNC_TYPE_RANDOM, "seed"); // Utility - Func::FuncInner::register_fn("weakref", sarray("obj")); - Func::FuncInner::register_fn("_typeof", sarray("variable")); - Func::FuncInner::register_fn("type_convert", sarray("variant", "type")); - Func::FuncInner::register_fn("str", sarray()); - Func::FuncInner::register_fn("error_string", sarray("error")); - Func::FuncInner::register_fn("type_string", sarray("type")); - Func::FuncInner::register_fn("print", sarray()); - Func::FuncInner::register_fn("print_rich", sarray()); - Func::FuncInner::register_fn("printerr", sarray()); - Func::FuncInner::register_fn("printt", sarray()); - Func::FuncInner::register_fn("prints", sarray()); - Func::FuncInner::register_fn("printraw", sarray()); - Func::FuncInner::register_fn("print_verbose", sarray()); - Func::FuncInner::register_fn("push_error", sarray()); - Func::FuncInner::register_fn("push_warning", sarray()); + bind_fn_vuf(weakref, Variant::UTILITY_FUNC_TYPE_GENERAL, "obj"); + bind_fn_vuf(_typeof, Variant::UTILITY_FUNC_TYPE_GENERAL, "variable"); + bind_fn_vuf(type_convert, Variant::UTILITY_FUNC_TYPE_GENERAL, "variant", "type"); + bind_fn_vuf(str, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(error_string, Variant::UTILITY_FUNC_TYPE_GENERAL, "error"); + bind_fn_vuf(type_string, Variant::UTILITY_FUNC_TYPE_GENERAL, "type"); + bind_fn_vuf(print, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(print_rich, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(printerr, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(printt, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(prints, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(printraw, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn(VariantUtilityFunctions::_print_verbose, Variant::UTILITY_FUNC_TYPE_GENERAL, "print_verbose"); + bind_fn_vuf(push_error, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(push_warning, Variant::UTILITY_FUNC_TYPE_GENERAL); - Func::FuncInner::register_fn("var_to_str", sarray("variable")); - Func::FuncInner::register_fn("str_to_var", sarray("string")); + bind_fn_vuf(var_to_str, Variant::UTILITY_FUNC_TYPE_GENERAL, "variable"); + bind_fn_vuf(str_to_var, Variant::UTILITY_FUNC_TYPE_GENERAL, "string"); - Func::FuncInner::register_fn("var_to_str_with_objects", sarray("variable")); - Func::FuncInner::register_fn("str_to_var_with_objects", sarray("string")); + bind_fn_vuf(var_to_str_with_objects, Variant::UTILITY_FUNC_TYPE_GENERAL, "variable"); + bind_fn_vuf(str_to_var_with_objects, Variant::UTILITY_FUNC_TYPE_GENERAL, "string"); - Func::FuncInner::register_fn("var_to_bytes", sarray("variable")); - Func::FuncInner::register_fn("bytes_to_var", sarray("bytes")); + bind_fn_vuf(var_to_bytes, Variant::UTILITY_FUNC_TYPE_GENERAL, "variable"); + bind_fn_vuf(bytes_to_var, Variant::UTILITY_FUNC_TYPE_GENERAL, "bytes"); - Func::FuncInner::register_fn("var_to_bytes_with_objects", sarray("variable")); - Func::FuncInner::register_fn("bytes_to_var_with_objects", sarray("bytes")); + bind_fn_vuf(var_to_bytes_with_objects, Variant::UTILITY_FUNC_TYPE_GENERAL, "variable"); + bind_fn_vuf(bytes_to_var_with_objects, Variant::UTILITY_FUNC_TYPE_GENERAL, "bytes"); - Func::FuncInner::register_fn("hash", sarray("variable")); + bind_fn_vuf(hash, Variant::UTILITY_FUNC_TYPE_GENERAL, "variable"); - Func::FuncInner::register_fn("instance_from_id", sarray("instance_id")); - Func::FuncInner::register_fn("is_instance_id_valid", sarray("id")); - Func::FuncInner::register_fn("is_instance_valid", sarray("instance")); + bind_fn_vuf(instance_from_id, Variant::UTILITY_FUNC_TYPE_GENERAL, "instance_id"); + bind_fn_vuf(is_instance_id_valid, Variant::UTILITY_FUNC_TYPE_GENERAL, "id"); + bind_fn_vuf(is_instance_valid, Variant::UTILITY_FUNC_TYPE_GENERAL, "instance"); - Func::FuncInner::register_fn("rid_allocate_id", Vector()); - Func::FuncInner::register_fn("rid_from_int64", sarray("base")); + bind_fn_vuf(rid_allocate_id, Variant::UTILITY_FUNC_TYPE_GENERAL); + bind_fn_vuf(rid_from_int64, Variant::UTILITY_FUNC_TYPE_GENERAL, "base"); - Func::FuncInner::register_fn("is_same", sarray("a", "b")); + bind_fn_vuf(is_same, Variant::UTILITY_FUNC_TYPE_GENERAL, "a", "b"); } void Variant::_unregister_variant_utility_functions() { From bec39dacd0fc31a492a1ff6173a13e5cbd37710a Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Sat, 14 Mar 2026 12:37:20 -0400 Subject: [PATCH 07/12] Remove failed experiment --- core/variant/method_ptrcall.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h index 113f8f5768b..4caa7bbf367 100644 --- a/core/variant/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -241,8 +241,6 @@ template <> struct PtrToArg : Internal::PtrToArgDirect {}; template <> struct PtrToArg : Internal::PtrToArgByReference {}; -// template <> -// struct PtrToArg : Internal::PtrToArgConvert {}; template struct PtrToArg>> : Internal::PtrToArgConvert {}; From a7cb3d9e0aca4f0ef731d07842eaf53e1284f929 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Sat, 14 Mar 2026 20:44:59 -0400 Subject: [PATCH 08/12] Deduplicate a little bit more --- core/variant/type_info.h | 2 + core/variant/variant_utility.cpp | 332 +++++++++++++++---------------- 2 files changed, 163 insertions(+), 171 deletions(-) diff --git a/core/variant/type_info.h b/core/variant/type_info.h index e70cd8f9e93..51e05e3405a 100644 --- a/core/variant/type_info.h +++ b/core/variant/type_info.h @@ -32,8 +32,10 @@ #pragma once +#include "core/object/object.h" #include "core/templates/simple_type.h" #include "core/typedefs.h" +#include "core/variant/variant.h" #include diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 8ded362c8e7..2a8a7901ed7 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -32,6 +32,7 @@ #include "variant_utility.h" +#include "binder_common.h" #include "core/io/marshalls.h" #include "core/math/math_funcs.h" #include "core/object/ref_counted.h" @@ -1213,163 +1214,189 @@ String VariantUtilityFunctions::join_string(const Variant **p_args, int p_arg_co } #ifdef DEBUG_ENABLED -#define VCALLR *ret = p_func(VariantCasterAndValidate

::cast(p_args, Is, r_error)...) -#define VCALL p_func(VariantCasterAndValidate

::cast(p_args, Is, r_error)...) +#define VCALLR(TArgs, ret, p_args, Is, r_error) *ret = p_func(VariantCasterAndValidate::cast(p_args, Is, r_error)...) +#define VCALLER(TArgs, ret, p_args, Is, r_error) *ret = p_func(r_error, VariantCasterAndValidate::cast(p_args, Is, r_error)...) +#define VCALL(TArgs, ret, p_args, Is, r_error) p_func(VariantCasterAndValidate::cast(p_args, Is, r_error)...) +#define VCALLE(TArgs, ret, p_args, Is, r_error) p_func(r_error, VariantCasterAndValidate::cast(p_args, Is, r_error)...) #else -#define VCALLR *ret = p_func(VariantCaster

::cast(*p_args[Is])...) -#define VCALL p_func(VariantCaster

::cast(*p_args[Is])...) +#define VCALLR(TArgs, ret, p_args, Is, r_error) *ret = p_func(VariantCaster::cast(*p_args[Is])...) +#define VCALLER(TArgs, ret, p_args, Is, r_error) *ret = p_func(r_error, VariantCaster::cast(*p_args[Is])...) +#define VCALL(TArgs, ret, p_args, Is, r_error) p_func(VariantCaster::cast(*p_args[Is])...) +#define VCALLE(TArgs, ret, p_args, Is, r_error) p_func(r_error, VariantCaster::cast(*p_args[Is])...) #endif // DEBUG_ENABLED -template -static _FORCE_INLINE_ void call_helperpr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { - *ret = p_func(r_error, VariantCasterAndValidate

::cast(p_args, Is, r_error)...); - (void)p_args; // avoid gcc warning -} +template +struct HelperBase { + static _FORCE_INLINE_ Variant::Type get_arg_type(int p_arg) { + return call_get_argument_type(p_arg); + } + static _FORCE_INLINE_ int arg_count() { + return sizeof...(TArgs); + } +}; -template -static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { - r_error.error = Callable::CallError::CALL_OK; - VCALLR; - (void)p_args; // avoid gcc warning - (void)r_error; -} +template +struct Helper; -template -static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, IndexSequence) { - *ret = p_func(VariantCaster

::cast(*p_args[Is])...); - (void)p_args; -} +template +struct Helper : HelperBase { + static _FORCE_INLINE_ void call(TRet (*p_func)(TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { + call_helper(p_func, ret, p_args, r_error, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args, IndexSequence) { - Callable::CallError err; - *ret = p_func(err, VariantCaster

::cast(*p_args[Is])...); - (void)p_args; -} + static _FORCE_INLINE_ void ptr_call(TRet (*p_func)(TArgs...), void *ret, const void **p_args) { + ptr_call_helper(p_func, ret, p_args, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(P...), void *ret, const void **p_args, IndexSequence) { - PtrToArg::encode(p_func(PtrToArg

::convert(p_args[Is])...), ret); - (void)p_args; -} + static _FORCE_INLINE_ void validated_call(TRet (*p_func)(TArgs...), Variant *ret, const Variant **p_args) { + validated_call_helper(p_func, ret, p_args, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(Callable::CallError &, P...), void *ret, const void **p_args, IndexSequence) { - Callable::CallError err; - PtrToArg::encode(p_func(err, PtrToArg

::convert(p_args[Is])...), ret); - (void)p_args; -} +private: + template + static _FORCE_INLINE_ void call_helper(TRet (*p_func)(TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + VCALLR(TArgs, ret, p_args, Is, r_error); + (void)p_args; // avoid gcc warning + (void)r_error; + } -template -static _FORCE_INLINE_ void call_helperr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { - call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence{}); -} + template + static _FORCE_INLINE_ void ptr_call_helper(TRet (*p_func)(TArgs...), void *ret, const void **p_args, IndexSequence) { + PtrToArg::encode(p_func(PtrToArg::convert(p_args[Is])...), ret); + (void)p_args; + } -template -static _FORCE_INLINE_ void call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { - call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence{}); -} + template + static _FORCE_INLINE_ void validated_call_helper(TRet (*p_func)(TArgs...), Variant *ret, const Variant **p_args, IndexSequence) { + *ret = p_func(VariantCaster::cast(*p_args[Is])...); + (void)p_args; + } +}; -template -static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args) { - validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); -} +template +struct Helper : HelperBase { + static _FORCE_INLINE_ void call(TRet (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { + call_helper(p_func, ret, p_args, r_error, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(Callable::CallError &, P...), Variant *ret, const Variant **p_args) { - validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); -} + static _FORCE_INLINE_ void ptr_call(TRet (*p_func)(Callable::CallError &, TArgs...), void *ret, const void **p_args) { + ptr_call_helper(p_func, ret, p_args, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(P...), void *ret, const void **p_args) { - ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); -} + static _FORCE_INLINE_ void validated_call(TRet (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args) { + validated_call_helper(p_func, ret, p_args, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(Callable::CallError &, P...), void *ret, const void **p_args) { - ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence{}); -} +private: + template + static _FORCE_INLINE_ void call_helper(TRet (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + VCALLER(TArgs, ret, p_args, Is, r_error); + (void)p_args; // avoid gcc warning + (void)r_error; + } -template -static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(P...)) { - return sizeof...(P); -} + template + static _FORCE_INLINE_ void ptr_call_helper(TRet (*p_func)(Callable::CallError &, TArgs...), void *ret, const void **p_args, IndexSequence) { + Callable::CallError ce; + PtrToArg::encode(p_func(ce, PtrToArg::convert(p_args[Is])...), ret); + (void)p_args; + } -template -static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(Callable::CallError &, P...)) { - return sizeof...(P); -} + template + static _FORCE_INLINE_ void validated_call_helper(TRet (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args, IndexSequence) { + Callable::CallError err; + *ret = p_func(err, VariantCaster::cast(*p_args[Is])...); + (void)p_args; + } +}; -template -static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int p_arg) { - return call_get_argument_type(p_arg); -} +template +struct Helper : HelperBase { + static _FORCE_INLINE_ void call(void (*p_func)(TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { + call_helper(p_func, ret, p_args, r_error, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(Callable::CallError &, P...), int p_arg) { - return call_get_argument_type(p_arg); -} + static _FORCE_INLINE_ void ptr_call( + void (*p_func)(TArgs...), + void *ret, + const void **p_args) { + ptr_call_helper(p_func, p_args, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) { - return GetTypeInfo::VARIANT_TYPE; -} + static _FORCE_INLINE_ void validated_call(void (*p_func)(TArgs...), Variant *ret, const Variant **p_args) { + validated_call_helper(p_func, ret, p_args, BuildIndexSequence{}); + } -// WITHOUT RET +private: + template + static _FORCE_INLINE_ void call_helper(void (*p_func)(TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + VCALL(TArgs, ret, p_args, Is, r_error); + (void)p_args; // avoid gcc warning + (void)r_error; + } -template -static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence) { - r_error.error = Callable::CallError::CALL_OK; - VCALL; - (void)p_args; - (void)r_error; -} + template + static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(TArgs...), const void **p_args, IndexSequence) { + p_func(PtrToArg::convert(p_args[Is])...); + (void)p_args; + } -template -static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence) { - p_func(VariantCaster

::cast(*p_args[Is])...); - (void)p_args; -} + template + static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(TArgs...), Variant *ret, const Variant **p_args, IndexSequence) { + p_func(VariantCaster::cast(*p_args[Is])...); + (void)p_args; + } +}; -template -static _FORCE_INLINE_ void ptr_call_helperp(void (*p_func)(P...), const void **p_args, IndexSequence) { - p_func(PtrToArg

::convert(p_args[Is])...); - (void)p_args; -} +template +struct Helper : HelperBase { + static _FORCE_INLINE_ void call(void (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { + call_helper(p_func, ret, p_args, r_error, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void call_helper(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error) { - call_helperp(p_func, p_args, r_error, BuildIndexSequence{}); -} + static _FORCE_INLINE_ void ptr_call(void (*p_func)(Callable::CallError &, TArgs...), void *ret, const void **p_args) { + ptr_call_helper(p_func, p_args, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(P...), const Variant **p_args) { - validated_call_helperp(p_func, p_args, BuildIndexSequence{}); -} + static _FORCE_INLINE_ void validated_call(void (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args) { + validated_call_helper(p_func, ret, p_args, BuildIndexSequence{}); + } -template -static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(P...), const void **p_args) { - ptr_call_helperp(p_func, p_args, BuildIndexSequence{}); -} +private: + template + static _FORCE_INLINE_ void call_helper(void (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence) { + r_error.error = Callable::CallError::CALL_OK; + VCALLE(TArgs, ret, p_args, Is, r_error); + (void)p_args; // avoid gcc warning + (void)r_error; + } -template -static _FORCE_INLINE_ int get_arg_count_helper(void (*p_func)(P...)) { - return sizeof...(P); -} + template + static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(Callable::CallError &, TArgs...), const void **p_args, IndexSequence) { + Callable::CallError ce; + p_func(ce, PtrToArg::convert(p_args[Is])...); + (void)p_args; + } -template -static _FORCE_INLINE_ Variant::Type get_arg_type_helper(void (*p_func)(P...), int p_arg) { - return call_get_argument_type(p_arg); -} + template + static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args, IndexSequence) { + Callable::CallError err; + *ret = p_func(err, VariantCaster::cast(*p_args[Is])...); + (void)p_args; + } +}; -template -static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) { - return Variant::NIL; +template +_FORCE_INLINE_ Variant::Type get_ret_type_helper() { + return GetTypeInfo::VARIANT_TYPE; } -template -static _FORCE_INLINE_ Variant::Type get_ret_type_helper(Variant (*p_func)(P...)) { - return Variant::NIL; +template <> +_FORCE_INLINE_ Variant::Type get_ret_type_helper() { + return Variant::Type::NIL; } struct VariantUtilityFunctionInfo { @@ -1419,43 +1446,6 @@ static void register_utility_function(const String &p_name, const Vector template struct Func; -template -struct Func { - template - struct FuncInner { - static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - call_helper(m_func, p_args, r_error); - } - static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { - validated_call_helper(m_func, p_args); - } - static void ptrcall(void *ret, const void **p_args, int p_argcount) { - ptr_call_helper(m_func, p_args); - } - static int get_argument_count() { - return get_arg_count_helper(m_func); - } - static Variant::Type get_argument_type(int p_arg) { - return get_arg_type_helper(m_func, p_arg); - } - static Variant::Type get_return_type() { - return get_ret_type_helper(m_func); - } - static bool has_return_type() { - return false; - } - static bool is_vararg() { - return false; - } - static Variant::UtilityFunctionType get_type() { - return m_category; - } - static void register_fn(const String &name, const Vector &args) { - register_utility_function>(name, args); - } - }; -}; - template <> struct Func { template @@ -1587,7 +1577,7 @@ struct Func { return Variant::NIL; } static bool has_return_type() { - return true; + return !std::is_same::value; } static bool is_vararg() { return true; @@ -1606,25 +1596,25 @@ struct Func { template struct FuncInner { static void call(Variant *ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - call_helperr(m_func, ret, p_args, r_error); + Helper::call(m_func, ret, p_args, r_error); } static void validated_call(Variant *ret, const Variant **p_args, int p_argcount) { - validated_call_helperr(m_func, ret, p_args); + Helper::validated_call(m_func, ret, p_args); } static void ptrcall(void *ret, const void **p_args, int p_argcount) { - ptr_call_helperr(m_func, ret, p_args); + Helper::ptr_call(m_func, ret, p_args); } static int get_argument_count() { - return get_arg_count_helperr(m_func); + return Helper::arg_count(); } static Variant::Type get_argument_type(int p_arg) { - return get_arg_type_helperr(m_func, p_arg); + return Helper::get_arg_type(p_arg); } static Variant::Type get_return_type() { - return get_ret_type_helperr(m_func); + return get_ret_type_helper(); } static bool has_return_type() { - return true; + return !std::is_same::value; } static bool is_vararg() { return false; From ac7093eef97bc1ad07189a6a1c9750b26a00761a Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Sat, 14 Mar 2026 21:18:45 -0400 Subject: [PATCH 09/12] Pull more common implementaitons out from FuncInner --- core/variant/variant_utility.cpp | 80 +++++++++++--------------------- 1 file changed, 28 insertions(+), 52 deletions(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 2a8a7901ed7..5743d92bc5c 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1399,6 +1399,11 @@ _FORCE_INLINE_ Variant::Type get_ret_type_helper() { return Variant::Type::NIL; } +template <> +_FORCE_INLINE_ Variant::Type get_ret_type_helper() { + return Variant::Type::NIL; +} + struct VariantUtilityFunctionInfo { void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = nullptr; Variant::ValidatedUtilityFunction validated_call_utility = nullptr; @@ -1443,13 +1448,32 @@ static void register_utility_function(const String &p_name, const Vector utility_function_name_table.push_back(sname); } +template +struct FuncBase { + template typename TFuncInner> + struct FuncInnerBase { + static Variant::UtilityFunctionType get_type() { + return m_category; + } + static void register_fn(const String &name, const Vector &args) { + register_utility_function>(name, args); + } + static bool has_return_type() { + return !std::is_same::value; + } + static Variant::Type get_return_type() { + return get_ret_type_helper(); + } + }; +}; + template struct Func; template <> struct Func { template - struct FuncInner { + struct FuncInner : FuncBase::template FuncInnerBase { static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; m_func(r_error, p_args, p_argcount); @@ -1476,28 +1500,16 @@ struct Func { static Variant::Type get_argument_type(int p_arg) { return Variant::NIL; } - static Variant::Type get_return_type() { - return Variant::NIL; - } - static bool has_return_type() { - return false; - } static bool is_vararg() { return true; } - static Variant::UtilityFunctionType get_type() { - return m_category; - } - static void register_fn(const String &name, const Vector &args) { - register_utility_function>(name, args); - } }; }; template <> struct Func { template - struct FuncInner { + struct FuncInner : FuncBase::template FuncInnerBase { static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; *r_ret = m_func(r_error, p_args, p_argcount); @@ -1525,28 +1537,16 @@ struct Func { static Variant::Type get_argument_type(int p_arg) { return Variant::NIL; } - static Variant::Type get_return_type() { - return Variant::STRING; - } - static bool has_return_type() { - return true; - } static bool is_vararg() { return true; } - static Variant::UtilityFunctionType get_type() { - return m_category; - } - static void register_fn(const String &name, const Vector &args) { - register_utility_function>(name, args); - } }; }; template struct Func { template - struct FuncInner { + struct FuncInner : FuncBase::template FuncInnerBase { static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; *r_ret = m_func(r_error, p_args, p_argcount); @@ -1573,28 +1573,16 @@ struct Func { static Variant::Type get_argument_type(int p_arg) { return Variant::NIL; } - static Variant::Type get_return_type() { - return Variant::NIL; - } - static bool has_return_type() { - return !std::is_same::value; - } static bool is_vararg() { return true; } - static Variant::UtilityFunctionType get_type() { - return m_category; - } - static void register_fn(const String &name, const Vector &args) { - register_utility_function>(name, args); - } }; }; template struct Func { template - struct FuncInner { + struct FuncInner : FuncBase::template FuncInnerBase { static void call(Variant *ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { Helper::call(m_func, ret, p_args, r_error); } @@ -1610,21 +1598,9 @@ struct Func { static Variant::Type get_argument_type(int p_arg) { return Helper::get_arg_type(p_arg); } - static Variant::Type get_return_type() { - return get_ret_type_helper(); - } - static bool has_return_type() { - return !std::is_same::value; - } static bool is_vararg() { return false; } - static Variant::UtilityFunctionType get_type() { - return m_category; - } - static void register_fn(const String &name, const Vector &args) { - register_utility_function>(name, args); - } }; }; From 14ec5de5424f7ac5570ab9291ed8f04aafa02b38 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Sat, 14 Mar 2026 21:43:19 -0400 Subject: [PATCH 10/12] Yeet template template --- core/variant/variant_utility.cpp | 39 +++++++++++++++----------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 5743d92bc5c..84227154d59 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1448,23 +1448,20 @@ static void register_utility_function(const String &p_name, const Vector utility_function_name_table.push_back(sname); } -template -struct FuncBase { - template typename TFuncInner> - struct FuncInnerBase { - static Variant::UtilityFunctionType get_type() { - return m_category; - } - static void register_fn(const String &name, const Vector &args) { - register_utility_function>(name, args); - } - static bool has_return_type() { - return !std::is_same::value; - } - static Variant::Type get_return_type() { - return get_ret_type_helper(); - } - }; +template +struct FuncInnerBase { + static Variant::UtilityFunctionType get_type() { + return m_category; + } + static void register_fn(const String &name, const Vector &args) { + register_utility_function(name, args); + } + static bool has_return_type() { + return !std::is_same::value; + } + static Variant::Type get_return_type() { + return get_ret_type_helper(); + } }; template @@ -1473,7 +1470,7 @@ struct Func; template <> struct Func { template - struct FuncInner : FuncBase::template FuncInnerBase { + struct FuncInner : FuncInnerBase> { static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; m_func(r_error, p_args, p_argcount); @@ -1509,7 +1506,7 @@ struct Func { template <> struct Func { template - struct FuncInner : FuncBase::template FuncInnerBase { + struct FuncInner : FuncInnerBase> { static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; *r_ret = m_func(r_error, p_args, p_argcount); @@ -1546,7 +1543,7 @@ struct Func { template struct Func { template - struct FuncInner : FuncBase::template FuncInnerBase { + struct FuncInner : FuncInnerBase> { static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; *r_ret = m_func(r_error, p_args, p_argcount); @@ -1582,7 +1579,7 @@ struct Func { template struct Func { template - struct FuncInner : FuncBase::template FuncInnerBase { + struct FuncInner : FuncInnerBase> { static void call(Variant *ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { Helper::call(m_func, ret, p_args, r_error); } From 9a1e8d35d0043788e03178c2ac86877bd890819c Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Mon, 16 Mar 2026 20:09:39 -0400 Subject: [PATCH 11/12] Fix broken reference doc. This isn't an actual change, CI is just being dumb. --- doc/classes/@GlobalScope.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index b0bcd70396f..cceff1a5852 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -619,7 +619,7 @@ - + Linearly interpolates between two values by the factor defined in [param weight]. To perform interpolation, [param weight] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i]. If this is not desired, use [method clampf] to limit [param weight]. Both [param from] and [param to] must be the same type. Supported types: [int], [float], [Vector2], [Vector3], [Vector4], [Color], [Quaternion], [Basis], [Transform2D], [Transform3D]. From 0ae2a5228a7f9d66cce57123733a72e35f350912 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Tue, 17 Mar 2026 22:58:19 -0400 Subject: [PATCH 12/12] Fixing an unused template. Thanks C++ template-isms. This likely would've been fixed if and when this case was realized, however, it was incorrect by construction and probably should be handled now. --- core/variant/variant_utility.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 84227154d59..b4f3d1f608e 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1384,8 +1384,9 @@ struct Helper : HelperBase static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(Callable::CallError &, TArgs...), Variant *ret, const Variant **p_args, IndexSequence) { Callable::CallError err; - *ret = p_func(err, VariantCaster::cast(*p_args[Is])...); + p_func(err, VariantCaster::cast(*p_args[Is])...); (void)p_args; + (void)ret; } };