diff options
| -rw-r--r-- | core/io/json.cpp | 32 | ||||
| -rw-r--r-- | core/io/json.h | 23 | ||||
| -rw-r--r-- | core/math/expression.cpp | 713 | ||||
| -rw-r--r-- | core/math/expression.h | 82 | ||||
| -rw-r--r-- | core/register_core_types.cpp | 2 | ||||
| -rw-r--r-- | core/string/ustring.h | 20 | ||||
| -rw-r--r-- | core/variant/variant.cpp | 26 | ||||
| -rw-r--r-- | core/variant/variant.h | 29 | ||||
| -rw-r--r-- | core/variant/variant_builtin_funcs.cpp | 1392 | ||||
| -rw-r--r-- | core/variant/variant_call.cpp | 20 | ||||
| -rw-r--r-- | core/variant/variant_construct.cpp | 20 | ||||
| -rw-r--r-- | editor/doc_data.cpp | 37 | 
12 files changed, 1574 insertions, 822 deletions
diff --git a/core/io/json.cpp b/core/io/json.cpp index 58bce1cf63..d61c2b8236 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -455,3 +455,35 @@ Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &  	return err;  } + +Error JSONParser::parse_string(const String &p_json_string) { +	return JSON::parse(p_json_string, data, err_text, err_line); +} +String JSONParser::get_error_text() const { +	return err_text; +} +int JSONParser::get_error_line() const { +	return err_line; +} +Variant JSONParser::get_data() const { +	return data; +} + +Error JSONParser::decode_data(const Variant &p_data, const String &p_indent, bool p_sort_keys) { +	string = JSON::print(p_data, p_indent, p_sort_keys); +	data = p_data; +	return OK; +} + +String JSONParser::get_string() const { +	return string; +} + +void JSONParser::_bind_methods() { +	ClassDB::bind_method(D_METHOD("parse_string", "json_string"), &JSONParser::parse_string); +	ClassDB::bind_method(D_METHOD("get_error_text"), &JSONParser::get_error_text); +	ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParser::get_error_line); +	ClassDB::bind_method(D_METHOD("get_data"), &JSONParser::get_data); +	ClassDB::bind_method(D_METHOD("decode_data", "data", "indent", "sort_keys"), &JSONParser::decode_data, DEFVAL(""), DEFVAL(true)); +	ClassDB::bind_method(D_METHOD("get_string"), &JSONParser::get_string); +} diff --git a/core/io/json.h b/core/io/json.h index 9fc6655fb4..2854d956ec 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -31,8 +31,8 @@  #ifndef JSON_H  #define JSON_H +#include "core/object/reference.h"  #include "core/variant/variant.h" -  class JSON {  	enum TokenType {  		TK_CURLY_BRACKET_OPEN, @@ -75,4 +75,25 @@ public:  	static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);  }; +class JSONParser : public Reference { +	GDCLASS(JSONParser, Reference); + +	Variant data; +	String string; +	String err_text; +	int err_line = 0; + +protected: +	static void _bind_methods(); + +public: +	Error parse_string(const String &p_json_string); +	String get_error_text() const; +	int get_error_line() const; +	Variant get_data() const; + +	Error decode_data(const Variant &p_data, const String &p_indent = "", bool p_sort_keys = true); +	String get_string() const; +}; +  #endif // JSON_H diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 48ad73bd32..13c8904f7e 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -37,688 +37,6 @@  #include "core/os/os.h"  #include "core/variant/variant_parser.h" -const char *Expression::func_name[Expression::FUNC_MAX] = { -	"sin", -	"cos", -	"tan", -	"sinh", -	"cosh", -	"tanh", -	"asin", -	"acos", -	"atan", -	"atan2", -	"sqrt", -	"fmod", -	"fposmod", -	"posmod", -	"floor", -	"ceil", -	"round", -	"abs", -	"sign", -	"pow", -	"log", -	"exp", -	"is_nan", -	"is_inf", -	"ease", -	"step_decimals", -	"stepify", -	"lerp", -	"lerp_angle", -	"inverse_lerp", -	"range_lerp", -	"smoothstep", -	"move_toward", -	"dectime", -	"randomize", -	"randi", -	"randf", -	"randf_range", -	"randi_range", -	"seed", -	"rand_seed", -	"deg2rad", -	"rad2deg", -	"linear2db", -	"db2linear", -	"polar2cartesian", -	"cartesian2polar", -	"wrapi", -	"wrapf", -	"max", -	"min", -	"clamp", -	"nearest_po2", -	"weakref", -	"convert", -	"typeof", -	"type_exists", -	"char", -	"ord", -	"str", -	"print", -	"printerr", -	"printraw", -	"var2str", -	"str2var", -	"var2bytes", -	"bytes2var", -	"color_named", -}; - -Expression::BuiltinFunc Expression::find_function(const String &p_string) { -	for (int i = 0; i < FUNC_MAX; i++) { -		if (p_string == func_name[i]) { -			return BuiltinFunc(i); -		} -	} - -	return FUNC_MAX; -} - -String Expression::get_func_name(BuiltinFunc p_func) { -	ERR_FAIL_INDEX_V(p_func, FUNC_MAX, String()); -	return func_name[p_func]; -} - -int Expression::get_func_argument_count(BuiltinFunc p_func) { -	switch (p_func) { -		case MATH_RANDOMIZE: -		case MATH_RANDI: -		case MATH_RANDF: -			return 0; -		case MATH_SIN: -		case MATH_COS: -		case MATH_TAN: -		case MATH_SINH: -		case MATH_COSH: -		case MATH_TANH: -		case MATH_ASIN: -		case MATH_ACOS: -		case MATH_ATAN: -		case MATH_SQRT: -		case MATH_FLOOR: -		case MATH_CEIL: -		case MATH_ROUND: -		case MATH_ABS: -		case MATH_SIGN: -		case MATH_LOG: -		case MATH_EXP: -		case MATH_ISNAN: -		case MATH_ISINF: -		case MATH_STEP_DECIMALS: -		case MATH_SEED: -		case MATH_RANDSEED: -		case MATH_DEG2RAD: -		case MATH_RAD2DEG: -		case MATH_LINEAR2DB: -		case MATH_DB2LINEAR: -		case LOGIC_NEAREST_PO2: -		case OBJ_WEAKREF: -		case TYPE_OF: -		case TEXT_CHAR: -		case TEXT_ORD: -		case TEXT_STR: -		case TEXT_PRINT: -		case TEXT_PRINTERR: -		case TEXT_PRINTRAW: -		case VAR_TO_STR: -		case STR_TO_VAR: -		case TYPE_EXISTS: -			return 1; -		case VAR_TO_BYTES: -		case BYTES_TO_VAR: -		case MATH_ATAN2: -		case MATH_FMOD: -		case MATH_FPOSMOD: -		case MATH_POSMOD: -		case MATH_POW: -		case MATH_EASE: -		case MATH_STEPIFY: -		case MATH_RANDF_RANGE: -		case MATH_RANDI_RANGE: -		case MATH_POLAR2CARTESIAN: -		case MATH_CARTESIAN2POLAR: -		case LOGIC_MAX: -		case LOGIC_MIN: -		case TYPE_CONVERT: -		case COLORN: -			return 2; -		case MATH_LERP: -		case MATH_LERP_ANGLE: -		case MATH_INVERSE_LERP: -		case MATH_SMOOTHSTEP: -		case MATH_MOVE_TOWARD: -		case MATH_DECTIME: -		case MATH_WRAP: -		case MATH_WRAPF: -		case LOGIC_CLAMP: -			return 3; -		case MATH_RANGE_LERP: -			return 5; -		case FUNC_MAX: { -		} -	} -	return 0; -} - -#define VALIDATE_ARG_NUM(m_arg)                                           \ -	if (!p_inputs[m_arg]->is_num()) {                                     \ -		r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \ -		r_error.argument = m_arg;                                         \ -		r_error.expected = Variant::FLOAT;                                \ -		return;                                                           \ -	} - -void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str) { -	r_error.error = Callable::CallError::CALL_OK; -	switch (p_func) { -		case MATH_SIN: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::sin((double)*p_inputs[0]); -		} break; -		case MATH_COS: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::cos((double)*p_inputs[0]); -		} break; -		case MATH_TAN: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::tan((double)*p_inputs[0]); -		} break; -		case MATH_SINH: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::sinh((double)*p_inputs[0]); -		} break; -		case MATH_COSH: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::cosh((double)*p_inputs[0]); -		} break; -		case MATH_TANH: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::tanh((double)*p_inputs[0]); -		} break; -		case MATH_ASIN: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::asin((double)*p_inputs[0]); -		} break; -		case MATH_ACOS: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::acos((double)*p_inputs[0]); -		} break; -		case MATH_ATAN: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::atan((double)*p_inputs[0]); -		} break; -		case MATH_ATAN2: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::atan2((double)*p_inputs[0], (double)*p_inputs[1]); -		} break; -		case MATH_SQRT: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::sqrt((double)*p_inputs[0]); -		} break; -		case MATH_FMOD: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::fmod((double)*p_inputs[0], (double)*p_inputs[1]); -		} break; -		case MATH_FPOSMOD: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]); -		} break; -		case MATH_POSMOD: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]); -		} break; -		case MATH_FLOOR: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::floor((double)*p_inputs[0]); -		} break; -		case MATH_CEIL: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::ceil((double)*p_inputs[0]); -		} break; -		case MATH_ROUND: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::round((double)*p_inputs[0]); -		} break; -		case MATH_ABS: { -			if (p_inputs[0]->get_type() == Variant::INT) { -				int64_t i = *p_inputs[0]; -				*r_return = ABS(i); -			} else if (p_inputs[0]->get_type() == Variant::FLOAT) { -				real_t r = *p_inputs[0]; -				*r_return = Math::abs(r); -			} else { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::FLOAT; -			} -		} break; -		case MATH_SIGN: { -			if (p_inputs[0]->get_type() == Variant::INT) { -				int64_t i = *p_inputs[0]; -				*r_return = i < 0 ? -1 : (i > 0 ? +1 : 0); -			} else if (p_inputs[0]->get_type() == Variant::FLOAT) { -				real_t r = *p_inputs[0]; -				*r_return = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0); -			} else { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::FLOAT; -			} -		} break; -		case MATH_POW: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::pow((double)*p_inputs[0], (double)*p_inputs[1]); -		} break; -		case MATH_LOG: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::log((double)*p_inputs[0]); -		} break; -		case MATH_EXP: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::exp((double)*p_inputs[0]); -		} break; -		case MATH_ISNAN: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::is_nan((double)*p_inputs[0]); -		} break; -		case MATH_ISINF: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::is_inf((double)*p_inputs[0]); -		} break; -		case MATH_EASE: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::ease((double)*p_inputs[0], (double)*p_inputs[1]); -		} break; -		case MATH_STEP_DECIMALS: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::step_decimals((double)*p_inputs[0]); -		} break; -		case MATH_STEPIFY: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::stepify((double)*p_inputs[0], (double)*p_inputs[1]); -		} break; -		case MATH_LERP: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); -		} break; -		case MATH_LERP_ANGLE: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::lerp_angle((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); -		} break; -		case MATH_INVERSE_LERP: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); -		} break; -		case MATH_RANGE_LERP: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			VALIDATE_ARG_NUM(3); -			VALIDATE_ARG_NUM(4); -			*r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]); -		} break; -		case MATH_SMOOTHSTEP: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); -		} break; -		case MATH_MOVE_TOWARD: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); -		} break; -		case MATH_DECTIME: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::dectime((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); -		} break; -		case MATH_RANDOMIZE: { -			Math::randomize(); - -		} break; -		case MATH_RANDI: { -			*r_return = Math::rand(); -		} break; -		case MATH_RANDF: { -			*r_return = Math::randf(); -		} break; -		case MATH_RANDF_RANGE: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::random((double)*p_inputs[0], (double)*p_inputs[1]); -		} break; -		case MATH_RANDI_RANGE: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			*r_return = Math::random((int)*p_inputs[0], (int)*p_inputs[1]); -		} break; -		case MATH_SEED: { -			VALIDATE_ARG_NUM(0); -			uint64_t seed = *p_inputs[0]; -			Math::seed(seed); - -		} break; -		case MATH_RANDSEED: { -			VALIDATE_ARG_NUM(0); -			uint64_t seed = *p_inputs[0]; -			int ret = Math::rand_from_seed(&seed); -			Array reta; -			reta.push_back(ret); -			reta.push_back(seed); -			*r_return = reta; - -		} break; -		case MATH_DEG2RAD: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::deg2rad((double)*p_inputs[0]); -		} break; -		case MATH_RAD2DEG: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::rad2deg((double)*p_inputs[0]); -		} break; -		case MATH_LINEAR2DB: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::linear2db((double)*p_inputs[0]); -		} break; -		case MATH_DB2LINEAR: { -			VALIDATE_ARG_NUM(0); -			*r_return = Math::db2linear((double)*p_inputs[0]); -		} break; -		case MATH_POLAR2CARTESIAN: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			double r = *p_inputs[0]; -			double th = *p_inputs[1]; -			*r_return = Vector2(r * Math::cos(th), r * Math::sin(th)); -		} break; -		case MATH_CARTESIAN2POLAR: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			double x = *p_inputs[0]; -			double y = *p_inputs[1]; -			*r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x)); -		} break; -		case MATH_WRAP: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::wrapi((int64_t)*p_inputs[0], (int64_t)*p_inputs[1], (int64_t)*p_inputs[2]); -		} break; -		case MATH_WRAPF: { -			VALIDATE_ARG_NUM(0); -			VALIDATE_ARG_NUM(1); -			VALIDATE_ARG_NUM(2); -			*r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); -		} break; -		case LOGIC_MAX: { -			if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { -				int64_t a = *p_inputs[0]; -				int64_t b = *p_inputs[1]; -				*r_return = MAX(a, b); -			} else { -				VALIDATE_ARG_NUM(0); -				VALIDATE_ARG_NUM(1); - -				real_t a = *p_inputs[0]; -				real_t b = *p_inputs[1]; - -				*r_return = MAX(a, b); -			} - -		} break; -		case LOGIC_MIN: { -			if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { -				int64_t a = *p_inputs[0]; -				int64_t b = *p_inputs[1]; -				*r_return = MIN(a, b); -			} else { -				VALIDATE_ARG_NUM(0); -				VALIDATE_ARG_NUM(1); - -				real_t a = *p_inputs[0]; -				real_t b = *p_inputs[1]; - -				*r_return = MIN(a, b); -			} -		} break; -		case LOGIC_CLAMP: { -			if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT && p_inputs[2]->get_type() == Variant::INT) { -				int64_t a = *p_inputs[0]; -				int64_t b = *p_inputs[1]; -				int64_t c = *p_inputs[2]; -				*r_return = CLAMP(a, b, c); -			} else { -				VALIDATE_ARG_NUM(0); -				VALIDATE_ARG_NUM(1); -				VALIDATE_ARG_NUM(2); - -				real_t a = *p_inputs[0]; -				real_t b = *p_inputs[1]; -				real_t c = *p_inputs[2]; - -				*r_return = CLAMP(a, b, c); -			} -		} break; -		case LOGIC_NEAREST_PO2: { -			VALIDATE_ARG_NUM(0); -			int64_t num = *p_inputs[0]; -			*r_return = next_power_of_2(num); -		} break; -		case OBJ_WEAKREF: { -			if (p_inputs[0]->get_type() != Variant::OBJECT) { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::OBJECT; - -				return; -			} - -			if (p_inputs[0]->is_ref()) { -				REF r = *p_inputs[0]; -				if (!r.is_valid()) { -					return; -				} - -				Ref<WeakRef> wref = memnew(WeakRef); -				wref->set_ref(r); -				*r_return = wref; -			} else { -				Object *obj = *p_inputs[0]; -				if (!obj) { -					return; -				} -				Ref<WeakRef> wref = memnew(WeakRef); -				wref->set_obj(obj); -				*r_return = wref; -			} - -		} break; -		case TYPE_CONVERT: { -			VALIDATE_ARG_NUM(1); -			int type = *p_inputs[1]; -			if (type < 0 || type >= Variant::VARIANT_MAX) { -				r_error_str = RTR("Invalid type argument to convert(), use TYPE_* constants."); -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::INT; -				return; - -			} else { -				Variant::construct(Variant::Type(type), *r_return, p_inputs, 1, r_error); -			} -		} break; -		case TYPE_OF: { -			*r_return = p_inputs[0]->get_type(); - -		} break; -		case TYPE_EXISTS: { -			*r_return = ClassDB::class_exists(*p_inputs[0]); - -		} break; -		case TEXT_CHAR: { -			char32_t result[2] = { *p_inputs[0], 0 }; - -			*r_return = String(result); - -		} break; -		case TEXT_ORD: { -			if (p_inputs[0]->get_type() != Variant::STRING) { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::STRING; - -				return; -			} - -			String str = *p_inputs[0]; - -			if (str.length() != 1) { -				r_error_str = RTR("Expected a string of length 1 (a character)."); -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::STRING; - -				return; -			} - -			*r_return = str.get(0); - -		} break; -		case TEXT_STR: { -			String str = *p_inputs[0]; - -			*r_return = str; - -		} break; -		case TEXT_PRINT: { -			String str = *p_inputs[0]; -			print_line(str); - -		} break; - -		case TEXT_PRINTERR: { -			String str = *p_inputs[0]; -			print_error(str); - -		} break; -		case TEXT_PRINTRAW: { -			String str = *p_inputs[0]; -			OS::get_singleton()->print("%s", str.utf8().get_data()); - -		} break; -		case VAR_TO_STR: { -			String vars; -			VariantWriter::write_to_string(*p_inputs[0], vars); -			*r_return = vars; -		} break; -		case STR_TO_VAR: { -			if (p_inputs[0]->get_type() != Variant::STRING) { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::STRING; - -				return; -			} - -			VariantParser::StreamString ss; -			ss.s = *p_inputs[0]; - -			String errs; -			int line; -			Error err = VariantParser::parse(&ss, *r_return, errs, line); - -			if (err != OK) { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::STRING; -				*r_return = "Parse error at line " + itos(line) + ": " + errs; -				return; -			} - -		} break; -		case VAR_TO_BYTES: { -			PackedByteArray barr; -			bool full_objects = *p_inputs[1]; -			int len; -			Error err = encode_variant(*p_inputs[0], nullptr, len, full_objects); -			if (err) { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::NIL; -				r_error_str = "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."; -				return; -			} - -			barr.resize(len); -			{ -				uint8_t *w = barr.ptrw(); -				encode_variant(*p_inputs[0], w, len, full_objects); -			} -			*r_return = barr; -		} break; -		case BYTES_TO_VAR: { -			if (p_inputs[0]->get_type() != Variant::PACKED_BYTE_ARRAY) { -				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -				r_error.argument = 0; -				r_error.expected = Variant::PACKED_BYTE_ARRAY; - -				return; -			} - -			PackedByteArray varr = *p_inputs[0]; -			bool allow_objects = *p_inputs[1]; -			Variant ret; -			{ -				const uint8_t *r = varr.ptr(); -				Error err = decode_variant(ret, r, varr.size(), nullptr, allow_objects); -				if (err != OK) { -					r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format."); -					r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; -					r_error.argument = 0; -					r_error.expected = Variant::PACKED_BYTE_ARRAY; -					return; -				} -			} - -			*r_return = ret; - -		} break; -		case COLORN: { -			VALIDATE_ARG_NUM(1); - -			Color color = Color::named(*p_inputs[0]); -			color.a = *p_inputs[1]; - -			*r_return = String(color); - -		} break; -		default: { -		} -	} -} - -//////// -  static bool _is_number(char32_t c) {  	return (c >= '0' && c <= '9');  } @@ -1092,18 +410,9 @@ Error Expression::_get_token(Token &r_token) {  					} else if (id == "self") {  						r_token.type = TK_SELF;  					} else { -						for (int i = 0; i < Variant::VARIANT_MAX; i++) { -							if (id == Variant::get_type_name(Variant::Type(i))) { -								r_token.type = TK_BASIC_TYPE; -								r_token.value = i; -								return OK; -							} -						} - -						BuiltinFunc bifunc = find_function(id); -						if (bifunc != FUNC_MAX) { +						if (Variant::has_builtin_func(id)) {  							r_token.type = TK_BUILTIN_FUNC; -							r_token.value = bifunc; +							r_token.value = id;  							return OK;  						} @@ -1401,6 +710,8 @@ Expression::ENode *Expression::_parse_expression() {  			case TK_BUILTIN_FUNC: {  				//builtin function +				StringName func = tk.value; +  				_get_token(tk);  				if (tk.type != TK_PARENTHESIS_OPEN) {  					_set_error("Expected '('"); @@ -1408,7 +719,7 @@ Expression::ENode *Expression::_parse_expression() {  				}  				BuiltinFuncNode *bifunc = alloc_node<BuiltinFuncNode>(); -				bifunc->func = BuiltinFunc(int(tk.value)); +				bifunc->func = func;  				while (true) {  					int cofs = str_ofs; @@ -1436,9 +747,11 @@ Expression::ENode *Expression::_parse_expression() {  					}  				} -				int expected_args = get_func_argument_count(bifunc->func); -				if (bifunc->arguments.size() != expected_args) { -					_set_error("Builtin func '" + get_func_name(bifunc->func) + "' expects " + itos(expected_args) + " arguments."); +				if (!Variant::is_builtin_func_vararg(bifunc->func)) { +					int expected_args = Variant::get_builtin_func_argument_count(bifunc->func); +					if (expected_args != bifunc->arguments.size()) { +						_set_error("Builtin func '" + String(bifunc->func) + "' expects " + itos(expected_args) + " arguments."); +					}  				}  				expr = bifunc; @@ -2047,11 +1360,11 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:  				argp.write[i] = &arr[i];  			} +			r_ret = Variant(); //may not return anything  			Callable::CallError ce; -			exec_func(bifunc->func, (const Variant **)argp.ptr(), &r_ret, ce, r_error_str); - +			Variant::call_builtin_func(bifunc->func, &r_ret, (const Variant **)argp.ptr(), argp.size(), ce);  			if (ce.error != Callable::CallError::CALL_OK) { -				r_error_str = "Builtin Call Failed. " + r_error_str; +				r_error_str = "Builtin Call Failed. " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce);  				return true;  			} diff --git a/core/math/expression.h b/core/math/expression.h index 991554f4fd..d9cedb8c2c 100644 --- a/core/math/expression.h +++ b/core/math/expression.h @@ -36,87 +36,7 @@  class Expression : public Reference {  	GDCLASS(Expression, Reference); -public: -	enum BuiltinFunc { -		MATH_SIN, -		MATH_COS, -		MATH_TAN, -		MATH_SINH, -		MATH_COSH, -		MATH_TANH, -		MATH_ASIN, -		MATH_ACOS, -		MATH_ATAN, -		MATH_ATAN2, -		MATH_SQRT, -		MATH_FMOD, -		MATH_FPOSMOD, -		MATH_POSMOD, -		MATH_FLOOR, -		MATH_CEIL, -		MATH_ROUND, -		MATH_ABS, -		MATH_SIGN, -		MATH_POW, -		MATH_LOG, -		MATH_EXP, -		MATH_ISNAN, -		MATH_ISINF, -		MATH_EASE, -		MATH_STEP_DECIMALS, -		MATH_STEPIFY, -		MATH_LERP, -		MATH_LERP_ANGLE, -		MATH_INVERSE_LERP, -		MATH_RANGE_LERP, -		MATH_SMOOTHSTEP, -		MATH_MOVE_TOWARD, -		MATH_DECTIME, -		MATH_RANDOMIZE, -		MATH_RANDI, -		MATH_RANDF, -		MATH_RANDF_RANGE, -		MATH_RANDI_RANGE, -		MATH_SEED, -		MATH_RANDSEED, -		MATH_DEG2RAD, -		MATH_RAD2DEG, -		MATH_LINEAR2DB, -		MATH_DB2LINEAR, -		MATH_POLAR2CARTESIAN, -		MATH_CARTESIAN2POLAR, -		MATH_WRAP, -		MATH_WRAPF, -		LOGIC_MAX, -		LOGIC_MIN, -		LOGIC_CLAMP, -		LOGIC_NEAREST_PO2, -		OBJ_WEAKREF, -		TYPE_CONVERT, -		TYPE_OF, -		TYPE_EXISTS, -		TEXT_CHAR, -		TEXT_ORD, -		TEXT_STR, -		TEXT_PRINT, -		TEXT_PRINTERR, -		TEXT_PRINTRAW, -		VAR_TO_STR, -		STR_TO_VAR, -		VAR_TO_BYTES, -		BYTES_TO_VAR, -		COLORN, -		FUNC_MAX -	}; - -	static int get_func_argument_count(BuiltinFunc p_func); -	static String get_func_name(BuiltinFunc p_func); -	static void exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str); -	static BuiltinFunc find_function(const String &p_string); -  private: -	static const char *func_name[FUNC_MAX]; -  	struct Input {  		Variant::Type type = Variant::NIL;  		String name; @@ -315,7 +235,7 @@ private:  	};  	struct BuiltinFuncNode : public ENode { -		BuiltinFunc func; +		StringName func;  		Vector<ENode *> arguments;  		BuiltinFuncNode() {  			type = TYPE_BUILTIN_FUNC; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 6bbdad11f8..7e32f215e7 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -43,6 +43,7 @@  #include "core/io/dtls_server.h"  #include "core/io/http_client.h"  #include "core/io/image_loader.h" +#include "core/io/json.h"  #include "core/io/marshalls.h"  #include "core/io/multiplayer_api.h"  #include "core/io/networked_multiplayer_peer.h" @@ -197,6 +198,7 @@ void register_core_types() {  	ClassDB::register_class<_Semaphore>();  	ClassDB::register_class<XMLParser>(); +	ClassDB::register_class<JSONParser>();  	ClassDB::register_class<ConfigFile>(); diff --git a/core/string/ustring.h b/core/string/ustring.h index 201b439b12..b46733ab66 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -536,4 +536,24 @@ String RTRN(const String &p_text, const String &p_text_plural, int p_n, const St  bool is_symbol(char32_t c);  bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end); +_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) { +} + +_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) { +	arr.push_back(p_str); +} + +template <class... P> +_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) { +	arr.push_back(p_str); +	sarray_add_str(arr, p_args...); +} + +template <class... P> +_FORCE_INLINE_ Vector<String> sarray(P... p_args) { +	Vector<String> arr; +	sarray_add_str(arr, p_args...); +	return arr; +} +  #endif // USTRING_H diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 3114a358f7..055f61cf92 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -3435,6 +3435,30 @@ String Variant::get_construct_string() const {  	return vars;  } +String Variant::get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) { +	String err_text; + +	if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) { +		int errorarg = ce.argument; +		if (p_argptrs) { +			err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + "."; +		} else { +			err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + "."; +		} +	} else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { +		err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + "."; +	} else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { +		err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + "."; +	} else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) { +		err_text = "Method not found."; +	} else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) { +		err_text = "Instance is null"; +	} else if (ce.error == Callable::CallError::CALL_OK) { +		return "Call OK"; +	} +	return "'" + String(p_method) + "': " + err_text; +} +  String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {  	String err_text; @@ -3525,10 +3549,12 @@ void Variant::register_types() {  	_register_variant_methods();  	_register_variant_setters_getters();  	_register_variant_constructors(); +	_register_variant_builtin_funcs();  }  void Variant::unregister_types() {  	_unregister_variant_operators();  	_unregister_variant_methods();  	_unregister_variant_setters_getters();  	_unregister_variant_constructors(); +	_unregister_variant_builtin_funcs();  } diff --git a/core/variant/variant.h b/core/variant/variant.h index ee08373b27..d3e2f84357 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -267,6 +267,8 @@ private:  	static void _unregister_variant_setters_getters();  	static void _register_variant_constructors();  	static void _unregister_variant_constructors(); +	static void _register_variant_builtin_funcs(); +	static void _unregister_variant_builtin_funcs();  public:  	_FORCE_INLINE_ Type get_type() const { @@ -523,6 +525,7 @@ public:  	Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);  	Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant()); +	static String get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);  	static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);  	static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce); @@ -619,6 +622,32 @@ public:  	void get_property_list(List<PropertyInfo> *p_list) const; +	static void call_builtin_func(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error); +	static bool has_builtin_func(const StringName &p_name); + +	typedef void (*BuiltinFunctionValidatedCall)(Variant *r_ret, const Variant **p_args, int p_argcount); +	typedef void (*BuiltinFunctionPTRCall)(void *r_ret, const void **p_args, int p_argcount); + +	static BuiltinFunctionValidatedCall get_builtin_validated_caller(const StringName &p_name); +	static BuiltinFunctionPTRCall get_builtin_ptr_caller(const StringName &p_name); + +	enum BuiltInFunctionType { +		BUILTIN_FUNC_TYPE_MATH, +		BUILTIN_FUNC_TYPE_RANDOM, +		BUILTIN_FUNC_TYPE_UTILITY, +	}; + +	static BuiltInFunctionType get_builtin_func_type(const StringName &p_name); + +	static int get_builtin_func_argument_count(const StringName &p_name); +	static Variant::Type get_builtin_func_argument_type(const StringName &p_name, int p_arg); +	static String get_builtin_func_argument_name(const StringName &p_name, int p_arg); +	static bool has_builtin_func_return_value(const StringName &p_name); +	static Variant::Type get_builtin_func_return_type(const StringName &p_name); +	static bool is_builtin_func_vararg(const StringName &p_name); + +	static void get_builtin_function_list(List<StringName> *r_functions); +  	//argsVariant call()  	bool operator==(const Variant &p_variant) const; diff --git a/core/variant/variant_builtin_funcs.cpp b/core/variant/variant_builtin_funcs.cpp new file mode 100644 index 0000000000..e89b83e6dd --- /dev/null +++ b/core/variant/variant_builtin_funcs.cpp @@ -0,0 +1,1392 @@ +/*************************************************************************/ +/*  variant_builtin_funcs.cpp                                            */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +#include "variant.h" + +#include "core/core_string_names.h" +#include "core/io/marshalls.h" +#include "core/object/reference.h" +#include "core/os/os.h" +#include "core/templates/oa_hash_map.h" +#include "core/variant/binder_common.h" +#include "core/variant/variant_parser.h" + +struct VariantBuiltinFunctions { +	// Math +	static inline double sin(double arg) { +		return Math::sin(arg); +	} +	static inline double cos(double arg) { +		return Math::cos(arg); +	} +	static inline double tan(double arg) { +		return Math::tan(arg); +	} + +	static inline double sinh(double arg) { +		return Math::sinh(arg); +	} +	static inline double cosh(double arg) { +		return Math::cosh(arg); +	} +	static inline double tanh(double arg) { +		return Math::tanh(arg); +	} + +	static inline double asin(double arg) { +		return Math::asin(arg); +	} +	static inline double acos(double arg) { +		return Math::acos(arg); +	} +	static inline double atan(double arg) { +		return Math::atan(arg); +	} + +	static inline double atan2(double y, double x) { +		return Math::atan2(y, x); +	} + +	static inline double sqrt(double x) { +		return Math::sqrt(x); +	} + +	static inline double fmod(double b, double r) { +		return Math::fmod(b, r); +	} + +	static inline double fposmod(double b, double r) { +		return Math::fposmod(b, r); +	} + +	static inline double floor(double x) { +		return Math::floor(x); +	} + +	static inline double ceil(double x) { +		return Math::ceil(x); +	} + +	static inline double round(double x) { +		return Math::round(x); +	} + +	static inline Variant abs(const Variant &x, Callable::CallError &r_error) { +		r_error.error = Callable::CallError::CALL_OK; +		switch (x.get_type()) { +			case Variant::INT: { +				return ABS(VariantInternalAccessor<int64_t>::get(&x)); +			} break; +			case Variant::FLOAT: { +				return Math::absd(VariantInternalAccessor<double>::get(&x)); +			} break; +			case Variant::VECTOR2: { +				return VariantInternalAccessor<Vector2>::get(&x).abs(); +			} break; +			case Variant::VECTOR2I: { +				return VariantInternalAccessor<Vector2i>::get(&x).abs(); +			} break; +			case Variant::VECTOR3: { +				return VariantInternalAccessor<Vector3>::get(&x).abs(); +			} break; +			case Variant::VECTOR3I: { +				return VariantInternalAccessor<Vector3i>::get(&x).abs(); +			} break; +			default: { +				r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; +				return Variant(); +			} +		} +	} + +	static inline double absf(double x) { +		return Math::absd(x); +	} + +	static inline int64_t absi(int64_t x) { +		return ABS(x); +	} + +	static inline Variant sign(const Variant &x, Callable::CallError &r_error) { +		r_error.error = Callable::CallError::CALL_OK; +		switch (x.get_type()) { +			case Variant::INT: { +				return SGN(VariantInternalAccessor<int64_t>::get(&x)); +			} break; +			case Variant::FLOAT: { +				return SGN(VariantInternalAccessor<double>::get(&x)); +			} break; +			case Variant::VECTOR2: { +				return VariantInternalAccessor<Vector2>::get(&x).sign(); +			} break; +			case Variant::VECTOR2I: { +				return VariantInternalAccessor<Vector2i>::get(&x).sign(); +			} break; +			case Variant::VECTOR3: { +				return VariantInternalAccessor<Vector3>::get(&x).sign(); +			} break; +			case Variant::VECTOR3I: { +				return VariantInternalAccessor<Vector3i>::get(&x).sign(); +			} break; +			default: { +				r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; +				return Variant(); +			} +		} +	} + +	static inline double signf(double x) { +		return SGN(x); +	} + +	static inline int64_t signi(int64_t x) { +		return SGN(x); +	} + +	static inline double pow(double x, double y) { +		return Math::pow(x, y); +	} +	static inline double log(double x) { +		return Math::log(x); +	} + +	static inline double exp(double x) { +		return Math::exp(x); +	} + +	static inline double is_nan(double x) { +		return Math::is_nan(x); +	} + +	static inline double is_inf(double x) { +		return Math::is_inf(x); +	} + +	static inline double is_equal_approx(double x, double y) { +		return Math::is_equal_approx(x, y); +	} + +	static inline double is_zero_approx(double x) { +		return Math::is_zero_approx(x); +	} + +	static inline double ease(float x, float c) { +		return Math::ease(x, c); +	} + +	static inline int step_decimals(float step) { +		return Math::step_decimals(step); +	} + +	static inline int range_step_decimals(float step) { +		return Math::range_step_decimals(step); +	} + +	static inline double stepify(double value, double step) { +		return Math::stepify(value, step); +	} + +	static inline double lerp(double from, double to, double weight) { +		return Math::lerp(from, to, weight); +	} + +	static inline double lerp_angle(double from, double to, double weight) { +		return Math::lerp_angle(from, to, weight); +	} + +	static inline double inverse_lerp(double from, double to, double weight) { +		return Math::inverse_lerp(from, to, weight); +	} + +	static inline double range_lerp(double value, double istart, double istop, double ostart, double ostop) { +		return Math::range_lerp(value, istart, istop, ostart, ostop); +	} + +	static inline double smoothstep(double from, double to, double val) { +		return Math::smoothstep(from, to, val); +	} + +	static inline double move_toward(double from, double to, double delta) { +		return Math::move_toward(from, to, delta); +	} + +	static inline double dectime(double value, double amount, double step) { +		return Math::dectime(value, amount, step); +	} + +	static inline double deg2rad(double angle_deg) { +		return Math::deg2rad(angle_deg); +	} + +	static inline double rad2deg(double angle_rad) { +		return Math::rad2deg(angle_rad); +	} + +	static inline double linear2db(double linear) { +		return Math::linear2db(linear); +	} + +	static inline double db2linear(double db) { +		return Math::db2linear(db); +	} + +	static inline Vector2 polar2cartesian(double r, double th) { +		return Vector2(r * Math::cos(th), r * Math::sin(th)); +	} + +	static inline Vector2 cartesian2polar(double x, double y) { +		return Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x)); +	} + +	static inline int64_t wrapi(int64_t value, int64_t min, int64_t max) { +		return Math::wrapi(value, min, max); +	} +	static inline double wrapf(double value, double min, double max) { +		return Math::wrapf(value, min, max); +	} + +	static inline Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +		if (p_argcount < 2) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.expected = 2; +			return Variant(); +		} +		Variant base = *p_args[0]; +		Variant ret; +		for (int i = 1; i < p_argcount; i++) { +			bool valid; +			Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid); +			if (!valid) { +				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; +				r_error.expected = base.get_type(); +				r_error.argument = i; +				return Variant(); +			} +			if (ret.booleanize()) { +				base = *p_args[i]; +			} +		} +		r_error.error = Callable::CallError::CALL_OK; +		return base; +	} + +	static inline double maxf(double x, double y) { +		return MAX(x, y); +	} + +	static inline int64_t maxi(int64_t x, int64_t y) { +		return MAX(x, y); +	} + +	static inline Variant min(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +		if (p_argcount < 2) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.expected = 2; +			return Variant(); +		} +		Variant base = *p_args[0]; +		Variant ret; +		for (int i = 1; i < p_argcount; i++) { +			bool valid; +			Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid); +			if (!valid) { +				r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; +				r_error.expected = base.get_type(); +				r_error.argument = i; +				return Variant(); +			} +			if (ret.booleanize()) { +				base = *p_args[i]; +			} +		} +		r_error.error = Callable::CallError::CALL_OK; +		return base; +	} + +	static inline double minf(double x, double y) { +		return MIN(x, y); +	} + +	static inline int64_t mini(int64_t x, int64_t y) { +		return MIN(x, y); +	} + +	static inline Variant clamp(const Variant &x, const Variant &min, const Variant &max, Callable::CallError &r_error) { +		Variant value = x; + +		Variant ret; + +		bool valid; +		Variant::evaluate(Variant::OP_LESS, value, min, ret, valid); +		if (!valid) { +			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; +			r_error.expected = value.get_type(); +			r_error.argument = 1; +			return Variant(); +		} +		if (ret.booleanize()) { +			value = min; +		} +		Variant::evaluate(Variant::OP_GREATER, value, max, ret, valid); +		if (!valid) { +			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; +			r_error.expected = value.get_type(); +			r_error.argument = 2; +			return Variant(); +		} +		if (ret.booleanize()) { +			value = max; +		} + +		r_error.error = Callable::CallError::CALL_OK; + +		return value; +	} + +	static inline double clampf(double x, double min, double max) { +		return CLAMP(x, min, max); +	} + +	static inline int64_t clampi(int64_t x, int64_t min, int64_t max) { +		return CLAMP(x, min, max); +	} + +	static inline int64_t nearest_po2(int64_t x) { +		return nearest_power_of_2_templated(uint64_t(x)); +	} + +	// Random + +	static inline void randomize() { +		Math::randomize(); +	} + +	static inline int64_t randi() { +		return Math::rand(); +	} + +	static inline double randf() { +		return Math::randf(); +	} + +	static inline int64_t randi_range(int64_t from, int64_t to) { +		return Math::random((int32_t)from, (int32_t)to); +	} + +	static inline double randf_range(double from, double to) { +		return Math::random(from, to); +	} + +	static inline void seed(int64_t s) { +		return Math::seed(s); +	} + +	static inline PackedInt64Array rand_from_seed(int64_t seed) { +		uint64_t s = seed; +		PackedInt64Array arr; +		arr.resize(2); +		arr.write[0] = Math::rand_from_seed(&s); +		arr.write[1] = s; +		return arr; +	} + +	// Utility + +	static inline Variant weakref(const Variant &obj, Callable::CallError &r_error) { +		if (obj.get_type() == Variant::OBJECT) { +			r_error.error = Callable::CallError::CALL_OK; +			if (obj.is_ref()) { +				Ref<WeakRef> wref = memnew(WeakRef); +				REF r = obj; +				if (r.is_valid()) { +					wref->set_ref(r); +				} +				return wref; +			} else { +				Ref<WeakRef> wref = memnew(WeakRef); +				Object *o = obj.get_validated_object(); +				if (o) { +					wref->set_obj(o); +				} +				return wref; +			} +		} else if (obj.get_type() == Variant::NIL) { +			r_error.error = Callable::CallError::CALL_OK; +			Ref<WeakRef> wref = memnew(WeakRef); +			return wref; +		} else { +			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; +			r_error.argument = 0; +			r_error.expected = Variant::OBJECT; +			return Variant(); +		} +	} + +	static inline int64_t _typeof(const Variant &obj) { +		return obj.get_type(); +	} + +	static inline String str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +			return String(); +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			String os = p_args[i]->operator String(); + +			if (i == 0) { +				str = os; +			} else { +				str += os; +			} +		} + +		r_error.error = Callable::CallError::CALL_OK; + +		return str; +	} + +	static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			String os = p_args[i]->operator String(); + +			if (i == 0) { +				str = os; +			} else { +				str += os; +			} +		} + +		print_line(str); +		r_error.error = Callable::CallError::CALL_OK; +	} + +	static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			String os = p_args[i]->operator String(); + +			if (i == 0) { +				str = os; +			} else { +				str += os; +			} +		} + +		print_error(str); +		r_error.error = Callable::CallError::CALL_OK; +	} + +	static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			if (i) { +				str += "\t"; +			} +			str += p_args[i]->operator String(); +		} + +		print_error(str); +		r_error.error = Callable::CallError::CALL_OK; +	} + +	static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			if (i) { +				str += " "; +			} +			str += p_args[i]->operator String(); +		} + +		print_error(str); +		r_error.error = Callable::CallError::CALL_OK; +	} + +	static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			String os = p_args[i]->operator String(); + +			if (i == 0) { +				str = os; +			} else { +				str += os; +			} +		} + +		OS::get_singleton()->print("%s", str.utf8().get_data()); +		r_error.error = Callable::CallError::CALL_OK; +	} + +	static inline void push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			String os = p_args[i]->operator String(); + +			if (i == 0) { +				str = os; +			} else { +				str += os; +			} +		} + +		ERR_PRINT(str); +		r_error.error = Callable::CallError::CALL_OK; +	} + +	static inline void push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +		if (p_arg_count < 1) { +			r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +			r_error.argument = 1; +		} +		String str; +		for (int i = 0; i < p_arg_count; i++) { +			String os = p_args[i]->operator String(); + +			if (i == 0) { +				str = os; +			} else { +				str += os; +			} +		} + +		WARN_PRINT(str); +		r_error.error = Callable::CallError::CALL_OK; +	} + +	static inline String var2str(const Variant &p_var) { +		String vars; +		VariantWriter::write_to_string(p_var, vars); +		return vars; +	} + +	static inline Variant str2var(const String &p_var) { +		VariantParser::StreamString ss; +		ss.s = p_var; + +		String errs; +		int line; +		Variant ret; +		(void)VariantParser::parse(&ss, ret, errs, line); + +		return ret; +	} + +	static inline PackedByteArray var2bytes(const Variant &p_var) { +		int len; +		Error err = encode_variant(p_var, nullptr, len, false); +		if (err != OK) { +			return PackedByteArray(); +		} + +		PackedByteArray barr; +		barr.resize(len); +		{ +			uint8_t *w = barr.ptrw(); +			err = encode_variant(p_var, w, len, false); +			if (err != OK) { +				return PackedByteArray(); +			} +		} + +		return barr; +	} + +	static inline PackedByteArray var2bytes_with_objects(const Variant &p_var) { +		int len; +		Error err = encode_variant(p_var, nullptr, len, true); +		if (err != OK) { +			return PackedByteArray(); +		} + +		PackedByteArray barr; +		barr.resize(len); +		{ +			uint8_t *w = barr.ptrw(); +			err = encode_variant(p_var, w, len, true); +			if (err != OK) { +				return PackedByteArray(); +			} +		} + +		return barr; +	} + +	static inline Variant bytes2var(const PackedByteArray &p_arr) { +		Variant ret; +		{ +			const uint8_t *r = p_arr.ptr(); +			Error err = decode_variant(ret, r, p_arr.size(), nullptr, false); +			if (err != OK) { +				return Variant(); +			} +		} +		return ret; +	} + +	static inline Variant bytes2var_with_objects(const PackedByteArray &p_arr) { +		Variant ret; +		{ +			const uint8_t *r = p_arr.ptr(); +			Error err = decode_variant(ret, r, p_arr.size(), nullptr, true); +			if (err != OK) { +				return Variant(); +			} +		} +		return ret; +	} + +	static inline int64_t hash(const Variant &p_arr) { +		return p_arr.hash(); +	} + +	static inline Variant instance_from_id(int64_t p_id) { +		ObjectID id = ObjectID((uint64_t)p_id); +		Variant ret = ObjectDB::get_instance(id); +		return ret; +	} + +	static inline bool is_instance_id_valid(int64_t p_id) { +		return ObjectDB::get_instance(ObjectID((uint64_t)p_id)) != nullptr; +	} + +	static inline bool is_instance_valid(const Variant &p_instance) { +		if (p_instance.get_type() != Variant::OBJECT) { +			return false; +		} +		return p_instance.get_validated_object() != nullptr; +	} +}; + +#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 <class R, class... 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; +	(void)r_error; +} + +template <class R, class... 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 <class R, class... 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 <class R, class... 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)>{}); +} + +template <class R, class... 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)>{}); +} + +template <class R, class... 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)>{}); +} + +template <class R, class... P> +static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(P...)) { +	return sizeof...(P); +} + +template <class R, class... P> +static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int p_arg) { +	return call_get_argument_type<P...>(p_arg); +} + +template <class R, class... P> +static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) { +	return GetTypeInfo<R>::VARIANT_TYPE; +} + +// WITHOUT RET + +template <class... 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 <class... 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 <class... 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])...); +	(void)p_args; +} + +template <class... 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)>{}); +} + +template <class... 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)>{}); +} + +template <class... 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)>{}); +} + +template <class... P> +static _FORCE_INLINE_ int get_arg_count_helper(void (*p_func)(P...)) { +	return sizeof...(P); +} + +template <class... P> +static _FORCE_INLINE_ Variant::Type get_arg_type_helper(void (*p_func)(P...), int p_arg) { +	return call_get_argument_type<P...>(p_arg); +} + +template <class... P> +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(VariantBuiltinFunctions::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(VariantBuiltinFunctions::m_func, r_ret, p_args);                              \ +		}                                                                                                        \ +		static void ptrcall(void *ret, const void **p_args, int p_argcount) {                                    \ +			ptr_call_helperr(VariantBuiltinFunctions::m_func, ret, p_args);                                      \ +		}                                                                                                        \ +                                                                                                                 \ +		static int get_argument_count() {                                                                        \ +			return get_arg_count_helperr(VariantBuiltinFunctions::m_func);                                       \ +		}                                                                                                        \ +                                                                                                                 \ +		static Variant::Type get_argument_type(int p_arg) {                                                      \ +			return get_arg_type_helperr(VariantBuiltinFunctions::m_func, p_arg);                                 \ +		}                                                                                                        \ +                                                                                                                 \ +		static Variant::Type get_return_type() {                                                                 \ +			return get_ret_type_helperr(VariantBuiltinFunctions::m_func);                                        \ +		}                                                                                                        \ +		static bool has_return_type() {                                                                          \ +			return true;                                                                                         \ +		}                                                                                                        \ +		static bool is_vararg() { return false; }                                                                \ +		static Variant::BuiltInFunctionType get_type() { return m_category; }                                    \ +	};                                                                                                           \ +	register_builtin_function<Func_##m_func>(#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 = VariantBuiltinFunctions::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 = VariantBuiltinFunctions::m_func(*p_args[0], ce);                                                   \ +		}                                                                                                               \ +		static void ptrcall(void *ret, const void **p_args, int p_argcount) {                                           \ +			Callable::CallError ce;                                                                                     \ +			PtrToArg<Variant>::encode(VariantBuiltinFunctions::m_func(PtrToArg<Variant>::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::BuiltInFunctionType get_type() { return m_category; }                                           \ +	};                                                                                                                  \ +	register_builtin_function<Func_##m_func>(#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 = VariantBuiltinFunctions::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 = VariantBuiltinFunctions::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 = VariantBuiltinFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), PtrToArg<Variant>::convert(p_args[1]), PtrToArg<Variant>::convert(p_args[2]), ce); \ +			PtrToArg<Variant>::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::BuiltInFunctionType get_type() { return m_category; }                                                                                             \ +	};                                                                                                                                                                    \ +	register_builtin_function<Func_##m_func>(#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 = VariantBuiltinFunctions::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 = VariantBuiltinFunctions::m_func(p_args, p_argcount, c);                                     \ +		}                                                                                                        \ +		static void ptrcall(void *ret, const void **p_args, int p_argcount) {                                    \ +			Vector<Variant> args;                                                                                \ +			for (int i = 0; i < p_argcount; i++) {                                                               \ +				args.push_back(PtrToArg<Variant>::convert(p_args[i]));                                           \ +			}                                                                                                    \ +			Vector<const Variant *> 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<Variant>::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::BuiltInFunctionType get_type() {                                                         \ +			return m_category;                                                                                   \ +		}                                                                                                        \ +	};                                                                                                           \ +	register_builtin_function<Func_##m_func>(#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 = VariantBuiltinFunctions::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 = VariantBuiltinFunctions::m_func(p_args, p_argcount, c);                                     \ +		}                                                                                                        \ +		static void ptrcall(void *ret, const void **p_args, int p_argcount) {                                    \ +			Vector<Variant> args;                                                                                \ +			for (int i = 0; i < p_argcount; i++) {                                                               \ +				args.push_back(PtrToArg<Variant>::convert(p_args[i]));                                           \ +			}                                                                                                    \ +			Vector<const Variant *> 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<String>::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::BuiltInFunctionType get_type() {                                                         \ +			return m_category;                                                                                   \ +		}                                                                                                        \ +	};                                                                                                           \ +	register_builtin_function<Func_##m_func>(#m_func, m_args) + +#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) { \ +			r_error.error = Callable::CallError::CALL_OK;                                                        \ +			VariantBuiltinFunctions::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;                                                                               \ +			VariantBuiltinFunctions::m_func(p_args, p_argcount, c);                                              \ +		}                                                                                                        \ +		static void ptrcall(void *ret, const void **p_args, int p_argcount) {                                    \ +			Vector<Variant> args;                                                                                \ +			for (int i = 0; i < p_argcount; i++) {                                                               \ +				args.push_back(PtrToArg<Variant>::convert(p_args[i]));                                           \ +			}                                                                                                    \ +			Vector<const Variant *> 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::BuiltInFunctionType get_type() {                                                         \ +			return m_category;                                                                                   \ +		}                                                                                                        \ +	};                                                                                                           \ +	register_builtin_function<Func_##m_func>(#m_func, m_args) + +#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(VariantBuiltinFunctions::m_func, p_args, r_error);                                       \ +		}                                                                                                        \ +                                                                                                                 \ +		static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) {                     \ +			validated_call_helper(VariantBuiltinFunctions::m_func, p_args);                                      \ +		}                                                                                                        \ +		static void ptrcall(void *ret, const void **p_args, int p_argcount) {                                    \ +			ptr_call_helper(VariantBuiltinFunctions::m_func, p_args);                                            \ +		}                                                                                                        \ +                                                                                                                 \ +		static int get_argument_count() {                                                                        \ +			return get_arg_count_helper(VariantBuiltinFunctions::m_func);                                        \ +		}                                                                                                        \ +                                                                                                                 \ +		static Variant::Type get_argument_type(int p_arg) {                                                      \ +			return get_arg_type_helper(VariantBuiltinFunctions::m_func, p_arg);                                  \ +		}                                                                                                        \ +                                                                                                                 \ +		static Variant::Type get_return_type() {                                                                 \ +			return get_ret_type_helper(VariantBuiltinFunctions::m_func);                                         \ +		}                                                                                                        \ +		static bool has_return_type() {                                                                          \ +			return false;                                                                                        \ +		}                                                                                                        \ +		static bool is_vararg() { return false; }                                                                \ +		static Variant::BuiltInFunctionType get_type() { return m_category; }                                    \ +	};                                                                                                           \ +	register_builtin_function<Func_##m_func>(#m_func, m_args) + +struct VariantBuiltinFunctionInfo { +	void (*call_builtin)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error); +	Variant::BuiltinFunctionValidatedCall validated_call_builtin; +	Variant::BuiltinFunctionPTRCall ptr_call_builtin; +	Vector<String> argnames; +	bool is_vararg; +	bool returns_value; +	int argcount; +	Variant::Type (*get_arg_type)(int); +	Variant::Type return_type; +	Variant::BuiltInFunctionType type; +}; + +static OAHashMap<StringName, VariantBuiltinFunctionInfo> builtin_function_table; +static List<StringName> builtin_function_name_table; + +template <class T> +static void register_builtin_function(const String &p_name, const Vector<String> &argnames) { +	String name = p_name; +	if (name.begins_with("_")) { +		name = name.substr(1, name.length() - 1); +	} +	StringName sname = name; +	ERR_FAIL_COND(builtin_function_table.has(sname)); + +	VariantBuiltinFunctionInfo bfi; +	bfi.call_builtin = T::call; +	bfi.validated_call_builtin = T::validated_call; +	bfi.ptr_call_builtin = T::ptrcall; +	bfi.is_vararg = T::is_vararg(); +	bfi.argnames = argnames; +	bfi.argcount = T::get_argument_count(); +	if (!bfi.is_vararg) { +		ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, "wrong number of arguments binding builtin function: " + name); +	} +	bfi.get_arg_type = T::get_argument_type; +	bfi.return_type = T::get_return_type(); +	bfi.type = T::get_type(); +	bfi.returns_value = T::has_return_type(); + +	builtin_function_table.insert(sname, bfi); +	builtin_function_name_table.push_back(sname); +} + +void Variant::_register_variant_builtin_funcs() { +	// Math + +	FUNCBINDR(sin, sarray("angle_rad"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(cos, sarray("angle_rad"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(tan, sarray("angle_rad"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(sinh, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(cosh, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(tanh, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(asin, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(acos, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(atan, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(atan2, sarray("y", "x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(sqrt, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(fmod, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(fposmod, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(floor, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(ceil, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(round, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDVR(abs, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(absf, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(absi, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDVR(sign, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(signf, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(signi, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(pow, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(log, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(exp, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(is_nan, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(is_inf, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(is_equal_approx, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(is_zero_approx, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(ease, sarray("x", "c"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(step_decimals, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(range_step_decimals, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(stepify, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(lerp, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(lerp_angle, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(inverse_lerp, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(range_lerp, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(smoothstep, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(dectime, sarray("value", "amount", "step"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(deg2rad, sarray("deg"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(rad2deg, sarray("rad"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(linear2db, sarray("lin"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(db2linear, sarray("db"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(polar2cartesian, sarray("r", "th"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(cartesian2polar, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(wrapi, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(wrapf, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDVARARG(max, sarray(), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(maxi, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(maxf, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDVARARG(min, sarray(), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(mini, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(minf, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDVR3(clamp, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(clampi, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH); +	FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	FUNCBINDR(nearest_po2, sarray("value"), Variant::BUILTIN_FUNC_TYPE_MATH); + +	//Random + +	FUNCBIND(randomize, sarray(), Variant::BUILTIN_FUNC_TYPE_RANDOM); +	FUNCBINDR(randi, sarray(), Variant::BUILTIN_FUNC_TYPE_RANDOM); +	FUNCBINDR(randf, sarray(), Variant::BUILTIN_FUNC_TYPE_RANDOM); +	FUNCBINDR(randi_range, sarray("from", "to"), Variant::BUILTIN_FUNC_TYPE_RANDOM); +	FUNCBINDR(randf_range, sarray("from", "to"), Variant::BUILTIN_FUNC_TYPE_RANDOM); +	FUNCBIND(seed, sarray("base"), Variant::BUILTIN_FUNC_TYPE_RANDOM); +	FUNCBINDR(rand_from_seed, sarray("seed"), Variant::BUILTIN_FUNC_TYPE_RANDOM); + +	// Utility +	FUNCBINDVR(weakref, sarray("from"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDR(_typeof, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGS(str, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGV(print, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGV(printerr, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGV(printt, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGV(prints, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGV(printraw, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGV(push_error, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDVARARGV(push_warning, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY); + +	FUNCBINDR(var2str, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDR(str2var, sarray("string"), Variant::BUILTIN_FUNC_TYPE_UTILITY); + +	FUNCBINDR(var2bytes, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDR(bytes2var, sarray("bytes"), Variant::BUILTIN_FUNC_TYPE_UTILITY); + +	FUNCBINDR(var2bytes_with_objects, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDR(bytes2var_with_objects, sarray("bytes"), Variant::BUILTIN_FUNC_TYPE_UTILITY); + +	FUNCBINDR(hash, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY); + +	FUNCBINDR(instance_from_id, sarray("id"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDR(is_instance_id_valid, sarray("id"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +	FUNCBINDR(is_instance_valid, sarray("instance"), Variant::BUILTIN_FUNC_TYPE_UTILITY); +} +void Variant::_unregister_variant_builtin_funcs() { +	builtin_function_table.clear(); +	builtin_function_name_table.clear(); +} + +void Variant::call_builtin_func(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; +		r_error.argument = 0; +		r_error.expected = 0; +		return; +	} + +	if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount)) { +		r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; +		r_error.argument = 0; +		r_error.expected = bfi->argcount; +		return; +	} + +	if (unlikely(!bfi->is_vararg && p_argcount > bfi->argcount)) { +		r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; +		r_error.argument = 0; +		r_error.expected = bfi->argcount; +		return; +	} + +	bfi->call_builtin(r_ret, p_args, p_argcount, r_error); +} + +bool Variant::has_builtin_func(const StringName &p_name) { +	return builtin_function_table.has(p_name); +} + +Variant::BuiltinFunctionValidatedCall Variant::get_builtin_validated_caller(const StringName &p_name) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return nullptr; +	} + +	return bfi->validated_call_builtin; +} +Variant::BuiltinFunctionPTRCall Variant::get_builtin_ptr_caller(const StringName &p_name) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return nullptr; +	} + +	return bfi->ptr_call_builtin; +} + +Variant::BuiltInFunctionType Variant::get_builtin_func_type(const StringName &p_name) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return Variant::BUILTIN_FUNC_TYPE_MATH; +	} + +	return bfi->type; +} + +int Variant::get_builtin_func_argument_count(const StringName &p_name) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return 0; +	} + +	return bfi->argcount; +} +Variant::Type Variant::get_builtin_func_argument_type(const StringName &p_name, int p_arg) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return Variant::NIL; +	} + +	return bfi->get_arg_type(p_arg); +} +String Variant::get_builtin_func_argument_name(const StringName &p_name, int p_arg) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return String(); +	} +	ERR_FAIL_COND_V(bfi->is_vararg, String()); +	ERR_FAIL_INDEX_V(p_arg, bfi->argnames.size(), String()); +	return bfi->argnames[p_arg]; +} +bool Variant::has_builtin_func_return_value(const StringName &p_name) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return false; +	} +	return bfi->returns_value; +} +Variant::Type Variant::get_builtin_func_return_type(const StringName &p_name) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return Variant::NIL; +	} + +	return bfi->return_type; +} +bool Variant::is_builtin_func_vararg(const StringName &p_name) { +	const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name); +	if (!bfi) { +		return false; +	} + +	return bfi->is_vararg; +} + +void Variant::get_builtin_function_list(List<StringName> *r_functions) { +	for (List<StringName>::Element *E = builtin_function_name_table.front(); E; E = E->next()) { +		r_functions->push_back(E->get()); +	} +} diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 06bf61720a..39290f2b04 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -38,26 +38,6 @@  #include "core/os/os.h"  #include "core/templates/oa_hash_map.h" -_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) { -} - -_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) { -	arr.push_back(p_str); -} - -template <class... P> -_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) { -	arr.push_back(p_str); -	sarray_add_str(arr, p_args...); -} - -template <class... P> -_FORCE_INLINE_ Vector<String> sarray(P... p_args) { -	Vector<String> arr; -	sarray_add_str(arr, p_args...); -	return arr; -} -  typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);  typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args); diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp index b777323e82..01f5b7df59 100644 --- a/core/variant/variant_construct.cpp +++ b/core/variant/variant_construct.cpp @@ -39,26 +39,6 @@  #include "core/templates/local_vector.h"  #include "core/templates/oa_hash_map.h" -_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) { -} - -_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) { -	arr.push_back(p_str); -} - -template <class... P> -_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) { -	arr.push_back(p_str); -	sarray_add_str(arr, p_args...); -} - -template <class... P> -_FORCE_INLINE_ Vector<String> sarray(P... p_args) { -	Vector<String> arr; -	sarray_add_str(arr, p_args...); -	return arr; -} -  template <class T, class... P>  class VariantConstructor {  	template <size_t... Is> diff --git a/editor/doc_data.cpp b/editor/doc_data.cpp index ae31f68587..78c601d4bc 100644 --- a/editor/doc_data.cpp +++ b/editor/doc_data.cpp @@ -736,6 +736,43 @@ void DocData::generate(bool p_basic_types) {  			}  			c.properties.push_back(pd);  		} + +		List<StringName> builtin_funcs; +		Variant::get_builtin_function_list(&builtin_funcs); +		builtin_funcs.sort_custom<StringName::AlphCompare>(); +		for (List<StringName>::Element *E = builtin_funcs.front(); E; E = E->next()) { +			MethodDoc md; +			md.name = E->get(); +			//return +			if (Variant::has_builtin_func_return_value(E->get())) { +				PropertyInfo pi; +				pi.type = Variant::get_builtin_func_return_type(E->get()); +				if (pi.type == Variant::NIL) { +					pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT; +				} +				DocData::ArgumentDoc ad; +				argument_doc_from_arginfo(ad, pi); +				md.return_type = ad.type; +			} + +			if (Variant::is_builtin_func_vararg(E->get())) { +				md.qualifiers = "vararg"; +			} else { +				for (int i = 0; i < Variant::get_builtin_func_argument_count(E->get()); i++) { +					PropertyInfo pi; +					pi.type = Variant::get_builtin_func_argument_type(E->get(), i); +					pi.name = Variant::get_builtin_func_argument_name(E->get(), i); +					if (pi.type == Variant::NIL) { +						pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT; +					} +					DocData::ArgumentDoc ad; +					argument_doc_from_arginfo(ad, pi); +					md.arguments.push_back(ad); +				} +			} + +			c.methods.push_back(md); +		}  	}  	// Built-in script reference.  |