summaryrefslogtreecommitdiff
path: root/core/variant
diff options
context:
space:
mode:
Diffstat (limited to 'core/variant')
-rw-r--r--core/variant/array.cpp131
-rw-r--r--core/variant/array.h10
-rw-r--r--core/variant/binder_common.h10
-rw-r--r--core/variant/callable.cpp16
-rw-r--r--core/variant/callable.h6
-rw-r--r--core/variant/callable_bind.cpp16
-rw-r--r--core/variant/callable_bind.h32
-rw-r--r--core/variant/dictionary.cpp151
-rw-r--r--core/variant/dictionary.h4
-rw-r--r--core/variant/native_ptr.h1
-rw-r--r--core/variant/type_info.h34
-rw-r--r--core/variant/variant.cpp154
-rw-r--r--core/variant/variant.h29
-rw-r--r--core/variant/variant_call.cpp97
-rw-r--r--core/variant/variant_construct.cpp12
-rw-r--r--core/variant/variant_construct.h10
-rw-r--r--core/variant/variant_op.cpp7
-rw-r--r--core/variant/variant_op.h18
-rw-r--r--core/variant/variant_parser.cpp21
-rw-r--r--core/variant/variant_parser.h18
-rw-r--r--core/variant/variant_setget.cpp162
-rw-r--r--core/variant/variant_setget.h16
-rw-r--r--core/variant/variant_utility.cpp93
23 files changed, 725 insertions, 323 deletions
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 1b39558dff..b1e142d239 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -43,7 +43,7 @@ class ArrayPrivate {
public:
SafeRefCount refcount;
Vector<Variant> array;
-
+ Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
ContainerTypeValidate typed;
};
@@ -52,6 +52,16 @@ void Array::_ref(const Array &p_from) const {
ERR_FAIL_COND(!_fp); // should NOT happen.
+ if (unlikely(_fp->read_only != nullptr)) {
+ // If p_from is a read-only array, just copy the contents to avoid further modification.
+ _unref();
+ _p = memnew(ArrayPrivate);
+ _p->refcount.init();
+ _p->array = _fp->array;
+ _p->typed = _fp->typed;
+ return;
+ }
+
if (_fp == _p) {
return; // whatever it is, nothing to do here move along
}
@@ -71,16 +81,27 @@ void Array::_unref() const {
}
if (_p->refcount.unref()) {
+ if (_p->read_only) {
+ memdelete(_p->read_only);
+ }
memdelete(_p);
}
_p = nullptr;
}
Variant &Array::operator[](int p_idx) {
+ if (unlikely(_p->read_only)) {
+ *_p->read_only = _p->array[p_idx];
+ return *_p->read_only;
+ }
return _p->array.write[p_idx];
}
const Variant &Array::operator[](int p_idx) const {
+ if (unlikely(_p->read_only)) {
+ *_p->read_only = _p->array[p_idx];
+ return *_p->read_only;
+ }
return _p->array[p_idx];
}
@@ -93,6 +114,7 @@ bool Array::is_empty() const {
}
void Array::clear() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.clear();
}
@@ -224,34 +246,43 @@ bool Array::_assign(const Array &p_array) {
}
void Array::operator=(const Array &p_array) {
+ if (this == &p_array) {
+ return;
+ }
_ref(p_array);
}
void Array::push_back(const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "push_back"));
_p->array.push_back(p_value);
}
void Array::append_array(const Array &p_array) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_array, "append_array"));
_p->array.append_array(p_array._p->array);
}
Error Array::resize(int p_new_size) {
+ ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
return _p->array.resize(p_new_size);
}
Error Array::insert(int p_pos, const Variant &p_value) {
+ ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "insert"), ERR_INVALID_PARAMETER);
return _p->array.insert(p_pos, p_value);
}
void Array::fill(const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "fill"));
_p->array.fill(p_value);
}
void Array::erase(const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "erase"));
_p->array.erase(p_value);
}
@@ -323,10 +354,12 @@ bool Array::has(const Variant &p_value) const {
}
void Array::remove_at(int p_pos) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.remove_at(p_pos);
}
void Array::set(int p_idx, const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "set"));
operator[](p_idx) = p_value;
@@ -468,6 +501,50 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const
return ret;
}
+bool Array::any(const Callable &p_callable) const {
+ const Variant *argptrs[1];
+ for (int i = 0; i < size(); i++) {
+ argptrs[0] = &get(i);
+
+ Variant result;
+ Callable::CallError ce;
+ p_callable.call(argptrs, 1, result, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+ }
+
+ if (result.operator bool()) {
+ // Return as early as possible when one of the conditions is `true`.
+ // This improves performance compared to relying on `filter(...).size() >= 1`.
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Array::all(const Callable &p_callable) const {
+ const Variant *argptrs[1];
+ for (int i = 0; i < size(); i++) {
+ argptrs[0] = &get(i);
+
+ Variant result;
+ Callable::CallError ce;
+ p_callable.call(argptrs, 1, result, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+ }
+
+ if (!(result.operator bool())) {
+ // Return as early as possible when one of the inverted conditions is `false`.
+ // This improves performance compared to relying on `filter(...).size() >= array_size().`.
+ return false;
+ }
+ }
+
+ return true;
+}
+
struct _ArrayVariantSort {
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
bool valid = false;
@@ -481,30 +558,17 @@ struct _ArrayVariantSort {
};
void Array::sort() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.sort_custom<_ArrayVariantSort>();
}
-struct _ArrayVariantSortCustom {
- Callable func;
-
- _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
- const Variant *args[2] = { &p_l, &p_r };
- Callable::CallError err;
- Variant res;
- func.call(args, 2, res, err);
- ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false,
- "Error calling sorting method: " + Variant::get_callable_error_text(func, args, 1, err));
- return res;
- }
-};
-
-void Array::sort_custom(Callable p_callable) {
- SortArray<Variant, _ArrayVariantSortCustom, true> avs;
- avs.compare.func = p_callable;
- avs.sort(_p->array.ptrw(), _p->array.size());
+void Array::sort_custom(const Callable &p_callable) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
+ _p->array.sort_custom<CallableComparator, true>(p_callable);
}
void Array::shuffle() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
const int n = _p->array.size();
if (n < 2) {
return;
@@ -524,25 +588,25 @@ int Array::bsearch(const Variant &p_value, bool p_before) {
return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
-int Array::bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before) {
+int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1);
- SearchArray<Variant, _ArrayVariantSortCustom> avs;
- avs.compare.func = p_callable;
-
- return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
+ return _p->array.bsearch_custom<CallableComparator>(p_value, p_before, p_callable);
}
void Array::reverse() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.reverse();
}
void Array::push_front(const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "push_front"));
_p->array.insert(0, p_value);
}
Variant Array::pop_back() {
+ ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) {
const int n = _p->array.size() - 1;
const Variant ret = _p->array.get(n);
@@ -553,6 +617,7 @@ Variant Array::pop_back() {
}
Variant Array::pop_front() {
+ ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) {
const Variant ret = _p->array.get(0);
_p->array.remove_at(0);
@@ -562,6 +627,7 @@ Variant Array::pop_front() {
}
Variant Array::pop_at(int p_pos) {
+ ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (_p->array.is_empty()) {
// Return `null` without printing an error to mimic `pop_back()` and `pop_front()` behavior.
return Variant();
@@ -646,6 +712,7 @@ bool Array::typed_assign(const Array &p_other) {
}
void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND_MSG(_p->array.size() > 0, "Type can only be set when array is empty.");
ERR_FAIL_COND_MSG(_p->refcount.get() > 1, "Type can only be set when array has no more than one user.");
ERR_FAIL_COND_MSG(_p->typed.type != Variant::NIL, "Type can only be set once.");
@@ -675,6 +742,22 @@ Variant Array::get_typed_script() const {
return _p->typed.script;
}
+void Array::set_read_only(bool p_enable) {
+ if (p_enable == bool(_p->read_only != nullptr)) {
+ return;
+ }
+ if (p_enable) {
+ _p->read_only = memnew(Variant);
+ } else {
+ memdelete(_p->read_only);
+ _p->read_only = nullptr;
+ }
+}
+
+bool Array::is_read_only() const {
+ return _p->read_only != nullptr;
+}
+
Array::Array(const Array &p_from) {
_p = nullptr;
_ref(p_from);
diff --git a/core/variant/array.h b/core/variant/array.h
index 72bed5932c..c007376734 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -82,10 +82,10 @@ public:
Variant back() const;
void sort();
- void sort_custom(Callable p_callable);
+ void sort_custom(const Callable &p_callable);
void shuffle();
int bsearch(const Variant &p_value, bool p_before = true);
- int bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before = true);
+ int bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before = true);
void reverse();
int find(const Variant &p_value, int p_from = 0) const;
@@ -108,6 +108,8 @@ public:
Array filter(const Callable &p_callable) const;
Array map(const Callable &p_callable) const;
Variant reduce(const Callable &p_callable, const Variant &p_accum) const;
+ bool any(const Callable &p_callable) const;
+ bool all(const Callable &p_callable) const;
bool operator<(const Array &p_array) const;
bool operator<=(const Array &p_array) const;
@@ -125,6 +127,10 @@ public:
uint32_t get_typed_builtin() const;
StringName get_typed_class_name() const;
Variant get_typed_script() const;
+
+ void set_read_only(bool p_enable);
+ bool is_read_only() const;
+
Array(const Array &p_from);
Array();
~Array();
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index b6fdb4d902..22a13b0fab 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -100,6 +100,10 @@ struct VariantCaster<const T &> {
_FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \
*(int64_t *)p_ptr = (int64_t)p_val; \
} \
+ }; \
+ template <> \
+ struct ZeroInitializer<m_enum> { \
+ static void initialize(m_enum &value) { value = (m_enum)0; } \
};
// Object enum casts must go here
@@ -182,7 +186,7 @@ struct VariantCasterAndValidate {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
- !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+ !VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = p_arg_idx;
r_error.expected = argtype;
@@ -197,7 +201,7 @@ struct VariantCasterAndValidate<T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
- !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+ !VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = p_arg_idx;
r_error.expected = argtype;
@@ -212,7 +216,7 @@ struct VariantCasterAndValidate<const T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
- !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+ !VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = p_arg_idx;
r_error.expected = argtype;
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 27792ce111..516b8f2d51 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -37,7 +37,7 @@
#include "core/object/script_language.h"
void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const {
- MessageQueue::get_singleton()->push_callable(*this, p_arguments, p_argcount);
+ MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount);
}
void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const {
@@ -59,7 +59,7 @@ void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_retu
return;
}
#endif
- r_return_value = obj->call(method, p_arguments, p_argcount, r_call_error);
+ r_return_value = obj->callp(method, p_arguments, p_argcount, r_call_error);
}
}
@@ -379,7 +379,7 @@ Error Signal::emit(const Variant **p_arguments, int p_argcount) const {
return ERR_INVALID_DATA;
}
- return obj->emit_signal(name, p_arguments, p_argcount);
+ return obj->emit_signalp(name, p_arguments, p_argcount);
}
Error Signal::connect(const Callable &p_callable, uint32_t p_flags) {
@@ -429,3 +429,13 @@ Signal::Signal(ObjectID p_object, const StringName &p_name) {
object = p_object;
name = p_name;
}
+
+bool CallableComparator::operator()(const Variant &p_l, const Variant &p_r) const {
+ const Variant *args[2] = { &p_l, &p_r };
+ Callable::CallError err;
+ Variant res;
+ func.call(args, 2, res, err);
+ ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false,
+ "Error calling compare method: " + Variant::get_callable_error_text(func, args, 1, err));
+ return res;
+}
diff --git a/core/variant/callable.h b/core/variant/callable.h
index c61870f194..6a760958d6 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -170,4 +170,10 @@ public:
Signal() {}
};
+struct CallableComparator {
+ const Callable &func;
+
+ bool operator()(const Variant &p_l, const Variant &p_r) const;
+};
+
#endif // CALLABLE_H
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 797e8afede..1a400b4360 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -40,8 +40,8 @@ String CallableCustomBind::get_as_text() const {
}
bool CallableCustomBind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomBind *a = (const CallableCustomBind *)p_a;
- const CallableCustomBind *b = (const CallableCustomBind *)p_b;
+ const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
+ const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
if (!(a->callable != b->callable)) {
return false;
@@ -55,8 +55,8 @@ bool CallableCustomBind::_equal_func(const CallableCustom *p_a, const CallableCu
}
bool CallableCustomBind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomBind *a = (const CallableCustomBind *)p_a;
- const CallableCustomBind *b = (const CallableCustomBind *)p_b;
+ const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
+ const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
if (a->callable < b->callable) {
return true;
@@ -117,8 +117,8 @@ String CallableCustomUnbind::get_as_text() const {
}
bool CallableCustomUnbind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomUnbind *a = (const CallableCustomUnbind *)p_a;
- const CallableCustomUnbind *b = (const CallableCustomUnbind *)p_b;
+ const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
+ const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
if (!(a->callable != b->callable)) {
return false;
@@ -132,8 +132,8 @@ bool CallableCustomUnbind::_equal_func(const CallableCustom *p_a, const Callable
}
bool CallableCustomUnbind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomUnbind *a = (const CallableCustomUnbind *)p_a;
- const CallableCustomUnbind *b = (const CallableCustomUnbind *)p_b;
+ const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
+ const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
if (a->callable < b->callable) {
return true;
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index 4f79a29629..a5c830e109 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -43,14 +43,14 @@ class CallableCustomBind : public CallableCustom {
public:
//for every type that inherits, these must always be the same for this type
- virtual uint32_t hash() const;
- virtual String get_as_text() const;
- virtual CompareEqualFunc get_compare_equal_func() const;
- virtual CompareLessFunc get_compare_less_func() const;
- virtual StringName get_method() const;
- virtual ObjectID get_object() const; //must always be able to provide an object
- virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const;
- virtual const Callable *get_base_comparator() const;
+ virtual uint32_t hash() const override;
+ virtual String get_as_text() const override;
+ virtual CompareEqualFunc get_compare_equal_func() const override;
+ virtual CompareLessFunc get_compare_less_func() const override;
+ virtual StringName get_method() const override;
+ virtual ObjectID get_object() const override; //must always be able to provide an object
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
+ virtual const Callable *get_base_comparator() const override;
Callable get_callable() { return callable; }
Vector<Variant> get_binds() { return binds; }
@@ -68,14 +68,14 @@ class CallableCustomUnbind : public CallableCustom {
public:
//for every type that inherits, these must always be the same for this type
- virtual uint32_t hash() const;
- virtual String get_as_text() const;
- virtual CompareEqualFunc get_compare_equal_func() const;
- virtual CompareLessFunc get_compare_less_func() const;
- virtual StringName get_method() const;
- virtual ObjectID get_object() const; //must always be able to provide an object
- virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const;
- virtual const Callable *get_base_comparator() const;
+ virtual uint32_t hash() const override;
+ virtual String get_as_text() const override;
+ virtual CompareEqualFunc get_compare_equal_func() const override;
+ virtual CompareLessFunc get_compare_less_func() const override;
+ virtual StringName get_method() const override;
+ virtual ObjectID get_object() const override; //must always be able to provide an object
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
+ virtual const Callable *get_base_comparator() const override;
Callable get_callable() { return callable; }
int get_unbinds() { return argcount; }
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index 0f2f8fc8ed..822021f440 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -30,7 +30,7 @@
#include "dictionary.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
#include "core/templates/safe_refcount.h"
#include "core/variant/variant.h"
// required in this order by VariantInternal, do not remove this comment.
@@ -41,7 +41,8 @@
struct DictionaryPrivate {
SafeRefCount refcount;
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
+ Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
+ HashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
};
void Dictionary::get_key_list(List<Variant> *p_keys) const {
@@ -49,16 +50,16 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const {
return;
}
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- p_keys->push_back(E.key());
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ p_keys->push_back(E.key);
}
}
Variant Dictionary::get_key_at_index(int p_index) const {
int index = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
if (index == p_index) {
- return E.key();
+ return E.key;
}
index++;
}
@@ -68,9 +69,9 @@ Variant Dictionary::get_key_at_index(int p_index) const {
Variant Dictionary::get_value_at_index(int p_index) const {
int index = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
if (index == p_index) {
- return E.value();
+ return E.value;
}
index++;
}
@@ -79,11 +80,22 @@ Variant Dictionary::get_value_at_index(int p_index) const {
}
Variant &Dictionary::operator[](const Variant &p_key) {
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- return _p->variant_map[sn->operator String()];
+ if (unlikely(_p->read_only)) {
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ *_p->read_only = _p->variant_map[sn->operator String()];
+ } else {
+ *_p->read_only = _p->variant_map[p_key];
+ }
+
+ return *_p->read_only;
} else {
- return _p->variant_map[p_key];
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ return _p->variant_map[sn->operator String()];
+ } else {
+ return _p->variant_map[p_key];
+ }
}
}
@@ -97,50 +109,55 @@ const Variant &Dictionary::operator[](const Variant &p_key) const {
}
const Variant *Dictionary::getptr(const Variant &p_key) const {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
} else {
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
}
if (!E) {
return nullptr;
}
- return &E.get();
+ return &E->value;
}
Variant *Dictionary::getptr(const Variant &p_key) {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E;
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E;
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
} else {
- E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
}
if (!E) {
return nullptr;
}
- return &E.get();
+ if (unlikely(_p->read_only != nullptr)) {
+ *_p->read_only = E->value;
+ return _p->read_only;
+ } else {
+ return &E->value;
+ }
}
Variant Dictionary::get_valid(const Variant &p_key) const {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
} else {
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
}
if (!E) {
return Variant();
}
- return E.get();
+ return E->value;
}
Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
@@ -179,6 +196,7 @@ bool Dictionary::has_all(const Array &p_keys) const {
}
bool Dictionary::erase(const Variant &p_key) {
+ ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
return _p->variant_map.erase(sn->operator String());
@@ -210,9 +228,9 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
return true;
}
recursion_count++;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement this_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->front(); this_E; this_E = this_E.next()) {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement other_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key());
- if (!other_E || !this_E.value().hash_compare(other_E.value(), recursion_count)) {
+ for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) {
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator other_E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key);
+ if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) {
return false;
}
}
@@ -220,6 +238,16 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
}
void Dictionary::_ref(const Dictionary &p_from) const {
+ if (unlikely(p_from._p->read_only != nullptr)) {
+ // If p_from is a read-only dictionary, just copy the contents to avoid further modification.
+ if (_p) {
+ _unref();
+ }
+ _p = memnew(DictionaryPrivate);
+ _p->refcount.init();
+ _p->variant_map = p_from._p->variant_map;
+ return;
+ }
//make a copy first (thread safe)
if (!p_from._p->refcount.ref()) {
return; // couldn't copy
@@ -237,12 +265,24 @@ void Dictionary::_ref(const Dictionary &p_from) const {
}
void Dictionary::clear() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
_p->variant_map.clear();
}
+void Dictionary::merge(const Dictionary &p_dictionary, bool p_overwrite) {
+ for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
+ if (p_overwrite || !has(E.key)) {
+ this->operator[](E.key) = E.value;
+ }
+ }
+}
+
void Dictionary::_unref() const {
ERR_FAIL_COND(!_p);
if (_p->refcount.unref()) {
+ if (_p->read_only) {
+ memdelete(_p->read_only);
+ }
memdelete(_p);
}
_p = nullptr;
@@ -261,9 +301,9 @@ uint32_t Dictionary::recursive_hash(int recursion_count) const {
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
recursion_count++;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- h = hash_djb2_one_32(E.key().recursive_hash(recursion_count), h);
- h = hash_djb2_one_32(E.value().recursive_hash(recursion_count), h);
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ h = hash_djb2_one_32(E.key.recursive_hash(recursion_count), h);
+ h = hash_djb2_one_32(E.value.recursive_hash(recursion_count), h);
}
return h;
@@ -278,8 +318,8 @@ Array Dictionary::keys() const {
varr.resize(size());
int i = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- varr[i] = E.key();
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ varr[i] = E.key;
i++;
}
@@ -295,8 +335,8 @@ Array Dictionary::values() const {
varr.resize(size());
int i = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- varr[i] = E.get();
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ varr[i] = E.value;
i++;
}
@@ -306,16 +346,23 @@ Array Dictionary::values() const {
const Variant *Dictionary::next(const Variant *p_key) const {
if (p_key == nullptr) {
// caller wants to get the first element
- if (_p->variant_map.front()) {
- return &_p->variant_map.front().key();
+ if (_p->variant_map.begin()) {
+ return &_p->variant_map.begin()->key;
}
return nullptr;
}
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key);
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E = _p->variant_map.find(*p_key);
+
+ if (!E) {
+ return nullptr;
+ }
+
+ ++E;
- if (E && E.next()) {
- return &E.next().key();
+ if (E) {
+ return &E->key;
}
+
return nullptr;
}
@@ -323,6 +370,21 @@ Dictionary Dictionary::duplicate(bool p_deep) const {
return recursive_duplicate(p_deep, 0);
}
+void Dictionary::set_read_only(bool p_enable) {
+ if (p_enable == bool(_p->read_only != nullptr)) {
+ return;
+ }
+ if (p_enable) {
+ _p->read_only = memnew(Variant);
+ } else {
+ memdelete(_p->read_only);
+ _p->read_only = nullptr;
+ }
+}
+bool Dictionary::is_read_only() const {
+ return _p->read_only != nullptr;
+}
+
Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) const {
Dictionary n;
@@ -333,12 +395,12 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con
if (p_deep) {
recursion_count++;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- n[E.key().recursive_duplicate(true, recursion_count)] = E.value().recursive_duplicate(true, recursion_count);
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ n[E.key.recursive_duplicate(true, recursion_count)] = E.value.recursive_duplicate(true, recursion_count);
}
} else {
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- n[E.key()] = E.value();
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ n[E.key] = E.value;
}
}
@@ -346,6 +408,9 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con
}
void Dictionary::operator=(const Dictionary &p_dictionary) {
+ if (this == &p_dictionary) {
+ return;
+ }
_ref(p_dictionary);
}
diff --git a/core/variant/dictionary.h b/core/variant/dictionary.h
index 16cf0c2bf8..2632893e8d 100644
--- a/core/variant/dictionary.h
+++ b/core/variant/dictionary.h
@@ -62,6 +62,7 @@ public:
int size() const;
bool is_empty() const;
void clear();
+ void merge(const Dictionary &p_dictionary, bool p_overwrite = false);
bool has(const Variant &p_key) const;
bool has_all(const Array &p_keys) const;
@@ -84,6 +85,9 @@ public:
Dictionary duplicate(bool p_deep = false) const;
Dictionary recursive_duplicate(bool p_deep, int recursion_count) const;
+ void set_read_only(bool p_enable);
+ bool is_read_only() const;
+
const void *id() const;
Dictionary(const Dictionary &p_from);
diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h
index 8e9fbbc0a4..ed68e0f6c9 100644
--- a/core/variant/native_ptr.h
+++ b/core/variant/native_ptr.h
@@ -124,6 +124,7 @@ struct PtrToArg<GDNativePtr<T>> {
}
};
+GDVIRTUAL_NATIVE_PTR(void)
GDVIRTUAL_NATIVE_PTR(AudioFrame)
GDVIRTUAL_NATIVE_PTR(bool)
GDVIRTUAL_NATIVE_PTR(char)
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index ee050cff4f..bacd0d19ce 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -281,4 +281,38 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) {
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
+template <typename T>
+struct ZeroInitializer {
+ static void initialize(T &value) {} //no initialization by default
+};
+
+template <>
+struct ZeroInitializer<bool> {
+ static void initialize(bool &value) { value = false; }
+};
+
+template <typename T>
+struct ZeroInitializer<T *> {
+ static void initialize(T *&value) { value = nullptr; }
+};
+
+#define ZERO_INITIALIZER_NUMBER(m_type) \
+ template <> \
+ struct ZeroInitializer<m_type> { \
+ static void initialize(m_type &value) { value = 0; } \
+ };
+
+ZERO_INITIALIZER_NUMBER(uint8_t)
+ZERO_INITIALIZER_NUMBER(int8_t)
+ZERO_INITIALIZER_NUMBER(uint16_t)
+ZERO_INITIALIZER_NUMBER(int16_t)
+ZERO_INITIALIZER_NUMBER(uint32_t)
+ZERO_INITIALIZER_NUMBER(int32_t)
+ZERO_INITIALIZER_NUMBER(uint64_t)
+ZERO_INITIALIZER_NUMBER(int64_t)
+ZERO_INITIALIZER_NUMBER(char16_t)
+ZERO_INITIALIZER_NUMBER(char32_t)
+ZERO_INITIALIZER_NUMBER(float)
+ZERO_INITIALIZER_NUMBER(double)
+
#endif // TYPE_INFO_H
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 3d11ed6303..2b4e777865 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -184,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;
}
@@ -490,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;
}
@@ -1620,6 +1620,27 @@ Variant::operator String() const {
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("[");
@@ -1627,7 +1648,8 @@ String stringify_vector(const T &vec, int recursion_count) {
if (i > 0) {
str += ", ";
}
- str = str + Variant(vec[i]).stringify(recursion_count);
+
+ str += stringify_variant_clean(vec[i], recursion_count);
}
str += "]";
return str;
@@ -1691,8 +1713,8 @@ String Variant::stringify(int recursion_count) const {
recursion_count++;
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
_VariantStrPair sp;
- sp.key = E->get().stringify(recursion_count);
- sp.value = d[E->get()].stringify(recursion_count);
+ sp.key = stringify_variant_clean(E->get(), recursion_count);
+ sp.value = stringify_variant_clean(d[E->get()], recursion_count);
pairs.push_back(sp);
}
@@ -1741,8 +1763,7 @@ String Variant::stringify(int recursion_count) const {
return "[...]";
}
- String str = stringify_vector(arr, recursion_count);
- return str;
+ return stringify_vector(arr, recursion_count);
} break;
case OBJECT: {
@@ -1908,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();
@@ -1926,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();
@@ -1972,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;
}
@@ -2790,7 +2811,7 @@ uint32_t Variant::recursive_hash(int recursion_count) 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);
}
}
@@ -2834,7 +2855,7 @@ uint32_t Variant::recursive_hash(int recursion_count) 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);
}
}
@@ -2845,7 +2866,7 @@ uint32_t Variant::recursive_hash(int recursion_count) 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);
}
@@ -3081,6 +3102,10 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
return *reinterpret_cast<const String *>(_data._mem) == *reinterpret_cast<const String *>(p_variant._data._mem);
} break;
+ case STRING_NAME: {
+ return *reinterpret_cast<const StringName *>(_data._mem) == *reinterpret_cast<const StringName *>(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);
@@ -3112,7 +3137,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) 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;
}
}
@@ -3162,7 +3187,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) 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;
}
}
@@ -3175,7 +3200,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) 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;
}
}
@@ -3309,21 +3334,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)) + "'.";
@@ -3341,8 +3352,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) {
@@ -3357,27 +3366,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) {
@@ -3402,37 +3391,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<Resource> 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) {
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 836a67d942..726ba120b5 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -282,6 +282,14 @@ private:
static void _register_variant_utility_functions();
static void _unregister_variant_utility_functions();
+ void _variant_call_error(const String &p_method, Callable::CallError &error);
+
+ // Avoid accidental conversion. If you reached this point, it's because you most likely forgot to dereference
+ // a Variant pointer (so add * like this: *variant_pointer).
+
+ Variant(const Variant *) {}
+ Variant(const Variant **) {}
+
public:
_FORCE_INLINE_ Type get_type() const {
return type;
@@ -465,6 +473,7 @@ public:
OP_NEGATE,
OP_POSITIVE,
OP_MODULE,
+ OP_POWER,
//bitwise
OP_SHIFT_LEFT,
OP_SHIFT_RIGHT,
@@ -503,6 +512,7 @@ public:
Variant recursive_duplicate(bool p_deep, int recursion_count) const;
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
+ static void sub(const Variant &a, const Variant &b, Variant &r_dst);
/* Built-In Methods */
@@ -527,8 +537,23 @@ public:
static int get_builtin_method_count(Variant::Type p_type);
static uint32_t get_builtin_method_hash(Variant::Type p_type, const StringName &p_method);
- void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, 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(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant());
+ void callp(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
+
+ template <typename... VarArgs>
+ Variant call(const StringName &p_method, 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];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ Callable::CallError cerr;
+ Variant ret;
+ callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), ret, cerr);
+ if (cerr.error != Callable::CallError::CALL_OK) {
+ _variant_call_error(p_method, cerr);
+ }
+ return ret;
+ }
static void call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index a5e89eec80..b335f2fcf4 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -919,11 +919,11 @@ struct _VariantCall {
}
struct ConstantData {
- Map<StringName, int> value;
+ HashMap<StringName, int> value;
#ifdef DEBUG_ENABLED
List<StringName> value_ordered;
#endif
- Map<StringName, Variant> variant_value;
+ HashMap<StringName, Variant> variant_value;
#ifdef DEBUG_ENABLED
List<StringName> variant_value_ordered;
#endif
@@ -949,20 +949,20 @@ struct _VariantCall {
_VariantCall::ConstantData *_VariantCall::constant_data = nullptr;
struct VariantBuiltInMethodInfo {
- void (*call)(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error);
- Variant::ValidatedBuiltInMethod validated_call;
- Variant::PTRBuiltInMethod ptrcall;
+ void (*call)(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) = nullptr;
+ Variant::ValidatedBuiltInMethod validated_call = nullptr;
+ Variant::PTRBuiltInMethod ptrcall = nullptr;
Vector<Variant> default_arguments;
Vector<String> argument_names;
- bool is_const;
- bool is_static;
- bool has_return_type;
- bool is_vararg;
+ bool is_const = false;
+ bool is_static = false;
+ bool has_return_type = false;
+ bool is_vararg = false;
Variant::Type return_type;
- int argument_count;
- Variant::Type (*get_argument_type)(int p_arg);
+ int argument_count = 0;
+ Variant::Type (*get_argument_type)(int p_arg) = nullptr;
};
typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap;
@@ -1003,7 +1003,7 @@ static void register_builtin_method(const Vector<String> &p_argnames, const Vect
builtin_method_names[T::get_base_type()].push_back(name);
}
-void Variant::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+void Variant::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
if (type == Variant::OBJECT) {
//call object
Object *obj = _get_obj().obj;
@@ -1018,7 +1018,7 @@ void Variant::call(const StringName &p_method, const Variant **p_args, int p_arg
}
#endif
- r_ret = _get_obj().obj->call(p_method, p_args, p_argcount, r_error);
+ r_ret = _get_obj().obj->callp(p_method, p_args, p_argcount, r_error);
//else if (type==Variant::METHOD) {
} else {
@@ -1239,10 +1239,10 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants) {
ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
- _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type];
+ const _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type];
#ifdef DEBUG_ENABLED
- for (List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) {
+ for (const List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) {
p_constants->push_back(E->get());
#else
for (const KeyValue<StringName, int> &E : cd.value) {
@@ -1251,7 +1251,7 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c
}
#ifdef DEBUG_ENABLED
- for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) {
+ for (const List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) {
p_constants->push_back(E->get());
#else
for (const KeyValue<StringName, Variant> &E : cd.variant_value) {
@@ -1281,14 +1281,14 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
_VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type];
- Map<StringName, int>::Element *E = cd.value.find(p_value);
+ HashMap<StringName, int>::Iterator E = cd.value.find(p_value);
if (!E) {
- Map<StringName, Variant>::Element *F = cd.variant_value.find(p_value);
+ HashMap<StringName, Variant>::Iterator F = cd.variant_value.find(p_value);
if (F) {
if (r_valid) {
*r_valid = true;
}
- return F->get();
+ return F->value;
} else {
return -1;
}
@@ -1297,7 +1297,7 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
*r_valid = true;
}
- return E->get();
+ return E->value;
}
#ifdef DEBUG_METHODS_ENABLED
@@ -1402,8 +1402,8 @@ static void _register_variant_builtin_methods() {
bind_method(String, to_upper, sarray(), varray());
bind_method(String, to_lower, sarray(), varray());
- bind_method(String, left, sarray("position"), varray());
- bind_method(String, right, sarray("position"), varray());
+ bind_method(String, left, sarray("length"), varray());
+ bind_method(String, right, sarray("length"), varray());
bind_method(String, strip_edges, sarray("left", "right"), varray(true, true));
bind_method(String, strip_escapes, sarray(), varray());
@@ -1467,9 +1467,15 @@ static void _register_variant_builtin_methods() {
bind_static_method(String, num_scientific, sarray("number"), varray());
bind_static_method(String, num, sarray("number", "decimals"), varray(-1));
+ bind_static_method(String, num_int64, sarray("number", "base", "capitalize_hex"), varray(10, false));
+ bind_static_method(String, num_uint64, sarray("number", "base", "capitalize_hex"), varray(10, false));
bind_static_method(String, chr, sarray("char"), varray());
bind_static_method(String, humanize_size, sarray("size"), varray());
+ /* StringName */
+
+ bind_method(StringName, hash, sarray(), varray());
+
/* Vector2 */
bind_method(Vector2, angle, sarray(), varray());
@@ -1493,7 +1499,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector2, max_axis_index, sarray(), varray());
bind_method(Vector2, min_axis_index, sarray(), varray());
bind_method(Vector2, move_toward, sarray("to", "delta"), varray());
- bind_method(Vector2, rotated, sarray("phi"), varray());
+ bind_method(Vector2, rotated, sarray("angle"), varray());
bind_method(Vector2, orthogonal, sarray(), varray());
bind_method(Vector2, floor, sarray(), varray());
bind_method(Vector2, ceil, sarray(), varray());
@@ -1573,7 +1579,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, inverse, sarray(), varray());
bind_method(Vector3, clamp, sarray("min", "max"), varray());
bind_method(Vector3, snapped, sarray("step"), varray());
- bind_method(Vector3, rotated, sarray("by_axis", "phi"), varray());
+ bind_method(Vector3, rotated, sarray("axis", "angle"), varray());
bind_method(Vector3, lerp, sarray("to", "weight"), varray());
bind_method(Vector3, slerp, sarray("to", "weight"), varray());
bind_method(Vector3, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray());
@@ -1626,6 +1632,8 @@ static void _register_variant_builtin_methods() {
bind_method(Quaternion, is_normalized, sarray(), varray());
bind_method(Quaternion, is_equal_approx, sarray("to"), varray());
bind_method(Quaternion, inverse, sarray(), varray());
+ bind_method(Quaternion, log, sarray(), varray());
+ bind_method(Quaternion, exp, sarray(), varray());
bind_method(Quaternion, angle_to, sarray("to"), varray());
bind_method(Quaternion, dot, sarray("with"), varray());
bind_method(Quaternion, slerp, sarray("to", "weight"), varray());
@@ -1652,6 +1660,8 @@ static void _register_variant_builtin_methods() {
bind_method(Color, darkened, sarray("amount"), varray());
bind_method(Color, blend, sarray("over"), varray());
bind_method(Color, get_luminance, sarray(), varray());
+ bind_method(Color, srgb_to_linear, sarray(), varray());
+ bind_method(Color, linear_to_srgb, sarray(), varray());
bind_method(Color, is_equal_approx, sarray("to"), varray());
@@ -1665,6 +1675,8 @@ static void _register_variant_builtin_methods() {
bind_static_method(Color, get_named_color, sarray("idx"), varray());
bind_static_method(Color, from_string, sarray("str", "default"), varray());
bind_static_method(Color, from_hsv, sarray("h", "s", "v", "alpha"), varray(1.0));
+ bind_static_method(Color, from_ok_hsl, sarray("h", "s", "l", "alpha"), varray(1.0));
+
bind_static_method(Color, from_rgbe9995, sarray("rgbe"), varray());
/* RID */
@@ -1678,6 +1690,7 @@ static void _register_variant_builtin_methods() {
bind_method(NodePath, get_name_count, sarray(), varray());
bind_method(NodePath, get_name, sarray("idx"), varray());
bind_method(NodePath, get_subname_count, sarray(), varray());
+ bind_method(NodePath, hash, sarray(), varray());
bind_method(NodePath, get_subname, sarray("idx"), varray());
bind_method(NodePath, get_concatenated_subnames, sarray(), varray());
bind_method(NodePath, get_as_property_path, sarray(), varray());
@@ -1724,7 +1737,7 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, get_scale, sarray(), varray());
bind_method(Transform2D, get_skew, sarray(), varray());
bind_method(Transform2D, orthonormalized, sarray(), varray());
- bind_method(Transform2D, rotated, sarray("phi"), varray());
+ bind_method(Transform2D, rotated, sarray("angle"), varray());
bind_method(Transform2D, scaled, sarray("scale"), varray());
bind_method(Transform2D, translated, sarray("offset"), varray());
bind_method(Transform2D, basis_xform, sarray("v"), varray());
@@ -1742,7 +1755,7 @@ static void _register_variant_builtin_methods() {
bind_method(Basis, transposed, sarray(), varray());
bind_method(Basis, orthonormalized, sarray(), varray());
bind_method(Basis, determinant, sarray(), varray());
- bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, real_t) const>(&Basis::rotated), sarray("axis", "phi"), varray());
+ bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, real_t) const>(&Basis::rotated), sarray("axis", "angle"), varray());
bind_method(Basis, scaled, sarray("scale"), varray());
bind_method(Basis, get_scale, sarray(), varray());
bind_method(Basis, get_euler, sarray("order"), varray(Basis::EULER_ORDER_YXZ));
@@ -1789,7 +1802,7 @@ static void _register_variant_builtin_methods() {
bind_method(Transform3D, inverse, sarray(), varray());
bind_method(Transform3D, affine_inverse, sarray(), varray());
bind_method(Transform3D, orthonormalized, sarray(), varray());
- bind_method(Transform3D, rotated, sarray("axis", "phi"), varray());
+ bind_method(Transform3D, rotated, sarray("axis", "angle"), varray());
bind_method(Transform3D, scaled, sarray("scale"), varray());
bind_method(Transform3D, translated, sarray("offset"), varray());
bind_method(Transform3D, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
@@ -1802,6 +1815,7 @@ static void _register_variant_builtin_methods() {
bind_method(Dictionary, size, sarray(), varray());
bind_method(Dictionary, is_empty, sarray(), varray());
bind_method(Dictionary, clear, sarray(), varray());
+ bind_method(Dictionary, merge, sarray("dictionary", "overwrite"), varray(false));
bind_method(Dictionary, has, sarray("key"), varray());
bind_method(Dictionary, has_all, sarray("keys"), varray());
bind_method(Dictionary, erase, sarray("key"), varray());
@@ -1847,6 +1861,8 @@ static void _register_variant_builtin_methods() {
bind_method(Array, filter, sarray("method"), varray());
bind_method(Array, map, sarray("method"), varray());
bind_method(Array, reduce, sarray("method", "accum"), varray(Variant()));
+ bind_method(Array, any, sarray("method"), varray());
+ bind_method(Array, all, sarray("method"), varray());
bind_method(Array, max, sarray(), varray());
bind_method(Array, min, sarray(), varray());
@@ -1867,6 +1883,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedByteArray, sort, sarray(), varray());
bind_method(PackedByteArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedByteArray, duplicate, sarray(), varray());
+ bind_method(PackedByteArray, find, sarray("value", "from"), varray(0));
+ bind_method(PackedByteArray, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedByteArray, count, sarray("value"), varray());
bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray());
bind_function(PackedByteArray, get_string_from_utf8, _VariantCall::func_PackedByteArray_get_string_from_utf8, sarray(), varray());
@@ -1929,6 +1948,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt32Array, sort, sarray(), varray());
bind_method(PackedInt32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt32Array, duplicate, sarray(), varray());
+ bind_method(PackedInt32Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedInt32Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedInt32Array, count, sarray("value"), varray());
/* Int64 Array */
@@ -1949,6 +1971,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt64Array, sort, sarray(), varray());
bind_method(PackedInt64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt64Array, duplicate, sarray(), varray());
+ bind_method(PackedInt64Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedInt64Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedInt64Array, count, sarray("value"), varray());
/* Float32 Array */
@@ -1969,6 +1994,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat32Array, sort, sarray(), varray());
bind_method(PackedFloat32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat32Array, duplicate, sarray(), varray());
+ bind_method(PackedFloat32Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedFloat32Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedFloat32Array, count, sarray("value"), varray());
/* Float64 Array */
@@ -1989,6 +2017,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat64Array, sort, sarray(), varray());
bind_method(PackedFloat64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat64Array, duplicate, sarray(), varray());
+ bind_method(PackedFloat64Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedFloat64Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedFloat64Array, count, sarray("value"), varray());
/* String Array */
@@ -2009,6 +2040,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedStringArray, sort, sarray(), varray());
bind_method(PackedStringArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedStringArray, duplicate, sarray(), varray());
+ bind_method(PackedStringArray, find, sarray("value", "from"), varray(0));
+ bind_method(PackedStringArray, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedStringArray, count, sarray("value"), varray());
/* Vector2 Array */
@@ -2029,6 +2063,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector2Array, sort, sarray(), varray());
bind_method(PackedVector2Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector2Array, duplicate, sarray(), varray());
+ bind_method(PackedVector2Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedVector2Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedVector2Array, count, sarray("value"), varray());
/* Vector3 Array */
@@ -2049,6 +2086,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector3Array, sort, sarray(), varray());
bind_method(PackedVector3Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector3Array, duplicate, sarray(), varray());
+ bind_method(PackedVector3Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedVector3Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedVector3Array, count, sarray("value"), varray());
/* Color Array */
@@ -2069,6 +2109,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedColorArray, sort, sarray(), varray());
bind_method(PackedColorArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedColorArray, duplicate, sarray(), varray());
+ bind_method(PackedColorArray, find, sarray("value", "from"), varray(0));
+ bind_method(PackedColorArray, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedColorArray, count, sarray("value"), varray());
/* Register constants */
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index 351f4ae253..78d5433d8c 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -31,11 +31,11 @@
#include "variant_construct.h"
struct VariantConstructData {
- void (*construct)(Variant &r_base, const Variant **p_args, Callable::CallError &r_error);
- Variant::ValidatedConstructor validated_construct;
- Variant::PTRConstructor ptr_construct;
- Variant::Type (*get_argument_type)(int);
- int argument_count;
+ void (*construct)(Variant &r_base, const Variant **p_args, Callable::CallError &r_error) = nullptr;
+ Variant::ValidatedConstructor validated_construct = nullptr;
+ Variant::PTRConstructor ptr_construct = nullptr;
+ Variant::Type (*get_argument_type)(int) = nullptr;
+ int argument_count = 0;
Vector<String> arg_names;
};
@@ -140,7 +140,7 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Basis>>(sarray());
add_constructor<VariantConstructor<Basis, Basis>>(sarray("from"));
add_constructor<VariantConstructor<Basis, Quaternion>>(sarray("from"));
- add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "phi"));
+ add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "angle"));
add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis"));
add_constructor<VariantConstructNoArgs<Transform3D>>(sarray());
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 6027cb027e..638c0136f3 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -344,7 +344,7 @@ public:
return;
}
- VariantTypeChanger<Array>::change(&r_ret);
+ r_ret = Array();
Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
@@ -356,7 +356,7 @@ public:
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
- VariantTypeChanger<Array>::change(r_ret);
+ *r_ret = Array();
Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret);
const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
@@ -543,14 +543,12 @@ public:
class VariantConstructNoArgsObject {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
- VariantInternal::clear(&r_ret);
- VariantInternal::object_assign_null(&r_ret);
+ r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr.
r_error.error = Callable::CallError::CALL_OK;
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
- VariantInternal::clear(r_ret);
- VariantInternal::object_assign_null(r_ret);
+ *r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr.
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Object *>::construct(nullptr, base);
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index cd1ae9f41f..adace2b534 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -177,6 +177,7 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAdd<double, double, double>>(Variant::OP_ADD, Variant::FLOAT, Variant::FLOAT);
register_op<OperatorEvaluatorAdd<String, String, String>>(Variant::OP_ADD, Variant::STRING, Variant::STRING);
register_op<OperatorEvaluatorAdd<String, char32_t, String>>(Variant::OP_ADD, Variant::INT, Variant::STRING);
+ register_op<OperatorEvaluatorAdd<String, String, char32_t>>(Variant::OP_ADD, Variant::STRING, Variant::INT);
register_op<OperatorEvaluatorAdd<Vector2, Vector2, Vector2>>(Variant::OP_ADD, Variant::VECTOR2, Variant::VECTOR2);
register_op<OperatorEvaluatorAdd<Vector2i, Vector2i, Vector2i>>(Variant::OP_ADD, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorAdd<Vector3, Vector3, Vector3>>(Variant::OP_ADD, Variant::VECTOR3, Variant::VECTOR3);
@@ -360,6 +361,11 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorStringModT<PackedVector3Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR3_ARRAY);
register_op<OperatorEvaluatorStringModT<PackedColorArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_COLOR_ARRAY);
+ register_op<OperatorEvaluatorPow<int64_t, int64_t, int64_t>>(Variant::OP_POWER, Variant::INT, Variant::INT);
+ register_op<OperatorEvaluatorPow<double, int64_t, double>>(Variant::OP_POWER, Variant::INT, Variant::FLOAT);
+ register_op<OperatorEvaluatorPow<double, double, double>>(Variant::OP_POWER, Variant::FLOAT, Variant::FLOAT);
+ register_op<OperatorEvaluatorPow<double, double, int64_t>>(Variant::OP_POWER, Variant::FLOAT, Variant::INT);
+
register_op<OperatorEvaluatorNeg<int64_t, int64_t>>(Variant::OP_NEGATE, Variant::INT, Variant::NIL);
register_op<OperatorEvaluatorNeg<double, double>>(Variant::OP_NEGATE, Variant::FLOAT, Variant::NIL);
register_op<OperatorEvaluatorNeg<Vector2, Vector2>>(Variant::OP_NEGATE, Variant::VECTOR2, Variant::NIL);
@@ -928,6 +934,7 @@ static const char *_op_names[Variant::OP_MAX] = {
"unary-",
"unary+",
"%",
+ "**",
"<<",
">>",
"&",
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index f72a92d31a..3e9bae1078 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -92,6 +92,24 @@ public:
};
template <class R, class A, class B>
+class OperatorEvaluatorPow {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+ const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+ *r_ret = R(Math::pow((double)a, (double)b));
+ r_valid = true;
+ }
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ *VariantGetInternalPtr<R>::get_ptr(r_ret) = R(Math::pow((double)*VariantGetInternalPtr<A>::get_ptr(left), (double)*VariantGetInternalPtr<B>::get_ptr(right)));
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<R>::encode(R(Math::pow((double)PtrToArg<A>::convert(left), (double)PtrToArg<B>::convert(right))), r_ret);
+ }
+ static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
class OperatorEvaluatorXForm {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index e889a1bb40..259ca8a60d 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -162,6 +162,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
return OK;
}
if (ch == '\n') {
+ line++;
break;
}
}
@@ -344,7 +345,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
if (string_name) {
r_token.type = TK_STRING_NAME;
r_token.value = StringName(str);
- string_name = false; //reset
} else {
r_token.type = TK_STRING;
r_token.value = str;
@@ -807,7 +807,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
return ERR_PARSE_ERROR;
}
- REF ref = REF(Object::cast_to<RefCounted>(obj));
+ Ref<RefCounted> ref = Ref<RefCounted>(Object::cast_to<RefCounted>(obj));
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_COMMA) {
@@ -888,7 +888,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
if (p_res_parser && id == "Resource" && p_res_parser->func) {
- RES res;
+ Ref<Resource> res;
Error err = p_res_parser->func(p_res_parser->userdata, p_stream, res, line, r_err_str);
if (err) {
return err;
@@ -896,7 +896,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = res;
} else if (p_res_parser && id == "ExtResource" && p_res_parser->ext_func) {
- RES res;
+ Ref<Resource> res;
Error err = p_res_parser->ext_func(p_res_parser->userdata, p_stream, res, line, r_err_str);
if (err) {
return err;
@@ -904,7 +904,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = res;
} else if (p_res_parser && id == "SubResource" && p_res_parser->sub_func) {
- RES res;
+ Ref<Resource> res;
Error err = p_res_parser->sub_func(p_res_parser->userdata, p_stream, res, line, r_err_str);
if (err) {
return err;
@@ -915,7 +915,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
get_token(p_stream, token, line, r_err_str);
if (token.type == TK_STRING) {
String path = token.value;
- RES res = ResourceLoader::load(path);
+ Ref<Resource> res = ResourceLoader::load(path);
if (res.is_null()) {
r_err_str = "Can't load resource at path: '" + path + "'.";
return ERR_PARSE_ERROR;
@@ -1402,6 +1402,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
return ERR_FILE_EOF;
}
if (ch == '\n') {
+ line++;
break;
}
}
@@ -1556,7 +1557,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtos_fix(m3.elements[i][j]);
+ s += rtos_fix(m3.columns[i][j]);
}
}
@@ -1571,7 +1572,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtos_fix(m3.elements[i][j]);
+ s += rtos_fix(m3.rows[i][j]);
}
}
@@ -1587,7 +1588,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtos_fix(m3.elements[i][j]);
+ s += rtos_fix(m3.rows[i][j]);
}
}
@@ -1625,7 +1626,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
break; // don't save it
}
- RES res = p_variant;
+ Ref<Resource> res = p_variant;
if (res.is_valid()) {
//is resource
String res_text;
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index e5585076c2..56b484c8bc 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -49,11 +49,11 @@ public:
};
struct StreamFile : public Stream {
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
- virtual char32_t get_char();
- virtual bool is_utf8() const;
- virtual bool is_eof() const;
+ virtual char32_t get_char() override;
+ virtual bool is_utf8() const override;
+ virtual bool is_eof() const override;
StreamFile() {}
};
@@ -62,9 +62,9 @@ public:
String s;
int pos = 0;
- virtual char32_t get_char();
- virtual bool is_utf8() const;
- virtual bool is_eof() const;
+ virtual char32_t get_char() override;
+ virtual bool is_utf8() const override;
+ virtual bool is_eof() const override;
StreamString() {}
};
@@ -113,7 +113,7 @@ public:
struct Tag {
String name;
- Map<String, Variant> fields;
+ HashMap<String, Variant> fields;
};
private:
@@ -138,7 +138,7 @@ public:
class VariantWriter {
public:
typedef Error (*StoreStringFunc)(void *ud, const String &p_string);
- typedef String (*EncodeResourceFunc)(void *ud, const RES &p_resource);
+ typedef String (*EncodeResourceFunc)(void *ud, const Ref<Resource> &p_resource);
static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int recursion_count = 0);
static Error write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func = nullptr, void *p_encode_res_ud = nullptr);
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index fa8d26a72b..3839da495f 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -624,6 +624,11 @@ struct VariantIndexedSetGet_Array {
PtrToArg<Variant>::encode(v[index], member);
}
static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) {
+ if (VariantGetInternalPtr<Array>::get_ptr(base)->is_read_only()) {
+ *valid = false;
+ *oob = true;
+ return;
+ }
int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size();
if (index < 0) {
index += size;
@@ -638,6 +643,10 @@ struct VariantIndexedSetGet_Array {
*valid = true;
}
static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) {
+ if (VariantGetInternalPtr<Array>::get_ptr(base)->is_read_only()) {
+ *oob = true;
+ return;
+ }
int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size();
if (index < 0) {
index += size;
@@ -766,11 +775,20 @@ struct VariantIndexedSetGet_String {
PtrToArg<Variant>::encode(*ptr, member); \
} \
static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
+ if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \
+ *valid = false; \
+ *oob = true; \
+ return; \
+ } \
(*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \
*oob = false; \
*valid = true; \
} \
static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
+ if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \
+ *oob = true; \
+ return; \
+ } \
(*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \
*oob = false; \
} \
@@ -789,8 +807,8 @@ INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3i, int64_t, int32_t, 3)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quaternion, double, real_t, 4)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Color, double, float, 4)
-INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .elements, 3)
-INDEXED_SETGET_STRUCT_BULTIN_FUNC(Basis, Vector3, set_axis, get_axis, 3)
+INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .columns, 3)
+INDEXED_SETGET_STRUCT_BULTIN_FUNC(Basis, Vector3, set_column, get_column, 3)
INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedByteArray, int64_t, uint8_t)
INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt32Array, int64_t, int32_t)
@@ -805,16 +823,16 @@ INDEXED_SETGET_STRUCT_TYPED(PackedColorArray, Color)
INDEXED_SETGET_STRUCT_DICT(Dictionary)
struct VariantIndexedSetterGetterInfo {
- void (*setter)(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob);
- void (*getter)(const Variant *base, int64_t index, Variant *value, bool *oob);
+ void (*setter)(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) = nullptr;
+ void (*getter)(const Variant *base, int64_t index, Variant *value, bool *oob) = nullptr;
- Variant::ValidatedIndexedSetter validated_setter;
- Variant::ValidatedIndexedGetter validated_getter;
+ Variant::ValidatedIndexedSetter validated_setter = nullptr;
+ Variant::ValidatedIndexedGetter validated_getter = nullptr;
- Variant::PTRIndexedSetter ptr_setter;
- Variant::PTRIndexedGetter ptr_getter;
+ Variant::PTRIndexedSetter ptr_setter = nullptr;
+ Variant::PTRIndexedGetter ptr_getter = nullptr;
- uint64_t (*get_indexed_size)(const Variant *base);
+ uint64_t (*get_indexed_size)(const Variant *base) = nullptr;
Variant::Type index_type;
@@ -946,6 +964,10 @@ struct VariantKeyedSetGetDictionary {
PtrToArg<Variant>::encode(*ptr, value);
}
static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) {
+ if (VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only()) {
+ *r_valid = false;
+ return;
+ }
(*VariantGetInternalPtr<Dictionary>::get_ptr(base))[*key] = *value;
*r_valid = true;
}
@@ -1018,13 +1040,13 @@ struct VariantKeyedSetGetObject {
};
struct VariantKeyedSetterGetterInfo {
- Variant::ValidatedKeyedSetter validated_setter;
- Variant::ValidatedKeyedGetter validated_getter;
- Variant::ValidatedKeyedChecker validated_checker;
+ Variant::ValidatedKeyedSetter validated_setter = nullptr;
+ Variant::ValidatedKeyedGetter validated_getter = nullptr;
+ Variant::ValidatedKeyedChecker validated_checker = nullptr;
- Variant::PTRKeyedSetter ptr_setter;
- Variant::PTRKeyedGetter ptr_getter;
- Variant::PTRKeyedChecker ptr_checker;
+ Variant::PTRKeyedSetter ptr_setter = nullptr;
+ Variant::PTRKeyedGetter ptr_getter = nullptr;
+ Variant::PTRKeyedChecker ptr_checker = nullptr;
bool valid = false;
};
@@ -1277,7 +1299,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
ref.push_back(r_iter);
Variant vref = ref;
const Variant *refp[] = { &vref };
- Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce);
+ Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce);
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
valid = false;
@@ -1504,7 +1526,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
ref.push_back(r_iter);
Variant vref = ref;
const Variant *refp[] = { &vref };
- Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce);
+ Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce);
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
valid = false;
@@ -1686,7 +1708,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
Callable::CallError ce;
ce.error = Callable::CallError::CALL_OK;
const Variant *refp[] = { &r_iter };
- Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce);
+ Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce);
if (ce.error != Callable::CallError::CALL_OK) {
r_valid = false;
@@ -1868,6 +1890,110 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const {
}
}
+void Variant::sub(const Variant &a, const Variant &b, Variant &r_dst) {
+ if (a.type != b.type) {
+ return;
+ }
+
+ switch (a.type) {
+ case NIL: {
+ r_dst = Variant();
+ }
+ return;
+ case INT: {
+ int64_t va = a._data._int;
+ int64_t vb = b._data._int;
+ r_dst = int(va - vb);
+ }
+ return;
+ case FLOAT: {
+ double ra = a._data._float;
+ double rb = b._data._float;
+ r_dst = ra - rb;
+ }
+ return;
+ case VECTOR2: {
+ r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) - *reinterpret_cast<const Vector2 *>(b._data._mem);
+ }
+ return;
+ case VECTOR2I: {
+ int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
+ int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
+ int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
+ int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
+ r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby));
+ }
+ return;
+ case RECT2: {
+ const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
+ const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
+ r_dst = Rect2(ra->position - rb->position, ra->size - rb->size);
+ }
+ return;
+ case RECT2I: {
+ const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
+ const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);
+
+ int32_t vax = ra->position.x;
+ int32_t vay = ra->position.y;
+ int32_t vbx = ra->size.x;
+ int32_t vby = ra->size.y;
+ int32_t vcx = rb->position.x;
+ int32_t vcy = rb->position.y;
+ int32_t vdx = rb->size.x;
+ int32_t vdy = rb->size.y;
+
+ r_dst = Rect2i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vcx - vdx), int32_t(vcy - vdy));
+ }
+ return;
+ case VECTOR3: {
+ r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) - *reinterpret_cast<const Vector3 *>(b._data._mem);
+ }
+ return;
+ case VECTOR3I: {
+ int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
+ int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
+ int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
+ int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
+ int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
+ int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
+ r_dst = Vector3i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vaz - vbz));
+ }
+ return;
+ case AABB: {
+ const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
+ const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
+ r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size);
+ }
+ return;
+ case QUATERNION: {
+ Quaternion empty_rot;
+ const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
+ const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
+ r_dst = (*qb).inverse() * *qa;
+ }
+ return;
+ case COLOR: {
+ const Color *ca = reinterpret_cast<const Color *>(a._data._mem);
+ const Color *cb = reinterpret_cast<const Color *>(b._data._mem);
+ float new_r = ca->r - cb->r;
+ float new_g = ca->g - cb->g;
+ float new_b = ca->b - cb->b;
+ float new_a = ca->a - cb->a;
+ new_r = new_r > 1.0 ? 1.0 : new_r;
+ new_g = new_g > 1.0 ? 1.0 : new_g;
+ new_b = new_b > 1.0 ? 1.0 : new_b;
+ new_a = new_a > 1.0 ? 1.0 : new_a;
+ r_dst = Color(new_r, new_g, new_b, new_a);
+ }
+ return;
+ default: {
+ r_dst = a;
+ }
+ return;
+ }
+}
+
void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
if (a.type != b.type) {
if (a.is_num() && b.is_num()) {
diff --git a/core/variant/variant_setget.h b/core/variant/variant_setget.h
index 28277fa5d0..bc4dc4b408 100644
--- a/core/variant/variant_setget.h
+++ b/core/variant/variant_setget.h
@@ -293,9 +293,9 @@ SETGET_STRUCT(AABB, Vector3, position)
SETGET_STRUCT(AABB, Vector3, size)
SETGET_STRUCT_FUNC(AABB, Vector3, end, set_end, get_end)
-SETGET_STRUCT_CUSTOM(Transform2D, Vector2, x, elements[0])
-SETGET_STRUCT_CUSTOM(Transform2D, Vector2, y, elements[1])
-SETGET_STRUCT_CUSTOM(Transform2D, Vector2, origin, elements[2])
+SETGET_STRUCT_CUSTOM(Transform2D, Vector2, x, columns[0])
+SETGET_STRUCT_CUSTOM(Transform2D, Vector2, y, columns[1])
+SETGET_STRUCT_CUSTOM(Transform2D, Vector2, origin, columns[2])
SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, x, normal.x)
SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, y, normal.y)
@@ -308,9 +308,9 @@ SETGET_NUMBER_STRUCT(Quaternion, double, y)
SETGET_NUMBER_STRUCT(Quaternion, double, z)
SETGET_NUMBER_STRUCT(Quaternion, double, w)
-SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_axis, get_axis, 0)
-SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_axis, get_axis, 1)
-SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_axis, get_axis, 2)
+SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_column, get_column, 0)
+SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_column, get_column, 1)
+SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_column, get_column, 2)
SETGET_STRUCT(Transform3D, Basis, basis)
SETGET_STRUCT(Transform3D, Vector3, origin)
@@ -329,4 +329,8 @@ SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h)
SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s)
SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v)
+SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_h, set_ok_hsl_h, get_ok_hsl_h)
+SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_s, set_ok_hsl_s, get_ok_hsl_s)
+SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_l, set_ok_hsl_l, get_ok_hsl_l)
+
#endif // VARIANT_SETGET_H
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index e83c71098d..66badce268 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -219,10 +219,6 @@ struct VariantUtilityFunctions {
return Math::step_decimals(step);
}
- static inline int range_step_decimals(float step) {
- return Math::range_step_decimals(step);
- }
-
static inline double snapped(double value, double step) {
return Math::snapped(value, step);
}
@@ -439,7 +435,7 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_OK;
if (obj.is_ref_counted()) {
Ref<WeakRef> wref = memnew(WeakRef);
- REF r = obj;
+ Ref<RefCounted> r = obj;
if (r.is_valid()) {
wref->set_ref(r);
}
@@ -474,20 +470,20 @@ struct VariantUtilityFunctions {
r_error.argument = 1;
return String();
}
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
r_error.error = Callable::CallError::CALL_OK;
- return str;
+ return s;
}
static inline String error_string(Error error) {
@@ -499,98 +495,98 @@ struct VariantUtilityFunctions {
}
static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- print_line(str);
+ print_line(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
if (OS::get_singleton()->is_stdout_verbose()) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
// No need to use `print_verbose()` as this call already only happens
// when verbose mode is enabled. This avoids performing string argument concatenation
// when not needed.
- print_line(str);
+ print_line(s);
}
r_error.error = Callable::CallError::CALL_OK;
}
static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- print_error(str);
+ print_error(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
- str += "\t";
+ s += "\t";
}
- str += p_args[i]->operator String();
+ s += p_args[i]->operator String();
}
- print_line(str);
+ print_line(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
- str += " ";
+ s += " ";
}
- str += p_args[i]->operator String();
+ s += p_args[i]->operator String();
}
- print_line(str);
+ print_line(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- OS::get_singleton()->print("%s", str.utf8().get_data());
+ OS::get_singleton()->print("%s", s.utf8().get_data());
r_error.error = Callable::CallError::CALL_OK;
}
@@ -599,18 +595,18 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
}
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- ERR_PRINT(str);
+ ERR_PRINT(s);
r_error.error = Callable::CallError::CALL_OK;
}
@@ -619,18 +615,18 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
}
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- WARN_PRINT(str);
+ WARN_PRINT(s);
r_error.error = Callable::CallError::CALL_OK;
}
@@ -1114,14 +1110,14 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
register_utility_function<Func_##m_func>(#m_func, m_args)
struct VariantUtilityFunctionInfo {
- void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- Variant::ValidatedUtilityFunction validated_call_utility;
- Variant::PTRUtilityFunction ptr_call_utility;
+ void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = nullptr;
+ Variant::ValidatedUtilityFunction validated_call_utility = nullptr;
+ Variant::PTRUtilityFunction ptr_call_utility = nullptr;
Vector<String> argnames;
- bool is_vararg;
- bool returns_value;
- int argcount;
- Variant::Type (*get_arg_type)(int);
+ bool is_vararg = false;
+ bool returns_value = false;
+ int argcount = 0;
+ Variant::Type (*get_arg_type)(int) = nullptr;
Variant::Type return_type;
Variant::UtilityFunctionType type;
};
@@ -1204,7 +1200,6 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(ease, sarray("x", "curve"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDR(range_step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);