diff options
Diffstat (limited to 'core/variant/variant.cpp')
-rw-r--r-- | core/variant/variant.cpp | 355 |
1 files changed, 130 insertions, 225 deletions
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 0dbeb6e4cb..e69bd88413 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 */ @@ -38,8 +38,6 @@ #include "core/math/math_funcs.h" #include "core/string/print_string.h" #include "core/variant/variant_parser.h" -#include "scene/gui/control.h" -#include "scene/main/node.h" String Variant::get_type_name(Variant::Type p_type) { switch (p_type) { @@ -186,7 +184,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { if (p_type_from == p_type_to) { return true; } - if (p_type_to == NIL && p_type_from != NIL) { //nil can convert to anything + if (p_type_to == NIL) { //nil can convert to anything return true; } @@ -313,7 +311,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { case BASIS: { static const Type valid[] = { QUATERNION, - VECTOR3, NIL }; @@ -493,7 +490,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type if (p_type_from == p_type_to) { return true; } - if (p_type_to == NIL && p_type_from != NIL) { //nil can convert to anything + if (p_type_to == NIL) { //nil can convert to anything return true; } @@ -620,7 +617,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type case BASIS: { static const Type valid[] = { QUATERNION, - VECTOR3, NIL }; @@ -786,16 +782,11 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } bool Variant::operator==(const Variant &p_variant) const { - if (type != p_variant.type) { //evaluation of operator== needs to be more strict - return false; - } - bool v; - Variant r; - evaluate(OP_EQUAL, *this, p_variant, r, v); - return r; + return hash_compare(p_variant); } bool Variant::operator!=(const Variant &p_variant) const { + // Don't use `!hash_compare(p_variant)` given it makes use of OP_EQUAL if (type != p_variant.type) { //evaluation of operator== needs to be more strict return true; } @@ -1032,6 +1023,13 @@ bool Variant::is_null() const { } } +bool Variant::initialize_ref(Object *p_object) { + RefCounted *ref_counted = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_object)); + if (!ref_counted->init_ref()) { + return false; + } + return true; +} void Variant::reference(const Variant &p_variant) { switch (type) { case NIL: @@ -1619,12 +1617,45 @@ struct _VariantStrPair { }; Variant::operator String() const { - List<const void *> stack; + return stringify(0); +} + +String stringify_variant_clean(const Variant p_variant, int recursion_count) { + String s = p_variant.stringify(recursion_count); + + // Wrap strings in quotes to avoid ambiguity. + switch (p_variant.get_type()) { + case Variant::STRING: { + s = s.c_escape().quote(); + } break; + case Variant::STRING_NAME: { + s = "&" + s.c_escape().quote(); + } break; + case Variant::NODE_PATH: { + s = "^" + s.c_escape().quote(); + } break; + default: { + } break; + } + + return s; +} + +template <class T> +String stringify_vector(const T &vec, int recursion_count) { + String str("["); + for (int i = 0; i < vec.size(); i++) { + if (i > 0) { + str += ", "; + } - return stringify(stack); + str += stringify_variant_clean(vec[i], recursion_count); + } + str += "]"; + return str; } -String Variant::stringify(List<const void *> &stack) const { +String Variant::stringify(int recursion_count) const { switch (type) { case NIL: return "null"; @@ -1668,29 +1699,26 @@ String Variant::stringify(List<const void *> &stack) const { return operator Color(); case DICTIONARY: { const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem); - if (stack.find(d.id())) { + if (recursion_count > MAX_RECURSION) { + ERR_PRINT("Max recursion reached"); return "{...}"; } - stack.push_back(d.id()); - - //const String *K=nullptr; String str("{"); List<Variant> keys; d.get_key_list(&keys); Vector<_VariantStrPair> pairs; - for (const Variant &E : keys) { + recursion_count++; + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { _VariantStrPair sp; - sp.key = E.stringify(stack); - sp.value = d[E].stringify(stack); + sp.key = stringify_variant_clean(E->get(), recursion_count); + sp.value = stringify_variant_clean(d[E->get()], recursion_count); pairs.push_back(sp); } - pairs.sort(); - for (int i = 0; i < pairs.size(); i++) { if (i > 0) { str += ", "; @@ -1699,112 +1727,43 @@ String Variant::stringify(List<const void *> &stack) const { } str += "}"; - stack.erase(d.id()); return str; } break; case PACKED_VECTOR2_ARRAY: { - Vector<Vector2> vec = operator Vector<Vector2>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + Variant(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<Vector2>(), recursion_count); } break; case PACKED_VECTOR3_ARRAY: { - Vector<Vector3> vec = operator Vector<Vector3>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + Variant(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<Vector3>(), recursion_count); + } break; + case PACKED_COLOR_ARRAY: { + return stringify_vector(operator Vector<Color>(), recursion_count); } break; case PACKED_STRING_ARRAY: { - Vector<String> vec = operator Vector<String>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + vec[i]; - } - str += "]"; - return str; + return stringify_vector(operator Vector<String>(), recursion_count); + } break; + case PACKED_BYTE_ARRAY: { + return stringify_vector(operator Vector<uint8_t>(), recursion_count); } break; case PACKED_INT32_ARRAY: { - Vector<int32_t> vec = operator Vector<int32_t>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + itos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<int32_t>(), recursion_count); } break; case PACKED_INT64_ARRAY: { - Vector<int64_t> vec = operator Vector<int64_t>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + itos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<int64_t>(), recursion_count); } break; case PACKED_FLOAT32_ARRAY: { - Vector<float> vec = operator Vector<float>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + rtos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<float>(), recursion_count); } break; case PACKED_FLOAT64_ARRAY: { - Vector<double> vec = operator Vector<double>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + rtos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<double>(), recursion_count); } break; case ARRAY: { Array arr = operator Array(); - if (stack.find(arr.id())) { + if (recursion_count > MAX_RECURSION) { + ERR_PRINT("Max recursion reached"); return "[...]"; } - stack.push_back(arr.id()); - String str("["); - for (int i = 0; i < arr.size(); i++) { - if (i) { - str += ", "; - } - - str += arr[i].stringify(stack); - } - - str += "]"; - stack.erase(arr.id()); - return str; + return stringify_vector(arr, recursion_count); } break; case OBJECT: { @@ -1941,8 +1900,6 @@ Variant::operator Basis() const { return *_data._basis; } else if (type == QUATERNION) { return *reinterpret_cast<const Quaternion *>(_data._mem); - } else if (type == VECTOR3) { - return Basis(*reinterpret_cast<const Vector3 *>(_data._mem)); } else if (type == TRANSFORM3D) { // unexposed in Variant::can_convert? return _data._transform3d->basis; } else { @@ -1972,12 +1929,12 @@ Variant::operator Transform3D() const { } else if (type == TRANSFORM2D) { const Transform2D &t = *_data._transform2d; Transform3D m; - m.basis.elements[0][0] = t.elements[0][0]; - m.basis.elements[1][0] = t.elements[0][1]; - m.basis.elements[0][1] = t.elements[1][0]; - m.basis.elements[1][1] = t.elements[1][1]; - m.origin[0] = t.elements[2][0]; - m.origin[1] = t.elements[2][1]; + m.basis.rows[0][0] = t.columns[0][0]; + m.basis.rows[1][0] = t.columns[0][1]; + m.basis.rows[0][1] = t.columns[1][0]; + m.basis.rows[1][1] = t.columns[1][1]; + m.origin[0] = t.columns[2][0]; + m.origin[1] = t.columns[2][1]; return m; } else { return Transform3D(); @@ -1990,12 +1947,12 @@ Variant::operator Transform2D() const { } else if (type == TRANSFORM3D) { const Transform3D &t = *_data._transform3d; Transform2D m; - m.elements[0][0] = t.basis.elements[0][0]; - m.elements[0][1] = t.basis.elements[1][0]; - m.elements[1][0] = t.basis.elements[0][1]; - m.elements[1][1] = t.basis.elements[1][1]; - m.elements[2][0] = t.origin[0]; - m.elements[2][1] = t.origin[1]; + m.columns[0][0] = t.basis.rows[0][0]; + m.columns[0][1] = t.basis.rows[1][0]; + m.columns[1][0] = t.basis.rows[0][1]; + m.columns[1][1] = t.basis.rows[1][1]; + m.columns[2][0] = t.origin[0]; + m.columns[2][1] = t.origin[1]; return m; } else { return Transform2D(); @@ -2036,7 +1993,7 @@ Variant::operator ::RID() const { } #endif Callable::CallError ce; - Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce); + Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce); if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::RID) { return ret; } @@ -2073,22 +2030,6 @@ Object *Variant::get_validated_object() const { } } -Variant::operator Node *() const { - if (type == OBJECT) { - return Object::cast_to<Node>(_get_obj().obj); - } else { - return nullptr; - } -} - -Variant::operator Control *() const { - if (type == OBJECT) { - return Object::cast_to<Control>(_get_obj().obj); - } else { - return nullptr; - } -} - Variant::operator Dictionary() const { if (type == DICTIONARY) { return *reinterpret_cast<const Dictionary *>(_data._mem); @@ -2824,6 +2765,10 @@ Variant::Variant(const Variant &p_variant) { } uint32_t Variant::hash() const { + return recursive_hash(0); +} + +uint32_t Variant::recursive_hash(int recursion_count) const { switch (type) { case NIL: { return 0; @@ -2866,7 +2811,7 @@ uint32_t Variant::hash() const { uint32_t hash = 5831; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { - hash = hash_djb2_one_float(_data._transform2d->elements[i][j], hash); + hash = hash_djb2_one_float(_data._transform2d->columns[i][j], hash); } } @@ -2910,7 +2855,7 @@ uint32_t Variant::hash() const { uint32_t hash = 5831; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - hash = hash_djb2_one_float(_data._basis->elements[i][j], hash); + hash = hash_djb2_one_float(_data._basis->rows[i][j], hash); } } @@ -2921,7 +2866,7 @@ uint32_t Variant::hash() const { uint32_t hash = 5831; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - hash = hash_djb2_one_float(_data._transform3d->basis.elements[i][j], hash); + hash = hash_djb2_one_float(_data._transform3d->basis.rows[i][j], hash); } hash = hash_djb2_one_float(_data._transform3d->origin[i], hash); } @@ -2951,7 +2896,7 @@ uint32_t Variant::hash() const { return reinterpret_cast<const NodePath *>(_data._mem)->hash(); } break; case DICTIONARY: { - return reinterpret_cast<const Dictionary *>(_data._mem)->hash(); + return reinterpret_cast<const Dictionary *>(_data._mem)->recursive_hash(recursion_count); } break; case CALLABLE: { @@ -2965,7 +2910,7 @@ uint32_t Variant::hash() const { } break; case ARRAY: { const Array &arr = *reinterpret_cast<const Array *>(_data._mem); - return arr.hash(); + return arr.recursive_hash(recursion_count); } break; case PACKED_BYTE_ARRAY: { @@ -3139,16 +3084,24 @@ uint32_t Variant::hash() const { \ return true -bool Variant::hash_compare(const Variant &p_variant) const { +bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const { if (type != p_variant.type) { return false; } switch (type) { + case INT: { + return _data._int == p_variant._data._int; + } break; + case FLOAT: { return hash_compare_scalar(_data._float, p_variant._data._float); } break; + case STRING: { + return *reinterpret_cast<const String *>(_data._mem) == *reinterpret_cast<const String *>(p_variant._data._mem); + } break; + case VECTOR2: { const Vector2 *l = reinterpret_cast<const Vector2 *>(_data._mem); const Vector2 *r = reinterpret_cast<const Vector2 *>(p_variant._data._mem); @@ -3166,7 +3119,7 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Rect2 *r = reinterpret_cast<const Rect2 *>(p_variant._data._mem); return (hash_compare_vector2(l->position, r->position)) && - (hash_compare_vector2(l->size, r->size)); + (hash_compare_vector2(l->size, r->size)); } break; case RECT2I: { const Rect2i *l = reinterpret_cast<const Rect2i *>(_data._mem); @@ -3180,7 +3133,7 @@ bool Variant::hash_compare(const Variant &p_variant) const { Transform2D *r = p_variant._data._transform2d; for (int i = 0; i < 3; i++) { - if (!(hash_compare_vector2(l->elements[i], r->elements[i]))) { + if (!(hash_compare_vector2(l->columns[i], r->columns[i]))) { return false; } } @@ -3206,7 +3159,7 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Plane *r = reinterpret_cast<const Plane *>(p_variant._data._mem); return (hash_compare_vector3(l->normal, r->normal)) && - (hash_compare_scalar(l->d, r->d)); + (hash_compare_scalar(l->d, r->d)); } break; case AABB: { @@ -3230,7 +3183,7 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Basis *r = p_variant._data._basis; for (int i = 0; i < 3; i++) { - if (!(hash_compare_vector3(l->elements[i], r->elements[i]))) { + if (!(hash_compare_vector3(l->rows[i], r->rows[i]))) { return false; } } @@ -3243,7 +3196,7 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Transform3D *r = p_variant._data._transform3d; for (int i = 0; i < 3; i++) { - if (!(hash_compare_vector3(l->basis.elements[i], r->basis.elements[i]))) { + if (!(hash_compare_vector3(l->basis.rows[i], r->basis.rows[i]))) { return false; } } @@ -3262,14 +3215,19 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Array &l = *(reinterpret_cast<const Array *>(_data._mem)); const Array &r = *(reinterpret_cast<const Array *>(p_variant._data._mem)); - if (l.size() != r.size()) { + if (!l.recursive_equal(r, recursion_count + 1)) { return false; } - for (int i = 0; i < l.size(); ++i) { - if (!l[i].hash_compare(r[i])) { - return false; - } + return true; + } break; + + case DICTIONARY: { + const Dictionary &l = *(reinterpret_cast<const Dictionary *>(_data._mem)); + const Dictionary &r = *(reinterpret_cast<const Dictionary *>(p_variant._data._mem)); + + if (!l.recursive_equal(r, recursion_count + 1)) { + return false; } return true; @@ -3306,7 +3264,7 @@ bool Variant::hash_compare(const Variant &p_variant) const { return false; } -bool Variant::is_ref() const { +bool Variant::is_ref_counted() const { return type == OBJECT && _get_obj().id.is_ref_counted(); } @@ -3372,21 +3330,7 @@ bool Variant::is_shared() const { return false; } -Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; - int argc = 0; - for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) { - break; - } - argc++; - } - - Callable::CallError error; - - Variant ret; - call(p_method, argptr, argc, ret, error); - +void Variant::_variant_call_error(const String &p_method, Callable::CallError &error) { switch (error.error) { case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { String err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'."; @@ -3404,8 +3348,6 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) { default: { } } - - return ret; } void Variant::construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct, void *p_construct_ud) { @@ -3420,27 +3362,7 @@ String Variant::get_construct_string() const { } 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; + return get_call_error_text(nullptr, p_method, p_argptrs, p_argcount, ce); } String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) { @@ -3465,37 +3387,20 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method, return "Call OK"; } - String class_name = p_base->get_class(); - Ref<Script> script = p_base->get_script(); - if (script.is_valid() && script->get_path().is_resource_file()) { - class_name += "(" + script->get_path().get_file() + ")"; + String base_text; + if (p_base) { + base_text = p_base->get_class(); + Ref<Resource> script = p_base->get_script(); + if (script.is_valid() && script->get_path().is_resource_file()) { + base_text += "(" + script->get_path().get_file() + ")"; + } + base_text += "::"; } - return "'" + class_name + "::" + String(p_method) + "': " + err_text; + return "'" + base_text + String(p_method) + "': " + err_text; } String Variant::get_callable_error_text(const Callable &p_callable, 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_callable) + " : " + err_text; + return get_call_error_text(p_callable.get_object(), p_callable.get_method(), p_argptrs, p_argcount, ce); } String vformat(const String &p_text, const Variant &p1, const Variant &p2, const Variant &p3, const Variant &p4, const Variant &p5) { |