From 6f7eccc75813c68b2d80cc5f62d0688820e7a068 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Wed, 14 Dec 2022 15:16:43 -0600 Subject: [PATCH] Add a type conversion method to Variant Utility and expose to scripting --- core/variant/variant_utility.cpp | 85 +++++++++++++++++++ doc/classes/@GlobalScope.xml | 17 ++++ modules/gdscript/doc_classes/@GDScript.xml | 3 +- .../gdscript/gdscript_utility_functions.cpp | 4 + 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index b51df89becdf..51ea17e2d207 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -752,6 +752,90 @@ int64_t VariantUtilityFunctions::_typeof(const Variant &obj) { return obj.get_type(); } +Variant VariantUtilityFunctions::type_convert(const Variant &p_variant, const Variant::Type p_type) { + switch (p_type) { + case Variant::Type::NIL: + return Variant(); + case Variant::Type::BOOL: + return p_variant.operator bool(); + case Variant::Type::INT: + return p_variant.operator int64_t(); + case Variant::Type::FLOAT: + return p_variant.operator double(); + case Variant::Type::STRING: + return p_variant.operator String(); + case Variant::Type::VECTOR2: + return p_variant.operator Vector2(); + case Variant::Type::VECTOR2I: + return p_variant.operator Vector2i(); + case Variant::Type::RECT2: + return p_variant.operator Rect2(); + case Variant::Type::RECT2I: + return p_variant.operator Rect2i(); + case Variant::Type::VECTOR3: + return p_variant.operator Vector3(); + case Variant::Type::VECTOR3I: + return p_variant.operator Vector3i(); + case Variant::Type::TRANSFORM2D: + return p_variant.operator Transform2D(); + case Variant::Type::VECTOR4: + return p_variant.operator Vector4(); + case Variant::Type::VECTOR4I: + return p_variant.operator Vector4i(); + case Variant::Type::PLANE: + return p_variant.operator Plane(); + case Variant::Type::QUATERNION: + return p_variant.operator Quaternion(); + case Variant::Type::AABB: + return p_variant.operator ::AABB(); + case Variant::Type::BASIS: + return p_variant.operator Basis(); + case Variant::Type::TRANSFORM3D: + return p_variant.operator Transform3D(); + case Variant::Type::PROJECTION: + return p_variant.operator Projection(); + case Variant::Type::COLOR: + return p_variant.operator Color(); + case Variant::Type::STRING_NAME: + return p_variant.operator StringName(); + case Variant::Type::NODE_PATH: + return p_variant.operator NodePath(); + case Variant::Type::RID: + return p_variant.operator ::RID(); + case Variant::Type::OBJECT: + return p_variant.operator Object *(); + case Variant::Type::CALLABLE: + return p_variant.operator Callable(); + case Variant::Type::SIGNAL: + return p_variant.operator Signal(); + case Variant::Type::DICTIONARY: + return p_variant.operator Dictionary(); + case Variant::Type::ARRAY: + return p_variant.operator Array(); + case Variant::Type::PACKED_BYTE_ARRAY: + return p_variant.operator PackedByteArray(); + case Variant::Type::PACKED_INT32_ARRAY: + return p_variant.operator PackedInt32Array(); + case Variant::Type::PACKED_INT64_ARRAY: + return p_variant.operator PackedInt64Array(); + case Variant::Type::PACKED_FLOAT32_ARRAY: + return p_variant.operator PackedFloat32Array(); + case Variant::Type::PACKED_FLOAT64_ARRAY: + return p_variant.operator PackedFloat64Array(); + case Variant::Type::PACKED_STRING_ARRAY: + return p_variant.operator PackedStringArray(); + case Variant::Type::PACKED_VECTOR2_ARRAY: + return p_variant.operator PackedVector2Array(); + case Variant::Type::PACKED_VECTOR3_ARRAY: + return p_variant.operator PackedVector3Array(); + case Variant::Type::PACKED_COLOR_ARRAY: + return p_variant.operator PackedColorArray(); + case Variant::Type::VARIANT_MAX: + ERR_PRINT("Invalid type argument to type_convert(), use the TYPE_* constants. Returning the unconverted Variant."); + } + return p_variant; +} + String VariantUtilityFunctions::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; @@ -1615,6 +1699,7 @@ void Variant::_register_variant_utility_functions() { FUNCBINDVR(weakref, sarray("obj"), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDR(_typeof, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(type_convert, sarray("variant", "type"), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGS(str, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDR(error_string, sarray("error"), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(print, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index fa3f6e434e23..3173e46be8d5 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1364,6 +1364,23 @@ [/codeblock] + + + + + + Converts the given [param variant] to the given [param type], using the [enum Variant.Type] values. This method is generous with how it handles types, it can automatically convert between array types, convert numeric [String]s to [int], and converting most things to [String]. + If the type conversion cannot be done, this method will return the default value for that type, for example converting [Rect2] to [Vector2] will always return [code]Vector2.ZERO[/code]. This method will never show error messages as long as [param type] is a valid Variant type. + The returned value is a [Variant], but the data inside and the [enum Variant.Type] will be the same as the requested type. + [codeblock] + type_convert("Hi!", TYPE_INT) # Returns 0 + type_convert("123", TYPE_INT) # Returns 123 + type_convert(123.4, TYPE_INT) # Returns 123 + type_convert(5, TYPE_VECTOR2) # Returns (0, 0) + type_convert("Hi!", TYPE_NIL) # Returns null + [/codeblock] + + diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 4f1a256ec994..18045e323ca7 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -57,11 +57,12 @@ [/codeblock] - + + [i]Deprecated.[/i] Use [method @GlobalScope.type_convert] instead. Converts [param what] to [param type] in the best way possible. The [param type] uses the [enum Variant.Type] values. [codeblock] var a = [4, 2.5, 1.2] diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index 030950267dee..cf4342c1e2ff 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -85,6 +85,7 @@ #endif struct GDScriptUtilityFunctionsDefinitions { +#ifndef DISABLE_DEPRECATED static inline void convert(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(2); VALIDATE_ARG_INT(1); @@ -100,6 +101,7 @@ struct GDScriptUtilityFunctionsDefinitions { Variant::construct(Variant::Type(type), *r_ret, p_args, 1, r_error); } } +#endif // DISABLE_DEPRECATED static inline void type_exists(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(1); @@ -703,7 +705,9 @@ static void _register_function(const String &p_name, const MethodInfo &p_method_ PropertyInfo(Variant::NIL, m_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT) void GDScriptUtilityFunctions::register_functions() { +#ifndef DISABLE_DEPRECATED REGISTER_VARIANT_FUNC(convert, true, VARARG("what"), ARG("type", Variant::INT)); +#endif // DISABLE_DEPRECATED REGISTER_FUNC(type_exists, true, Variant::BOOL, ARG("type", Variant::STRING_NAME)); REGISTER_FUNC(_char, true, Variant::STRING, ARG("char", Variant::INT)); REGISTER_VARARG_FUNC(range, false, Variant::ARRAY);