Add support for default arguments in utility functions
Co-authored-by: Leo Belda <leo.belda@wanadoo.fr>
This commit is contained in:
parent
3978628c6c
commit
bf4ff9b792
|
@ -580,14 +580,20 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
|
|||
bool vararg = Variant::is_utility_function_vararg(name);
|
||||
func["is_vararg"] = Variant::is_utility_function_vararg(name);
|
||||
func["hash"] = Variant::get_utility_function_hash(name);
|
||||
|
||||
Array arguments;
|
||||
const Vector<Variant> def_args = Variant::get_utility_function_default_arguments(name);
|
||||
int argcount = Variant::get_utility_function_argument_count(name);
|
||||
for (int i = 0; i < argcount; i++) {
|
||||
Dictionary arg;
|
||||
String argname = vararg ? "arg" + itos(i + 1) : Variant::get_utility_function_argument_name(name, i);
|
||||
arg["name"] = argname;
|
||||
arg["type"] = get_builtin_or_variant_type_name(Variant::get_utility_function_argument_type(name, i));
|
||||
//no default value support in utility functions
|
||||
|
||||
const int dargidx = Variant::get_utility_function_default_argument_index(name, i);
|
||||
if (dargidx >= 0) {
|
||||
arg["default_value"] = def_args[dargidx].get_construct_string();
|
||||
}
|
||||
arguments.push_back(arg);
|
||||
}
|
||||
|
||||
|
|
|
@ -551,7 +551,7 @@ public:
|
|||
static uint32_t rand();
|
||||
static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_32BIT_MAX; }
|
||||
static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_32BIT_MAX; }
|
||||
static double randfn(double mean, double deviation);
|
||||
static double randfn(double mean = 0.0, double deviation = 1.0);
|
||||
|
||||
static double random(double from, double to);
|
||||
static float random(float from, float to);
|
||||
|
|
|
@ -752,6 +752,8 @@ public:
|
|||
static int get_utility_function_argument_count(const StringName &p_name);
|
||||
static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg);
|
||||
static String get_utility_function_argument_name(const StringName &p_name, int p_arg);
|
||||
static Vector<Variant> get_utility_function_default_arguments(const StringName &p_name);
|
||||
static int get_utility_function_default_argument_index(const StringName &p_name, int p_arg);
|
||||
static bool has_utility_function_return_value(const StringName &p_name);
|
||||
static Variant::Type get_utility_function_return_type(const StringName &p_name);
|
||||
static bool is_utility_function_vararg(const StringName &p_name);
|
||||
|
|
|
@ -1228,47 +1228,19 @@ bool VariantUtilityFunctions::is_same(const Variant &p_a, const Variant &p_b) {
|
|||
return p_a.identity_compare(p_b);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
#define VCALLR *ret = p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...)
|
||||
#define VCALL p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...)
|
||||
#else
|
||||
#define VCALLR *ret = p_func(VariantCaster<P>::cast(*p_args[Is])...)
|
||||
#define VCALL p_func(VariantCaster<P>::cast(*p_args[Is])...)
|
||||
#endif
|
||||
|
||||
template <typename R, typename... P, size_t... Is>
|
||||
static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = Callable::CallError::CALL_OK;
|
||||
VCALLR;
|
||||
(void)p_args; // avoid gcc warning
|
||||
(void)r_error;
|
||||
}
|
||||
|
||||
template <typename R, typename... P, size_t... Is>
|
||||
static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, IndexSequence<Is...>) {
|
||||
*ret = p_func(VariantCaster<P>::cast(*p_args[Is])...);
|
||||
(void)p_args;
|
||||
}
|
||||
|
||||
template <typename R, typename... P, size_t... Is>
|
||||
static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(P...), void *ret, const void **p_args, IndexSequence<Is...>) {
|
||||
PtrToArg<R>::encode(p_func(PtrToArg<P>::convert(p_args[Is])...), ret);
|
||||
(void)p_args;
|
||||
}
|
||||
|
||||
template <typename R, typename... P>
|
||||
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<sizeof...(P)>{});
|
||||
static _FORCE_INLINE_ void call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
|
||||
call_with_variant_args_static_ret_dv(p_func, p_args, p_argcount, *ret, r_error, p_defvals);
|
||||
}
|
||||
|
||||
template <typename R, typename... P>
|
||||
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<sizeof...(P)>{});
|
||||
call_with_validated_variant_args_static_method_ret(p_func, p_args, ret);
|
||||
}
|
||||
|
||||
template <typename R, typename... P>
|
||||
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<sizeof...(P)>{});
|
||||
call_with_ptr_args_static_method_ret<R, P...>(p_func, p_args, ret);
|
||||
}
|
||||
|
||||
template <typename R, typename... P>
|
||||
|
@ -1288,20 +1260,6 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) {
|
|||
|
||||
// WITHOUT RET
|
||||
|
||||
template <typename... P, size_t... Is>
|
||||
static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = Callable::CallError::CALL_OK;
|
||||
VCALL;
|
||||
(void)p_args;
|
||||
(void)r_error;
|
||||
}
|
||||
|
||||
template <typename... P, size_t... Is>
|
||||
static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence<Is...>) {
|
||||
p_func(VariantCaster<P>::cast(*p_args[Is])...);
|
||||
(void)p_args;
|
||||
}
|
||||
|
||||
template <typename... P, size_t... Is>
|
||||
static _FORCE_INLINE_ void ptr_call_helperp(void (*p_func)(P...), const void **p_args, IndexSequence<Is...>) {
|
||||
p_func(PtrToArg<P>::convert(p_args[Is])...);
|
||||
|
@ -1309,18 +1267,18 @@ static _FORCE_INLINE_ void ptr_call_helperp(void (*p_func)(P...), const void **p
|
|||
}
|
||||
|
||||
template <typename... P>
|
||||
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<sizeof...(P)>{});
|
||||
static _FORCE_INLINE_ void call_helper(void (*p_func)(P...), const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
|
||||
call_with_variant_args_static_dv(p_func, p_args, p_argcount, r_error, p_defvals);
|
||||
}
|
||||
|
||||
template <typename... P>
|
||||
static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(P...), const Variant **p_args) {
|
||||
validated_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
|
||||
call_with_validated_variant_args_static_method(p_func, p_args);
|
||||
}
|
||||
|
||||
template <typename... P>
|
||||
static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(P...), const void **p_args) {
|
||||
ptr_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
|
||||
call_with_ptr_args_static_method<P...>(p_func, p_args);
|
||||
}
|
||||
|
||||
template <typename... P>
|
||||
|
@ -1341,8 +1299,8 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
#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 call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args, p_argcount, varray(), 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); \
|
||||
|
@ -1365,12 +1323,41 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
static bool is_vararg() { return false; } \
|
||||
static Variant::UtilityFunctionType get_type() { return m_category; } \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
#define FUNCBINDRD(m_func, m_args, m_defvals, m_category) \
|
||||
class Func_##m_func { \
|
||||
public: \
|
||||
static void call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args, p_argcount, p_defvals, 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<Func_##m_func>(#m_func, m_args, m_defvals)
|
||||
|
||||
#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) { \
|
||||
static void call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
r_error.error = Callable::CallError::CALL_OK; \
|
||||
*r_ret = VariantUtilityFunctions::m_func(*p_args[0], r_error); \
|
||||
} \
|
||||
|
@ -1397,12 +1384,12 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
static bool is_vararg() { return false; } \
|
||||
static Variant::UtilityFunctionType get_type() { return m_category; } \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
#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) { \
|
||||
static void call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
r_error.error = Callable::CallError::CALL_OK; \
|
||||
*r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], r_error); \
|
||||
} \
|
||||
|
@ -1431,12 +1418,12 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
static bool is_vararg() { return false; } \
|
||||
static Variant::UtilityFunctionType get_type() { return m_category; } \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
#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) { \
|
||||
static void call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, 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); \
|
||||
} \
|
||||
|
@ -1465,12 +1452,12 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
static bool is_vararg() { return false; } \
|
||||
static Variant::UtilityFunctionType get_type() { return m_category; } \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
#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) { \
|
||||
static void call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
r_error.error = Callable::CallError::CALL_OK; \
|
||||
*r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \
|
||||
} \
|
||||
|
@ -1510,12 +1497,12 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
return m_category; \
|
||||
} \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
#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) { \
|
||||
static void call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
r_error.error = Callable::CallError::CALL_OK; \
|
||||
*r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \
|
||||
} \
|
||||
|
@ -1555,12 +1542,12 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
return m_category; \
|
||||
} \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
#define FUNCBINDVARARGV(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) { \
|
||||
static void call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
r_error.error = Callable::CallError::CALL_OK; \
|
||||
VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \
|
||||
} \
|
||||
|
@ -1599,13 +1586,13 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
return m_category; \
|
||||
} \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
#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 call(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
|
||||
call_helper(VariantUtilityFunctions::m_func, p_args, p_argcount, varray(), r_error); \
|
||||
} \
|
||||
static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
|
||||
validated_call_helper(VariantUtilityFunctions::m_func, p_args); \
|
||||
|
@ -1628,12 +1615,13 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
|
|||
static bool is_vararg() { return false; } \
|
||||
static Variant::UtilityFunctionType get_type() { return m_category; } \
|
||||
}; \
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args)
|
||||
register_utility_function<Func_##m_func>(#m_func, m_args, varray())
|
||||
|
||||
struct VariantUtilityFunctionInfo {
|
||||
void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = nullptr;
|
||||
void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, const Vector<Variant> &p_defvals, Callable::CallError &r_error) = nullptr;
|
||||
Variant::ValidatedUtilityFunction validated_call_utility = nullptr;
|
||||
Variant::PTRUtilityFunction ptr_call_utility = nullptr;
|
||||
Vector<Variant> default_arguments;
|
||||
Vector<String> argnames;
|
||||
bool is_vararg = false;
|
||||
bool returns_value = false;
|
||||
|
@ -1647,7 +1635,7 @@ static OAHashMap<StringName, VariantUtilityFunctionInfo> utility_function_table;
|
|||
static List<StringName> utility_function_name_table;
|
||||
|
||||
template <typename T>
|
||||
static void register_utility_function(const String &p_name, const Vector<String> &argnames) {
|
||||
static void register_utility_function(const String &p_name, const Vector<String> &argnames, const Vector<Variant> &p_def_args) {
|
||||
String name = p_name;
|
||||
if (name.begins_with("_")) {
|
||||
name = name.substr(1, name.length() - 1);
|
||||
|
@ -1660,6 +1648,7 @@ static void register_utility_function(const String &p_name, const Vector<String>
|
|||
bfi.validated_call_utility = T::validated_call;
|
||||
bfi.ptr_call_utility = T::ptrcall;
|
||||
bfi.is_vararg = T::is_vararg();
|
||||
bfi.default_arguments = p_def_args;
|
||||
bfi.argnames = argnames;
|
||||
bfi.argcount = T::get_argument_count();
|
||||
if (!bfi.is_vararg) {
|
||||
|
@ -1786,7 +1775,7 @@ void Variant::_register_variant_utility_functions() {
|
|||
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);
|
||||
FUNCBINDRD(randfn, sarray("mean", "deviation"), varray(0.0, 1.0), 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);
|
||||
|
||||
|
@ -1843,9 +1832,9 @@ void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, co
|
|||
return;
|
||||
}
|
||||
|
||||
if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount)) {
|
||||
if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount - bfi->default_arguments.size())) {
|
||||
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.expected = bfi->argcount;
|
||||
r_error.expected = bfi->argcount - bfi->default_arguments.size();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1855,7 +1844,7 @@ void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, co
|
|||
return;
|
||||
}
|
||||
|
||||
bfi->call_utility(r_ret, p_args, p_argcount, r_error);
|
||||
bfi->call_utility(r_ret, p_args, p_argcount, bfi->default_arguments, r_error);
|
||||
}
|
||||
|
||||
bool Variant::has_utility_function(const StringName &p_name) {
|
||||
|
@ -1907,6 +1896,7 @@ MethodInfo Variant::get_utility_function_info(const StringName &p_name) {
|
|||
arg.name = bfi->argnames[i];
|
||||
info.arguments.push_back(arg);
|
||||
}
|
||||
info.default_arguments = bfi->default_arguments;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
@ -1920,6 +1910,24 @@ int Variant::get_utility_function_argument_count(const StringName &p_name) {
|
|||
return bfi->argcount;
|
||||
}
|
||||
|
||||
Vector<Variant> Variant::get_utility_function_default_arguments(const StringName &p_name) {
|
||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
||||
if (!bfi) {
|
||||
return varray();
|
||||
}
|
||||
|
||||
return bfi->default_arguments;
|
||||
}
|
||||
|
||||
int Variant::get_utility_function_default_argument_index(const StringName &p_name, int p_arg) {
|
||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
||||
if (!bfi) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_arg - (bfi->argcount - bfi->default_arguments.size());
|
||||
}
|
||||
|
||||
Variant::Type Variant::get_utility_function_argument_type(const StringName &p_name, int p_arg) {
|
||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
||||
if (!bfi) {
|
||||
|
|
|
@ -119,7 +119,7 @@ struct VariantUtilityFunctions {
|
|||
static void randomize();
|
||||
static int64_t randi();
|
||||
static double randf();
|
||||
static double randfn(double mean, double deviation);
|
||||
static double randfn(double mean = 0.0, double deviation = 1.0);
|
||||
static int64_t randi_range(int64_t from, int64_t to);
|
||||
static double randf_range(double from, double to);
|
||||
static void seed(int64_t s);
|
||||
|
|
|
@ -1033,8 +1033,8 @@
|
|||
</method>
|
||||
<method name="randfn">
|
||||
<return type="float" />
|
||||
<param index="0" name="mean" type="float" />
|
||||
<param index="1" name="deviation" type="float" />
|
||||
<param index="0" name="mean" type="float" default="0.0" />
|
||||
<param index="1" name="deviation" type="float" default="1.0" />
|
||||
<description>
|
||||
Returns a [url=https://en.wikipedia.org/wiki/Normal_distribution]normally-distributed[/url], pseudo-random floating-point value from the specified [param mean] and a standard [param deviation]. This is also known as a Gaussian distribution.
|
||||
[b]Note:[/b] This method uses the [url=https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform]Box-Muller transform[/url] algorithm.
|
||||
|
|
|
@ -981,6 +981,7 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
|
|||
if (Variant::is_utility_function_vararg(E)) {
|
||||
md.qualifiers = "vararg";
|
||||
} else {
|
||||
const Vector<Variant> def_args = Variant::get_utility_function_default_arguments(E);
|
||||
for (int i = 0; i < Variant::get_utility_function_argument_count(E); i++) {
|
||||
PropertyInfo pi;
|
||||
pi.type = Variant::get_utility_function_argument_type(E, i);
|
||||
|
@ -990,6 +991,12 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
|
|||
}
|
||||
DocData::ArgumentDoc ad;
|
||||
DocData::argument_doc_from_arginfo(ad, pi);
|
||||
|
||||
const int dargidx = Variant::get_utility_function_default_argument_index(E, i);
|
||||
if (dargidx >= 0) {
|
||||
ad.default_value = DocData::get_default_value_string(def_args[dargidx]);
|
||||
}
|
||||
|
||||
md.arguments.push_back(ad);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ static MethodInfo info_from_utility_func(const StringName &p_function) {
|
|||
pi.type = Variant::get_utility_function_argument_type(p_function, i);
|
||||
info.arguments.push_back(pi);
|
||||
}
|
||||
info.default_arguments = Variant::get_utility_function_default_arguments(p_function);
|
||||
}
|
||||
|
||||
return info;
|
||||
|
|
|
@ -621,6 +621,20 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(call->function_name) < Variant::VARIANT_MAX) {
|
||||
gen->write_construct(result, GDScriptParser::get_builtin_type(call->function_name), arguments);
|
||||
} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && Variant::has_utility_function(call->function_name)) {
|
||||
int arg_count = Variant::get_utility_function_argument_count(call->function_name);
|
||||
|
||||
if (call->arguments.size() < arg_count) {
|
||||
Vector<Variant> def_args = Variant::get_utility_function_default_arguments(call->function_name);
|
||||
|
||||
for (int i = call->arguments.size(); i < arg_count; i++) {
|
||||
const int dargidx = Variant::get_utility_function_default_argument_index(call->function_name, i);
|
||||
|
||||
if (dargidx >= 0) {
|
||||
arguments.push_back(codegen.add_constant(def_args[dargidx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variant utility function.
|
||||
gen->write_call_utility(result, call->function_name, arguments);
|
||||
} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptUtilityFunctions::function_exists(call->function_name)) {
|
||||
|
|
|
@ -2167,12 +2167,19 @@ TEST_CASE("[Variant] Utility functions") {
|
|||
if (Variant::is_utility_function_vararg(E)) {
|
||||
md.is_vararg = true;
|
||||
} else {
|
||||
const Vector<Variant> def_args = Variant::get_utility_function_default_arguments(E);
|
||||
for (int i = 0; i < Variant::get_utility_function_argument_count(E); i++) {
|
||||
ArgumentData arg;
|
||||
arg.type = Variant::get_utility_function_argument_type(E, i);
|
||||
arg.name = Variant::get_utility_function_argument_name(E, i);
|
||||
arg.position = i;
|
||||
|
||||
const int dargidx = Variant::get_utility_function_default_argument_index(E, i);
|
||||
if (dargidx >= 0) {
|
||||
arg.has_defval = true;
|
||||
arg.defval = def_args[dargidx];
|
||||
}
|
||||
|
||||
md.arguments.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
@ -2187,6 +2194,13 @@ TEST_CASE("[Variant] Utility functions") {
|
|||
|
||||
TEST_COND((arg.name.is_empty() || arg.name.begins_with("_unnamed_arg")),
|
||||
vformat("Unnamed argument in position %d of function '%s'.", arg.position, E.name));
|
||||
|
||||
if (arg.has_defval) {
|
||||
const bool arg_defval_assignable_to_type = arg.type == arg.defval.get_type();
|
||||
|
||||
TEST_COND(!arg_defval_assignable_to_type,
|
||||
vformat("Invalid default value for parameter '%s' of function '%s'.", arg.name, E.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue