diff options
Diffstat (limited to 'core/variant')
-rw-r--r-- | core/variant/array.cpp | 4 | ||||
-rw-r--r-- | core/variant/binder_common.h | 56 | ||||
-rw-r--r-- | core/variant/callable.cpp | 15 | ||||
-rw-r--r-- | core/variant/callable.h | 2 | ||||
-rw-r--r-- | core/variant/callable_bind.cpp | 6 | ||||
-rw-r--r-- | core/variant/container_type_validate.h | 2 | ||||
-rw-r--r-- | core/variant/dictionary.cpp | 4 | ||||
-rw-r--r-- | core/variant/method_ptrcall.h | 44 | ||||
-rw-r--r-- | core/variant/typed_array.h | 3 | ||||
-rw-r--r-- | core/variant/variant.cpp | 17 | ||||
-rw-r--r-- | core/variant/variant.h | 17 | ||||
-rw-r--r-- | core/variant/variant_call.cpp | 34 | ||||
-rw-r--r-- | core/variant/variant_internal.h | 2 | ||||
-rw-r--r-- | core/variant/variant_op.h | 4 | ||||
-rw-r--r-- | core/variant/variant_parser.cpp | 2 | ||||
-rw-r--r-- | core/variant/variant_setget.cpp | 6 | ||||
-rw-r--r-- | core/variant/variant_utility.cpp | 260 | ||||
-rw-r--r-- | core/variant/variant_utility.h | 3 |
18 files changed, 349 insertions, 132 deletions
diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 5a0ded6c01..ab0315ae34 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -52,7 +52,7 @@ public: void Array::_ref(const Array &p_from) const { ArrayPrivate *_fp = p_from._p; - ERR_FAIL_COND(!_fp); // should NOT happen. + ERR_FAIL_NULL(_fp); // Should NOT happen. if (_fp == _p) { return; // whatever it is, nothing to do here move along @@ -137,7 +137,7 @@ bool Array::recursive_equal(const Array &p_array, int recursion_count) const { } recursion_count++; for (int i = 0; i < size; i++) { - if (!a1[i].hash_compare(a2[i], recursion_count)) { + if (!a1[i].hash_compare(a2[i], recursion_count, false)) { return false; } } diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index 9f8fb7e95e..34b54f1d00 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -404,13 +404,13 @@ void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Vari #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -422,7 +422,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const V #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -433,7 +433,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const V #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -455,13 +455,13 @@ void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, con #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -473,7 +473,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -484,7 +484,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -506,7 +506,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -517,7 +517,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -539,7 +539,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -550,7 +550,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -785,13 +785,13 @@ void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Var #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -815,13 +815,13 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -833,13 +833,13 @@ void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -851,13 +851,13 @@ void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, co #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -882,7 +882,7 @@ void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -893,7 +893,7 @@ void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -928,7 +928,7 @@ void call_with_variant_args_static_helper_dv(T *p_instance, void (*p_method)(T * #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -939,7 +939,7 @@ void call_with_variant_args_static_helper_dv(T *p_instance, void (*p_method)(T * #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -961,7 +961,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -972,7 +972,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -994,7 +994,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_ #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -1005,7 +1005,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_ #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp index 630873ec2e..0b1174c873 100644 --- a/core/variant/callable.cpp +++ b/core/variant/callable.cpp @@ -47,6 +47,13 @@ void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_ret r_call_error.expected = 0; r_return_value = Variant(); } else if (is_custom()) { + if (!is_valid()) { + r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL; + r_call_error.argument = 0; + r_call_error.expected = 0; + r_return_value = Variant(); + return; + } custom->call(p_arguments, p_argcount, r_return_value, r_call_error); } else { Object *obj = ObjectDB::get_instance(ObjectID(object)); @@ -465,20 +472,20 @@ Error Signal::emit(const Variant **p_arguments, int p_argcount) const { Error Signal::connect(const Callable &p_callable, uint32_t p_flags) { Object *obj = get_object(); - ERR_FAIL_COND_V(!obj, ERR_UNCONFIGURED); + ERR_FAIL_NULL_V(obj, ERR_UNCONFIGURED); return obj->connect(name, p_callable, p_flags); } void Signal::disconnect(const Callable &p_callable) { Object *obj = get_object(); - ERR_FAIL_COND(!obj); + ERR_FAIL_NULL(obj); obj->disconnect(name, p_callable); } bool Signal::is_connected(const Callable &p_callable) const { Object *obj = get_object(); - ERR_FAIL_COND_V(!obj, false); + ERR_FAIL_NULL_V(obj, false); return obj->is_connected(name, p_callable); } @@ -500,7 +507,7 @@ Array Signal::get_connections() const { } Signal::Signal(const Object *p_object, const StringName &p_name) { - ERR_FAIL_COND_MSG(p_object == nullptr, "Object argument to Signal constructor must be non-null"); + ERR_FAIL_NULL_MSG(p_object, "Object argument to Signal constructor must be non-null."); object = p_object->get_instance_id(); name = p_name; diff --git a/core/variant/callable.h b/core/variant/callable.h index 086e5d2a00..3ae424e9bf 100644 --- a/core/variant/callable.h +++ b/core/variant/callable.h @@ -69,6 +69,8 @@ public: int expected = 0; }; + template <typename... VarArgs> + Variant call(VarArgs... p_args) const; void callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const; void call_deferredp(const Variant **p_arguments, int p_argcount) const; Variant callv(const Array &p_arguments) const; diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp index a5629d5d39..9a6380a55f 100644 --- a/core/variant/callable_bind.cpp +++ b/core/variant/callable_bind.cpp @@ -245,9 +245,8 @@ void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments, int } void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { - if (argcount > p_argcount) { + if (p_argcount < argcount) { r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_call_error.argument = 0; r_call_error.expected = argcount; return; } @@ -255,9 +254,8 @@ void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Var } Error CallableCustomUnbind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const { - if (argcount > p_argcount) { + if (p_argcount < argcount) { r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_call_error.argument = 0; r_call_error.expected = argcount; return ERR_UNCONFIGURED; } diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h index ffe1dc90a3..0a23c69cb4 100644 --- a/core/variant/container_type_validate.h +++ b/core/variant/container_type_validate.h @@ -113,7 +113,7 @@ struct ContainerTypeValidate { return true; // This is fine, it's null. } Object *object = ObjectDB::get_instance(object_id); - ERR_FAIL_COND_V_MSG(object == nullptr, false, "Attempted to " + String(p_operation) + " an invalid (previously freed?) object instance into a '" + String(where) + "."); + ERR_FAIL_NULL_V_MSG(object, false, "Attempted to " + String(p_operation) + " an invalid (previously freed?) object instance into a '" + String(where) + "."); #else Object *object = p_variant; if (object == nullptr) { diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index f019273735..141ce25fa6 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -210,7 +210,7 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c recursion_count++; for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) { HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator other_E(p_dictionary._p->variant_map.find(this_E.key)); - if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) { + if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count, false)) { return false; } } @@ -248,7 +248,7 @@ void Dictionary::merge(const Dictionary &p_dictionary, bool p_overwrite) { } void Dictionary::_unref() const { - ERR_FAIL_COND(!_p); + ERR_FAIL_NULL(_p); if (_p->refcount.unref()) { if (_p->read_only) { memdelete(_p->read_only); diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h index cbfb9cc257..79be85cae6 100644 --- a/core/variant/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -38,26 +38,26 @@ template <class T> struct PtrToArg {}; -#define MAKE_PTRARG(m_type) \ - template <> \ - struct PtrToArg<m_type> { \ - _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \ - return *reinterpret_cast<const m_type *>(p_ptr); \ - } \ - typedef m_type EncodeT; \ - _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \ - *((m_type *)p_ptr) = p_val; \ - } \ - }; \ - template <> \ - struct PtrToArg<const m_type &> { \ - _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \ - return *reinterpret_cast<const m_type *>(p_ptr); \ - } \ - typedef m_type EncodeT; \ - _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \ - *((m_type *)p_ptr) = p_val; \ - } \ +#define MAKE_PTRARG(m_type) \ + template <> \ + struct PtrToArg<m_type> { \ + _FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \ + return *reinterpret_cast<const m_type *>(p_ptr); \ + } \ + typedef m_type EncodeT; \ + _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \ + *((m_type *)p_ptr) = p_val; \ + } \ + }; \ + template <> \ + struct PtrToArg<const m_type &> { \ + _FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \ + return *reinterpret_cast<const m_type *>(p_ptr); \ + } \ + typedef m_type EncodeT; \ + _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \ + *((m_type *)p_ptr) = p_val; \ + } \ } #define MAKE_PTRARGCONV(m_type, m_conv) \ @@ -85,7 +85,7 @@ struct PtrToArg {}; #define MAKE_PTRARG_BY_REFERENCE(m_type) \ template <> \ struct PtrToArg<m_type> { \ - _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \ + _FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \ return *reinterpret_cast<const m_type *>(p_ptr); \ } \ typedef m_type EncodeT; \ @@ -95,7 +95,7 @@ struct PtrToArg {}; }; \ template <> \ struct PtrToArg<const m_type &> { \ - _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \ + _FORCE_INLINE_ static const m_type &convert(const void *p_ptr) { \ return *reinterpret_cast<const m_type *>(p_ptr); \ } \ typedef m_type EncodeT; \ diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h index 055c52aa63..037c5c7c2e 100644 --- a/core/variant/typed_array.h +++ b/core/variant/typed_array.h @@ -145,8 +145,7 @@ struct PtrToArg<TypedArray<T>> { template <class T> struct PtrToArg<const TypedArray<T> &> { typedef Array EncodeT; - _FORCE_INLINE_ static TypedArray<T> - convert(const void *p_ptr) { + _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) { return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr)); } }; diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 8a0289898d..4c0212075b 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -1291,7 +1291,13 @@ void Variant::zero() { break; default: + Type prev_type = type; this->clear(); + if (type != prev_type) { + // clear() changes type to NIL, so it needs to be restored. + Callable::CallError ce; + Variant::construct(prev_type, *this, nullptr, 0, ce); + } break; } } @@ -2117,7 +2123,7 @@ Variant::operator ::RID() const { } else if (type == OBJECT && _get_obj().obj) { #ifdef DEBUG_ENABLED if (EngineDebugger::is_active()) { - ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, ::RID(), "Invalid pointer (object was freed)."); + ERR_FAIL_NULL_V_MSG(ObjectDB::get_instance(_get_obj().id), ::RID(), "Invalid pointer (object was freed)."); } #endif Callable::CallError ce; @@ -3235,8 +3241,11 @@ uint32_t Variant::recursive_hash(int recursion_count) const { return 0; } +#define hash_compare_scalar_base(p_lhs, p_rhs, semantic_comparison) \ + (((p_lhs) == (p_rhs)) || (semantic_comparison && Math::is_nan(p_lhs) && Math::is_nan(p_rhs))) + #define hash_compare_scalar(p_lhs, p_rhs) \ - (((p_lhs) == (p_rhs)) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs))) + (hash_compare_scalar_base(p_lhs, p_rhs, true)) #define hash_compare_vector2(p_lhs, p_rhs) \ (hash_compare_scalar((p_lhs).x, (p_rhs).x) && \ @@ -3282,7 +3291,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const { \ return true -bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const { +bool Variant::hash_compare(const Variant &p_variant, int recursion_count, bool semantic_comparison) const { if (type != p_variant.type) { return false; } @@ -3293,7 +3302,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const } break; case FLOAT: { - return hash_compare_scalar(_data._float, p_variant._data._float); + return hash_compare_scalar_base(_data._float, p_variant._data._float, semantic_comparison); } break; case STRING: { diff --git a/core/variant/variant.h b/core/variant/variant.h index 04c2fe2012..21342ae6ef 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -751,7 +751,8 @@ public: uint32_t hash() const; uint32_t recursive_hash(int recursion_count) const; - bool hash_compare(const Variant &p_variant, int recursion_count = 0) const; + // By default, performs a semantic comparison. Otherwise, numeric/binary comparison (if appropriate). + bool hash_compare(const Variant &p_variant, int recursion_count = 0, bool semantic_comparison = true) const; bool identity_compare(const Variant &p_variant) const; bool booleanize() const; String stringify(int recursion_count = 0) const; @@ -833,6 +834,20 @@ String vformat(const String &p_text, const VarArgs... p_args) { } template <typename... VarArgs> +Variant Callable::call(VarArgs... p_args) const { + Variant args[sizeof...(p_args) + 1] = { p_args..., 0 }; // +1 makes sure zero sized arrays are also supported. + const Variant *argptrs[sizeof...(p_args) + 1]; + for (uint32_t i = 0; i < sizeof...(p_args); i++) { + argptrs[i] = &args[i]; + } + + Variant ret; + CallError ce; + callp(sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), ret, ce); + return ret; +} + +template <typename... VarArgs> Callable Callable::bind(VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. const Variant *argptrs[sizeof...(p_args) + 1]; diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 5a405a7080..f041d2c95e 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1037,9 +1037,7 @@ struct _VariantCall { static void func_Callable_rpc_id(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { if (p_argcount == 0) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; r_error.expected = 1; - } else if (p_args[0]->get_type() != Variant::INT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -1259,28 +1257,28 @@ bool Variant::has_builtin_method(Variant::Type p_type, const StringName &p_metho Variant::ValidatedBuiltInMethod Variant::get_validated_builtin_method(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, nullptr); + ERR_FAIL_NULL_V(method, nullptr); return method->validated_call; } Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, nullptr); + ERR_FAIL_NULL_V(method, nullptr); return method->ptrcall; } int Variant::get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, 0); + ERR_FAIL_NULL_V(method, 0); return method->argument_count; } Variant::Type Variant::get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, Variant::NIL); + ERR_FAIL_NULL_V(method, Variant::NIL); ERR_FAIL_INDEX_V(p_argument, method->argument_count, Variant::NIL); return method->get_argument_type(p_argument); } @@ -1288,7 +1286,7 @@ Variant::Type Variant::get_builtin_method_argument_type(Variant::Type p_type, co String Variant::get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String()); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, String()); + ERR_FAIL_NULL_V(method, String()); #ifdef DEBUG_METHODS_ENABLED ERR_FAIL_INDEX_V(p_argument, method->argument_count, String()); return method->argument_names[p_argument]; @@ -1300,14 +1298,14 @@ String Variant::get_builtin_method_argument_name(Variant::Type p_type, const Str Vector<Variant> Variant::get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Vector<Variant>()); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, Vector<Variant>()); + ERR_FAIL_NULL_V(method, Vector<Variant>()); return method->default_arguments; } bool Variant::has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, false); + ERR_FAIL_NULL_V(method, false); return method->has_return_type; } @@ -1326,35 +1324,35 @@ int Variant::get_builtin_method_count(Variant::Type p_type) { Variant::Type Variant::get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, Variant::NIL); + ERR_FAIL_NULL_V(method, Variant::NIL); return method->return_type; } bool Variant::is_builtin_method_const(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, false); + ERR_FAIL_NULL_V(method, false); return method->is_const; } bool Variant::is_builtin_method_static(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, false); + ERR_FAIL_NULL_V(method, false); return method->is_static; } bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, false); + ERR_FAIL_NULL_V(method, false); return method->is_vararg; } uint32_t Variant::get_builtin_method_hash(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); - ERR_FAIL_COND_V(!method, 0); + ERR_FAIL_NULL_V(method, 0); uint32_t hash = hash_murmur3_one_32(method->is_const); hash = hash_murmur3_one_32(method->is_static, hash); hash = hash_murmur3_one_32(method->is_vararg, hash); @@ -2076,6 +2074,7 @@ static void _register_variant_builtin_methods() { bind_method(Transform2D, basis_xform, sarray("v"), varray()); bind_method(Transform2D, basis_xform_inv, sarray("v"), varray()); bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray()); + bind_method(Transform2D, is_conformal, sarray(), varray()); bind_method(Transform2D, is_equal_approx, sarray("xform"), varray()); bind_method(Transform2D, is_finite, sarray(), varray()); // Do not bind functions like set_rotation, set_scale, set_skew, etc because this type is immutable and can't be modified. @@ -2095,6 +2094,7 @@ static void _register_variant_builtin_methods() { bind_method(Basis, tdoty, sarray("with"), varray()); bind_method(Basis, tdotz, sarray("with"), varray()); bind_method(Basis, slerp, sarray("to", "weight"), varray()); + bind_method(Basis, is_conformal, sarray(), varray()); bind_method(Basis, is_equal_approx, sarray("b"), varray()); bind_method(Basis, is_finite, sarray(), varray()); bind_method(Basis, get_rotation_quaternion, sarray(), varray()); @@ -2569,9 +2569,13 @@ static void _register_variant_builtin_methods() { _VariantCall::add_variant_constant(Variant::VECTOR4I, "ZERO", Vector4i(0, 0, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR4I, "ONE", Vector4i(1, 1, 1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR4I, "MIN", Vector4i(INT32_MIN, INT32_MIN, INT32_MIN, INT32_MIN)); + _VariantCall::add_variant_constant(Variant::VECTOR4I, "MAX", Vector4i(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "MIN", Vector3i(INT32_MIN, INT32_MIN, INT32_MIN)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "MAX", Vector3i(INT32_MAX, INT32_MAX, INT32_MAX)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "RIGHT", Vector3i(1, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "UP", Vector3i(0, 1, 0)); @@ -2601,6 +2605,8 @@ static void _register_variant_builtin_methods() { _VariantCall::add_variant_constant(Variant::VECTOR2I, "ZERO", Vector2i(0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR2I, "ONE", Vector2i(1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR2I, "MIN", Vector2i(INT32_MIN, INT32_MIN)); + _VariantCall::add_variant_constant(Variant::VECTOR2I, "MAX", Vector2i(INT32_MAX, INT32_MAX)); _VariantCall::add_variant_constant(Variant::VECTOR2I, "LEFT", Vector2i(-1, 0)); _VariantCall::add_variant_constant(Variant::VECTOR2I, "RIGHT", Vector2i(1, 0)); _VariantCall::add_variant_constant(Variant::VECTOR2I, "UP", Vector2i(0, -1)); diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index 782053b613..116210e8de 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -418,7 +418,7 @@ public: case Variant::PACKED_COLOR_ARRAY: return get_color_array(v); case Variant::OBJECT: - return v->_get_obj().obj; + return get_object(v); case Variant::VARIANT_MAX: ERR_FAIL_V(nullptr); } diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h index fc1f7828a2..9e6367ab6d 100644 --- a/core/variant/variant_op.h +++ b/core/variant/variant_op.h @@ -1493,7 +1493,7 @@ public: } static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { Object *l = right->get_validated_object(); - ERR_FAIL_COND(l == nullptr); + ERR_FAIL_NULL(l); const String &a = *VariantGetInternalPtr<String>::get_ptr(left); bool valid; @@ -1527,7 +1527,7 @@ public: } static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { Object *l = right->get_validated_object(); - ERR_FAIL_COND(l == nullptr); + ERR_FAIL_NULL(l); const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(left); bool valid; diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index fea1622222..86e7654090 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -1075,7 +1075,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } - static HashMap<StringName, Variant::Type> builtin_types; + static HashMap<String, Variant::Type> builtin_types; if (builtin_types.is_empty()) { for (int i = 1; i < Variant::VARIANT_MAX; i++) { builtin_types[Variant::get_type_name((Variant::Type)i)] = (Variant::Type)i; diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index 30fb5d0e9f..05f7abf32c 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -318,7 +318,7 @@ Variant Variant::get_named(const StringName &p_member, bool &r_valid) const { #ifdef DEBUG_ENABLED #define NULL_TEST(m_key) \ - ERR_FAIL_COND(!m_key) + ERR_FAIL_NULL(m_key) #else @@ -1068,7 +1068,7 @@ struct VariantKeyedSetGetObject { } static uint32_t ptr_has(const void *base, const void *key) { const Object *obj = PtrToArg<Object *>::convert(base); - ERR_FAIL_COND_V(!obj, false); + ERR_FAIL_NULL_V(obj, false); bool valid; obj->getvar(PtrToArg<Variant>::convert(key), &valid); return valid; @@ -1245,7 +1245,7 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { } } else if (type == OBJECT) { Object *obj = get_validated_object(); - ERR_FAIL_COND(!obj); + ERR_FAIL_NULL(obj); obj->get_property_list(p_list); } else { diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index b51df89bec..cc48394b64 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -121,16 +121,27 @@ Variant VariantUtilityFunctions::floor(Variant x, Callable::CallError &r_error) case Variant::VECTOR2: { return VariantInternalAccessor<Vector2>::get(&x).floor(); } break; + case Variant::VECTOR2I: { + return VariantInternalAccessor<Vector2i>::get(&x); + } break; case Variant::VECTOR3: { return VariantInternalAccessor<Vector3>::get(&x).floor(); } break; + case Variant::VECTOR3I: { + return VariantInternalAccessor<Vector3i>::get(&x); + } break; case Variant::VECTOR4: { return VariantInternalAccessor<Vector4>::get(&x).floor(); } break; + case Variant::VECTOR4I: { + return VariantInternalAccessor<Vector4i>::get(&x); + } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return Variant(); - } + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)"; + } break; } } @@ -154,16 +165,27 @@ Variant VariantUtilityFunctions::ceil(Variant x, Callable::CallError &r_error) { case Variant::VECTOR2: { return VariantInternalAccessor<Vector2>::get(&x).ceil(); } break; + case Variant::VECTOR2I: { + return VariantInternalAccessor<Vector2i>::get(&x); + } break; case Variant::VECTOR3: { return VariantInternalAccessor<Vector3>::get(&x).ceil(); } break; + case Variant::VECTOR3I: { + return VariantInternalAccessor<Vector3i>::get(&x); + } break; case Variant::VECTOR4: { return VariantInternalAccessor<Vector4>::get(&x).ceil(); } break; + case Variant::VECTOR4I: { + return VariantInternalAccessor<Vector4i>::get(&x); + } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return Variant(); - } + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)"; + } break; } } @@ -187,16 +209,27 @@ Variant VariantUtilityFunctions::round(Variant x, Callable::CallError &r_error) case Variant::VECTOR2: { return VariantInternalAccessor<Vector2>::get(&x).round(); } break; + case Variant::VECTOR2I: { + return VariantInternalAccessor<Vector2i>::get(&x); + } break; case Variant::VECTOR3: { return VariantInternalAccessor<Vector3>::get(&x).round(); } break; + case Variant::VECTOR3I: { + return VariantInternalAccessor<Vector3i>::get(&x); + } break; case Variant::VECTOR4: { return VariantInternalAccessor<Vector4>::get(&x).round(); } break; + case Variant::VECTOR4I: { + return VariantInternalAccessor<Vector4i>::get(&x); + } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return Variant(); - } + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)"; + } break; } } @@ -236,9 +269,11 @@ Variant VariantUtilityFunctions::abs(const Variant &x, Callable::CallError &r_er return VariantInternalAccessor<Vector4i>::get(&x).abs(); } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return Variant(); - } + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)"; + } break; } } @@ -278,9 +313,11 @@ Variant VariantUtilityFunctions::sign(const Variant &x, Callable::CallError &r_e return VariantInternalAccessor<Vector4i>::get(&x).sign(); } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return Variant(); - } + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)"; + } break; } } @@ -333,13 +370,40 @@ int VariantUtilityFunctions::step_decimals(float step) { } Variant VariantUtilityFunctions::snapped(const Variant &x, const Variant &step, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; - if (x.get_type() != step.get_type() && !((x.get_type() == Variant::INT && step.get_type() == Variant::FLOAT) || (x.get_type() == Variant::FLOAT && step.get_type() == Variant::INT))) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 1; - return Variant(); + switch (x.get_type()) { + case Variant::INT: + case Variant::FLOAT: + case Variant::VECTOR2: + case Variant::VECTOR2I: + case Variant::VECTOR3: + case Variant::VECTOR3I: + case Variant::VECTOR4: + case Variant::VECTOR4I: + break; + default: + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)"; + } + + if (x.get_type() != step.get_type()) { + if (x.get_type() == Variant::INT || x.get_type() == Variant::FLOAT) { + if (step.get_type() != Variant::INT && step.get_type() != Variant::FLOAT) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + r_error.expected = Variant::NIL; + return R"(Argument "step" must be "int" or "float".)"; + } + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + r_error.expected = x.get_type(); + return Variant(); + } } + r_error.error = Callable::CallError::CALL_OK; switch (step.get_type()) { case Variant::INT: { return snappedi(x, VariantInternalAccessor<int64_t>::get(&step)); @@ -366,9 +430,8 @@ Variant VariantUtilityFunctions::snapped(const Variant &x, const Variant &step, return VariantInternalAccessor<Vector4i>::get(&x).snapped(VariantInternalAccessor<Vector4i>::get(&step)); } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return Variant(); - } + return Variant(); // Already handled. + } break; } } @@ -381,14 +444,31 @@ int64_t VariantUtilityFunctions::snappedi(double x, int64_t step) { } Variant VariantUtilityFunctions::lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; + switch (from.get_type()) { + case Variant::INT: + case Variant::FLOAT: + case Variant::VECTOR2: + case Variant::VECTOR3: + case Variant::VECTOR4: + case Variant::QUATERNION: + case Variant::BASIS: + case Variant::COLOR: + break; + default: + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return R"(Argument "from" must be "int", "float", "Vector2", "Vector3", "Vector4", "Quaternion", "Basis, or "Color".)"; + } + if (from.get_type() != to.get_type()) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = from.get_type(); r_error.argument = 1; + r_error.expected = from.get_type(); return Variant(); } + r_error.error = Callable::CallError::CALL_OK; switch (from.get_type()) { case Variant::INT: { return lerpf(VariantInternalAccessor<int64_t>::get(&from), to, weight); @@ -415,9 +495,8 @@ Variant VariantUtilityFunctions::lerp(const Variant &from, const Variant &to, do return VariantInternalAccessor<Color>::get(&from).lerp(VariantInternalAccessor<Color>::get(&to), weight); } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return Variant(); - } + return Variant(); // Already handled. + } break; } } @@ -451,6 +530,10 @@ double VariantUtilityFunctions::bezier_derivative(double p_start, double p_contr return Math::bezier_derivative(p_start, p_control_1, p_control_2, p_end, p_t); } +double VariantUtilityFunctions::angle_difference(double from, double to) { + return Math::angle_difference(from, to); +} + double VariantUtilityFunctions::lerp_angle(double from, double to, double weight) { return Math::lerp_angle(from, to, weight); } @@ -471,6 +554,10 @@ double VariantUtilityFunctions::move_toward(double from, double to, double delta return Math::move_toward(from, to, delta); } +double VariantUtilityFunctions::rotate_toward(double from, double to, double delta) { + return Math::rotate_toward(from, to, delta); +} + double VariantUtilityFunctions::deg_to_rad(double angle_deg) { return Math::deg_to_rad(angle_deg); } @@ -492,7 +579,7 @@ Variant VariantUtilityFunctions::wrap(const Variant &p_x, const Variant &p_min, if (x_type != Variant::INT && x_type != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; - r_error.expected = x_type; + r_error.expected = Variant::FLOAT; return Variant(); } @@ -558,8 +645,8 @@ Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Cal Variant::Type arg_type = p_args[i]->get_type(); if (arg_type != Variant::INT && arg_type != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = Variant::FLOAT; r_error.argument = i; + r_error.expected = Variant::FLOAT; return Variant(); } if (i == 0) { @@ -569,8 +656,8 @@ Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Cal 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; + r_error.expected = base.get_type(); return Variant(); } if (ret.booleanize()) { @@ -602,8 +689,8 @@ Variant VariantUtilityFunctions::min(const Variant **p_args, int p_argcount, Cal Variant::Type arg_type = p_args[i]->get_type(); if (arg_type != Variant::INT && arg_type != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = Variant::FLOAT; r_error.argument = i; + r_error.expected = Variant::FLOAT; return Variant(); } if (i == 0) { @@ -613,8 +700,8 @@ Variant VariantUtilityFunctions::min(const Variant **p_args, int p_argcount, Cal 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; + r_error.expected = base.get_type(); return Variant(); } if (ret.booleanize()) { @@ -642,8 +729,8 @@ Variant VariantUtilityFunctions::clamp(const Variant &x, const Variant &min, con 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; + r_error.expected = value.get_type(); return Variant(); } if (ret.booleanize()) { @@ -652,8 +739,8 @@ Variant VariantUtilityFunctions::clamp(const Variant &x, const Variant &min, con 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; + r_error.expected = value.get_type(); return Variant(); } if (ret.booleanize()) { @@ -752,10 +839,94 @@ 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; - r_error.argument = 1; + r_error.expected = 1; return String(); } String s; @@ -782,6 +953,11 @@ String VariantUtilityFunctions::error_string(Error error) { return String(error_names[error]); } +String VariantUtilityFunctions::type_string(Variant::Type p_type) { + ERR_FAIL_INDEX_V_MSG((int)p_type, (int)Variant::VARIANT_MAX, "<invalid type>", "Invalid type argument to type_string(), use the TYPE_* constants."); + return Variant::get_type_name(p_type); +} + void VariantUtilityFunctions::print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { String s; for (int i = 0; i < p_arg_count; i++) { @@ -899,7 +1075,7 @@ void VariantUtilityFunctions::printraw(const Variant **p_args, int p_arg_count, void VariantUtilityFunctions::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; + r_error.expected = 1; } String s; for (int i = 0; i < p_arg_count; i++) { @@ -919,7 +1095,7 @@ void VariantUtilityFunctions::push_error(const Variant **p_args, int p_arg_count void VariantUtilityFunctions::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; + r_error.expected = 1; } String s; for (int i = 0; i < p_arg_count; i++) { @@ -1569,12 +1745,14 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_derivative, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(angle_difference, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(remap, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(rotate_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(deg_to_rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(rad_to_deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1615,8 +1793,10 @@ 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); + FUNCBINDR(type_string, sarray("type"), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(print, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(print_rich, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(printerr, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); @@ -1664,14 +1844,12 @@ void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, co 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; } @@ -1788,7 +1966,7 @@ bool Variant::is_utility_function_vararg(const StringName &p_name) { uint32_t Variant::get_utility_function_hash(const StringName &p_name) { const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); - ERR_FAIL_COND_V(!bfi, 0); + ERR_FAIL_NULL_V(bfi, 0); uint32_t hash = hash_murmur3_one_32(bfi->is_vararg); hash = hash_murmur3_one_32(bfi->returns_value, hash); diff --git a/core/variant/variant_utility.h b/core/variant/variant_utility.h index 66883fb140..a56c84a8e9 100644 --- a/core/variant/variant_utility.h +++ b/core/variant/variant_utility.h @@ -90,11 +90,13 @@ struct VariantUtilityFunctions { double to_t, double pre_t, double post_t); static double bezier_interpolate(double p_start, double p_control_1, double p_control_2, double p_end, double p_t); static double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t); + static double angle_difference(double from, double to); static double lerp_angle(double from, double to, double weight); static double inverse_lerp(double from, double to, double weight); static double remap(double value, double istart, double istop, double ostart, double ostop); static double smoothstep(double from, double to, double val); static double move_toward(double from, double to, double delta); + static double rotate_toward(double from, double to, double delta); static double deg_to_rad(double angle_deg); static double rad_to_deg(double angle_rad); static double linear_to_db(double linear); @@ -128,6 +130,7 @@ struct VariantUtilityFunctions { static Variant type_convert(const Variant &p_variant, const Variant::Type p_type); static String str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); static String error_string(Error error); + static String type_string(Variant::Type p_type); static void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); static void print_rich(const Variant **p_args, int p_arg_count, Callable::CallError &r_error); #undef print_verbose |