summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.h4
-rw-r--r--core/callable.h7
-rw-r--r--core/callable_method_pointer.cpp94
-rw-r--r--core/callable_method_pointer.h292
-rw-r--r--core/class_db.h8
-rw-r--r--core/global_constants.cpp1
-rw-r--r--core/io/marshalls.cpp89
-rw-r--r--core/io/multiplayer_api.cpp2
-rw-r--r--core/io/resource_format_binary.cpp68
-rw-r--r--core/io/resource_loader.cpp2
-rw-r--r--core/math/rect2.h5
-rw-r--r--core/math/vector2.h7
-rw-r--r--core/method_bind.h11
-rw-r--r--core/method_ptrcall.h26
-rw-r--r--core/node_path.h9
-rw-r--r--core/object.cpp26
-rw-r--r--core/os/input_event.cpp2
-rw-r--r--core/packed_data_container.cpp5
-rw-r--r--core/resource.cpp2
-rw-r--r--core/script_debugger_remote.cpp1145
-rw-r--r--core/script_debugger_remote.h316
-rw-r--r--core/type_info.h2
-rw-r--r--core/typedefs.h30
-rw-r--r--core/undo_redo.cpp24
-rw-r--r--core/undo_redo.h10
-rw-r--r--core/ustring.cpp1
-rw-r--r--core/variant.cpp480
-rw-r--r--core/variant.h88
-rw-r--r--core/variant_call.cpp302
-rw-r--r--core/variant_op.cpp628
-rw-r--r--core/variant_parser.cpp91
-rw-r--r--core/variant_parser.h1
32 files changed, 3452 insertions, 326 deletions
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 342c43802e..ae569ea189 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -581,9 +581,9 @@ private:
bool _list_skip_hidden;
};
-class _Marshalls : public Reference {
+class _Marshalls : public Object {
- GDCLASS(_Marshalls, Reference);
+ GDCLASS(_Marshalls, Object);
static _Marshalls *singleton;
diff --git a/core/callable.h b/core/callable.h
index 8ea5377ce8..cecf2264a3 100644
--- a/core/callable.h
+++ b/core/callable.h
@@ -39,10 +39,9 @@ class Object;
class Variant;
class CallableCustom;
-// This is an abstraction of things that can be called
-// it is used for signals and other cases where effient
-// calling of functions is required.
-// It is designed for the standard case (object and method)
+// This is an abstraction of things that can be called.
+// It is used for signals and other cases where efficient calling of functions
+// is required. It is designed for the standard case (object and method)
// but can be optimized or customized.
class Callable {
diff --git a/core/callable_method_pointer.cpp b/core/callable_method_pointer.cpp
new file mode 100644
index 0000000000..8774af6add
--- /dev/null
+++ b/core/callable_method_pointer.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* callable_method_pointer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "callable_method_pointer.h"
+
+bool CallableCustomMethodPointerBase::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
+ const CallableCustomMethodPointerBase *a = static_cast<const CallableCustomMethodPointerBase *>(p_a);
+ const CallableCustomMethodPointerBase *b = static_cast<const CallableCustomMethodPointerBase *>(p_b);
+
+ if (a->comp_size != b->comp_size) {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < a->comp_size; i++) {
+ if (a->comp_ptr[i] != b->comp_ptr[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CallableCustomMethodPointerBase::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) {
+
+ const CallableCustomMethodPointerBase *a = static_cast<const CallableCustomMethodPointerBase *>(p_a);
+ const CallableCustomMethodPointerBase *b = static_cast<const CallableCustomMethodPointerBase *>(p_b);
+
+ if (a->comp_size != b->comp_size) {
+ return a->comp_size < b->comp_size;
+ }
+
+ for (uint32_t i = 0; i < a->comp_size; i++) {
+ if (a->comp_ptr[i] == b->comp_ptr[i]) {
+ continue;
+ }
+
+ return a->comp_ptr[i] < b->comp_ptr[i];
+ }
+
+ return false;
+}
+
+CallableCustom::CompareEqualFunc CallableCustomMethodPointerBase::get_compare_equal_func() const {
+ return compare_equal;
+}
+
+CallableCustom::CompareLessFunc CallableCustomMethodPointerBase::get_compare_less_func() const {
+ return compare_less;
+}
+
+uint32_t CallableCustomMethodPointerBase::hash() const {
+ return h;
+}
+
+void CallableCustomMethodPointerBase::_setup(uint32_t *p_base_ptr, uint32_t p_ptr_size) {
+ comp_ptr = p_base_ptr;
+ comp_size = p_ptr_size / 4;
+
+ // Precompute hash.
+ for (uint32_t i = 0; i < comp_size; i++) {
+ if (i == 0) {
+ h = hash_djb2_one_32(comp_ptr[i]);
+ } else {
+ h = hash_djb2_one_32(comp_ptr[i], h);
+ }
+ }
+}
diff --git a/core/callable_method_pointer.h b/core/callable_method_pointer.h
new file mode 100644
index 0000000000..a931a344e6
--- /dev/null
+++ b/core/callable_method_pointer.h
@@ -0,0 +1,292 @@
+/*************************************************************************/
+/* callable_method_pointer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CALLABLE_METHOD_POINTER_H
+#define CALLABLE_METHOD_POINTER_H
+
+#include "core/callable.h"
+#include "core/hashfuncs.h"
+#include "core/object.h"
+#include "core/simple_type.h"
+
+class CallableCustomMethodPointerBase : public CallableCustom {
+
+ uint32_t *comp_ptr;
+ uint32_t comp_size;
+ uint32_t h;
+#ifdef DEBUG_METHODS_ENABLED
+ const char *text = "";
+#endif
+ static bool compare_equal(const CallableCustom *p_a, const CallableCustom *p_b);
+ static bool compare_less(const CallableCustom *p_a, const CallableCustom *p_b);
+
+protected:
+ void _setup(uint32_t *p_base_ptr, uint32_t p_ptr_size);
+
+public:
+#ifdef DEBUG_METHODS_ENABLED
+ void set_text(const char *p_text) {
+ text = p_text;
+ }
+ virtual String get_as_text() const {
+ return text;
+ }
+#else
+ virtual String get_as_text() const {
+ return String();
+ }
+#endif
+ virtual CompareEqualFunc get_compare_equal_func() const;
+ virtual CompareLessFunc get_compare_less_func() const;
+
+ virtual uint32_t hash() const;
+};
+
+#ifdef DEBUG_METHODS_ENABLED
+
+template <class T>
+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)) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = p_arg_idx;
+ r_error.expected = argtype;
+ }
+
+ return VariantCaster<T>::cast(*p_args[p_arg_idx]);
+ }
+};
+
+template <class T>
+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)) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = p_arg_idx;
+ r_error.expected = argtype;
+ }
+
+ return VariantCaster<T>::cast(*p_args[p_arg_idx]);
+ }
+};
+
+template <class T>
+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)) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = p_arg_idx;
+ r_error.expected = argtype;
+ }
+
+ return VariantCaster<T>::cast(*p_args[p_arg_idx]);
+ }
+};
+
+#endif // DEBUG_METHODS_ENABLED
+
+// GCC 8 raises "parameter 'p_args' set but not used" here, probably using a
+// template version that does not have arguments and thus sees it unused, but
+// obviously the template can be used for functions with and without them, and
+// the optimizer will get rid of it anyway.
+#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
+#endif
+
+template <class T, class... P, size_t... Is>
+void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+ (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+ (p_instance->*p_method)(VariantCaster<P>::cast(p_args[Is])...);
+#endif
+}
+
+#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+template <class T, class... P>
+void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+#ifdef DEBUG_METHODS_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+
+ if ((size_t)p_argcount < sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+ call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class... P>
+class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
+
+ struct Data {
+ T *instance;
+ void (T::*method)(P...);
+ } data;
+
+public:
+ virtual ObjectID get_object() const { return data.instance->get_instance_id(); }
+
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+
+ call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
+ }
+
+ CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
+ zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes.
+ data.instance = p_instance;
+ data.method = p_method;
+ _setup((uint32_t *)&data, sizeof(Data));
+ }
+};
+
+template <class T, class... P>
+Callable create_custom_callable_function_pointer(T *p_instance,
+#ifdef DEBUG_METHODS_ENABLED
+ const char *p_func_text,
+#endif
+ void (T::*p_method)(P...)) {
+
+ typedef CallableCustomMethodPointer<T, P...> CCMP; // Messes with memnew otherwise.
+ CCMP *ccmp = memnew(CCMP(p_instance, p_method));
+#ifdef DEBUG_METHODS_ENABLED
+ ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
+#endif
+ return Callable(ccmp);
+}
+
+// VERSION WITH RETURN
+
+// GCC 8 raises "parameter 'p_args' set but not used" here, probably using a
+// template version that does not have arguments and thus sees it unused, but
+// obviously the template can be used for functions with and without them, and
+// the optimizer will get rid of it anyway.
+#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
+#endif
+
+template <class T, class R, class... P, size_t... Is>
+void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+ r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+ (p_instance->*p_method)(VariantCaster<P>::cast(p_args[Is])...);
+#endif
+}
+
+#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+template <class T, class R, class... P>
+void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+#ifdef DEBUG_METHODS_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+
+ if ((size_t)p_argcount < sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+ call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class R, class... P>
+class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
+
+ struct Data {
+ T *instance;
+ R(T::*method)
+ (P...);
+ } data;
+
+public:
+ virtual ObjectID get_object() const { return data.instance->get_instance_id(); }
+
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+
+ call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
+ }
+
+ CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
+ zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes.
+ data.instance = p_instance;
+ data.method = p_method;
+ _setup((uint32_t *)&data, sizeof(Data));
+ }
+};
+
+template <class T, class R, class... P>
+Callable create_custom_callable_function_pointer(T *p_instance,
+#ifdef DEBUG_METHODS_ENABLED
+ const char *p_func_text,
+#endif
+ R (T::*p_method)(P...)) {
+
+ typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
+ CCMP *ccmp = memnew(CCMP(p_instance, p_method));
+#ifdef DEBUG_METHODS_ENABLED
+ ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
+#endif
+ return Callable(ccmp);
+}
+
+#ifdef DEBUG_METHODS_ENABLED
+#define callable_mp(I, M) create_custom_callable_function_pointer(I, #M, M)
+#else
+#define callable_mp(I, M) create_custom_callable_function_pointer(I, M)
+#endif
+
+#endif // CALLABLE_METHOD_POINTER_H
diff --git a/core/class_db.h b/core/class_db.h
index 404b04f2d0..398eca9132 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -35,13 +35,15 @@
#include "core/object.h"
#include "core/print_string.h"
-/** To bind more then 6 parameters include this:
+/** To bind more then 6 parameters include this:
* #include "core/method_bind_ext.gen.inc"
*/
-#define DEFVAL(m_defval) (m_defval)
+// Makes callable_mp readily available in all classes connecting signals.
+// Needs to come after method_bind and object have been included.
+#include "core/callable_method_pointer.h"
-//#define SIMPLE_METHODDEF
+#define DEFVAL(m_defval) (m_defval)
#ifdef DEBUG_METHODS_ENABLED
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index b990ec9276..3de36dcb9d 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -606,6 +606,7 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM", Variant::TRANSFORM);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME); // 15
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH); // 15
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RID", Variant::_RID);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_OBJECT", Variant::OBJECT);
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index ab88f4d85c..e97c26e05d 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -187,6 +187,18 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4 * 2;
} break; // 5
+ case Variant::VECTOR2I: {
+
+ ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA);
+ Vector2i val;
+ val.x = decode_uint32(&buf[0]);
+ val.y = decode_uint32(&buf[4]);
+ r_variant = val;
+
+ if (r_len)
+ (*r_len) += 4 * 2;
+
+ } break; // 5
case Variant::RECT2: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
@@ -201,6 +213,20 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4 * 4;
} break;
+ case Variant::RECT2I: {
+
+ ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
+ Rect2i val;
+ val.position.x = decode_uint32(&buf[0]);
+ val.position.y = decode_uint32(&buf[4]);
+ val.size.x = decode_uint32(&buf[8]);
+ val.size.y = decode_uint32(&buf[12]);
+ r_variant = val;
+
+ if (r_len)
+ (*r_len) += 4 * 4;
+
+ } break;
case Variant::VECTOR3: {
ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA);
@@ -214,6 +240,19 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4 * 3;
} break;
+ case Variant::VECTOR3I: {
+
+ ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA);
+ Vector3i val;
+ val.x = decode_uint32(&buf[0]);
+ val.y = decode_uint32(&buf[4]);
+ val.z = decode_uint32(&buf[8]);
+ r_variant = val;
+
+ if (r_len)
+ (*r_len) += 4 * 3;
+
+ } break;
case Variant::TRANSFORM2D: {
ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA);
@@ -328,6 +367,16 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4 * 4;
} break;
+ case Variant::STRING_NAME: {
+
+ String str;
+ Error err = _decode_string(buf, len, r_len, str);
+ if (err)
+ return err;
+ r_variant = StringName(str);
+
+ } break;
+
case Variant::NODE_PATH: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
@@ -939,6 +988,11 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
_encode_string(p_variant, buf, r_len);
} break;
+ case Variant::STRING_NAME: {
+
+ _encode_string(p_variant, buf, r_len);
+
+ } break;
// math types
case Variant::VECTOR2: {
@@ -952,6 +1006,17 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 2 * 4;
} break; // 5
+ case Variant::VECTOR2I: {
+
+ if (buf) {
+ Vector2i v2 = p_variant;
+ encode_uint32(v2.x, &buf[0]);
+ encode_uint32(v2.y, &buf[4]);
+ }
+
+ r_len += 2 * 4;
+
+ } break; // 5
case Variant::RECT2: {
if (buf) {
@@ -964,6 +1029,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4 * 4;
} break;
+ case Variant::RECT2I: {
+
+ if (buf) {
+ Rect2i r2 = p_variant;
+ encode_uint32(r2.position.x, &buf[0]);
+ encode_uint32(r2.position.y, &buf[4]);
+ encode_uint32(r2.size.x, &buf[8]);
+ encode_uint32(r2.size.y, &buf[12]);
+ }
+ r_len += 4 * 4;
+
+ } break;
case Variant::VECTOR3: {
if (buf) {
@@ -976,6 +1053,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 3 * 4;
} break;
+ case Variant::VECTOR3I: {
+
+ if (buf) {
+ Vector3i v3 = p_variant;
+ encode_uint32(v3.x, &buf[0]);
+ encode_uint32(v3.y, &buf[4]);
+ encode_uint32(v3.z, &buf[8]);
+ }
+
+ r_len += 3 * 4;
+
+ } break;
case Variant::TRANSFORM2D: {
if (buf) {
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 1fcd00c0e4..6a0eeea513 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -51,7 +51,7 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas
case MultiplayerAPI::RPC_MODE_MASTERSYNC: {
if (is_master)
r_skip_rpc = true; // I am the master, so skip remote call.
- FALLTHROUGH;
+ [[fallthrough]];
}
case MultiplayerAPI::RPC_MODE_REMOTESYNC:
case MultiplayerAPI::RPC_MODE_PUPPETSYNC: {
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 991853e86d..518323c5c4 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -75,6 +75,10 @@ enum {
VARIANT_DOUBLE = 41,
VARIANT_CALLABLE = 42,
VARIANT_SIGNAL = 43,
+ VARIANT_STRING_NAME = 44,
+ VARIANT_VECTOR2I = 45,
+ VARIANT_RECT2I = 46,
+ VARIANT_VECTOR3I = 47,
OBJECT_EMPTY = 0,
OBJECT_EXTERNAL_RESOURCE = 1,
OBJECT_INTERNAL_RESOURCE = 2,
@@ -158,6 +162,14 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
+ case VARIANT_VECTOR2I: {
+
+ Vector2i v;
+ v.x = f->get_32();
+ v.y = f->get_32();
+ r_v = v;
+
+ } break;
case VARIANT_RECT2: {
Rect2 v;
@@ -168,6 +180,16 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
+ case VARIANT_RECT2I: {
+
+ Rect2i v;
+ v.position.x = f->get_32();
+ v.position.y = f->get_32();
+ v.size.x = f->get_32();
+ v.size.y = f->get_32();
+ r_v = v;
+
+ } break;
case VARIANT_VECTOR3: {
Vector3 v;
@@ -176,6 +198,14 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
v.z = f->get_real();
r_v = v;
} break;
+ case VARIANT_VECTOR3I: {
+
+ Vector3i v;
+ v.x = f->get_32();
+ v.y = f->get_32();
+ v.z = f->get_32();
+ r_v = v;
+ } break;
case VARIANT_PLANE: {
Plane v;
@@ -260,6 +290,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
+ case VARIANT_STRING_NAME: {
+
+ r_v = StringName(get_unicode_string());
+ } break;
case VARIANT_NODE_PATH: {
@@ -1288,6 +1322,14 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
f->store_real(val.y);
} break;
+ case Variant::VECTOR2I: {
+
+ f->store_32(VARIANT_VECTOR2I);
+ Vector2i val = p_property;
+ f->store_32(val.x);
+ f->store_32(val.y);
+
+ } break;
case Variant::RECT2: {
f->store_32(VARIANT_RECT2);
@@ -1298,6 +1340,16 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
f->store_real(val.size.y);
} break;
+ case Variant::RECT2I: {
+
+ f->store_32(VARIANT_RECT2I);
+ Rect2i val = p_property;
+ f->store_32(val.position.x);
+ f->store_32(val.position.y);
+ f->store_32(val.size.x);
+ f->store_32(val.size.y);
+
+ } break;
case Variant::VECTOR3: {
f->store_32(VARIANT_VECTOR3);
@@ -1307,6 +1359,15 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
f->store_real(val.z);
} break;
+ case Variant::VECTOR3I: {
+
+ f->store_32(VARIANT_VECTOR3I);
+ Vector3i val = p_property;
+ f->store_32(val.x);
+ f->store_32(val.y);
+ f->store_32(val.z);
+
+ } break;
case Variant::PLANE: {
f->store_32(VARIANT_PLANE);
@@ -1394,6 +1455,13 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
f->store_real(val.a);
} break;
+ case Variant::STRING_NAME: {
+
+ f->store_32(VARIANT_STRING_NAME);
+ String val = p_property;
+ save_unicode_string(f, val);
+
+ } break;
case Variant::NODE_PATH: {
f->store_32(VARIANT_NODE_PATH);
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 1d5d8f9280..39bbebefa6 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -248,7 +248,7 @@ void ResourceFormatLoader::_bind_methods() {
}
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_recognized_extensions"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles_type", PropertyInfo(Variant::STRING, "typename")));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles_type", PropertyInfo(Variant::STRING_NAME, "typename")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type", PropertyInfo(Variant::STRING, "path")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "rename_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "renames")));
diff --git a/core/math/rect2.h b/core/math/rect2.h
index 0d2e7eb6e5..e4ea615c22 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -387,6 +387,11 @@ struct Rect2i {
size = end - begin;
}
+ _FORCE_INLINE_ Rect2i abs() const {
+
+ return Rect2i(Point2i(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());
+ }
+
operator String() const { return String(position) + ", " + String(size); }
operator Rect2() const { return Rect2(position, size); }
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 1dec830821..ba5558102f 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -311,10 +311,15 @@ struct Vector2i {
bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); }
+ bool operator<=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
+ bool operator>=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
+
bool operator==(const Vector2i &p_vec2) const;
bool operator!=(const Vector2i &p_vec2) const;
- real_t get_aspect() const { return width / (real_t)height; }
+ real_t aspect() const { return width / (real_t)height; }
+ Vector2i sign() const { return Vector2i(SGN(x), SGN(y)); }
+ Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); }
operator String() const { return String::num(x) + ", " + String::num(y); }
diff --git a/core/method_bind.h b/core/method_bind.h
index 72be141fd3..726ce512f8 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -31,19 +31,18 @@
#ifndef METHOD_BIND_H
#define METHOD_BIND_H
+#ifdef DEBUG_ENABLED
+#define DEBUG_METHODS_ENABLED
+#endif
+
#include "core/list.h"
#include "core/method_ptrcall.h"
#include "core/object.h"
+#include "core/type_info.h"
#include "core/variant.h"
#include <stdio.h>
-#ifdef DEBUG_ENABLED
-#define DEBUG_METHODS_ENABLED
-#endif
-
-#include "core/type_info.h"
-
enum MethodFlags {
METHOD_FLAG_NORMAL = 1,
diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h
index 42d71dea46..7e21c2cc24 100644
--- a/core/method_ptrcall.h
+++ b/core/method_ptrcall.h
@@ -125,6 +125,7 @@ MAKE_PTRARG_BY_REFERENCE(AABB);
MAKE_PTRARG_BY_REFERENCE(Basis);
MAKE_PTRARG_BY_REFERENCE(Transform);
MAKE_PTRARG_BY_REFERENCE(Color);
+MAKE_PTRARG(StringName);
MAKE_PTRARG(NodePath);
MAKE_PTRARG(RID);
MAKE_PTRARG(Dictionary);
@@ -373,29 +374,7 @@ MAKE_VECARR(Plane);
} \
}
-//MAKE_DVECARR(Plane);
-//for special case StringName
-
-#define MAKE_STRINGCONV(m_type) \
- template <> \
- struct PtrToArg<m_type> { \
- _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
- m_type s = *reinterpret_cast<const String *>(p_ptr); \
- return s; \
- } \
- _FORCE_INLINE_ static void encode(m_type p_vec, void *p_ptr) { \
- String *arr = reinterpret_cast<String *>(p_ptr); \
- *arr = p_vec; \
- } \
- }; \
- \
- template <> \
- struct PtrToArg<const m_type &> { \
- _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
- m_type s = *reinterpret_cast<const String *>(p_ptr); \
- return s; \
- } \
- }
+// Special case for IP_Address.
#define MAKE_STRINGCONV_BY_REFERENCE(m_type) \
template <> \
@@ -418,7 +397,6 @@ MAKE_VECARR(Plane);
} \
}
-MAKE_STRINGCONV(StringName);
MAKE_STRINGCONV_BY_REFERENCE(IP_Address);
template <>
diff --git a/core/node_path.h b/core/node_path.h
index 5439658910..05b6d844ff 100644
--- a/core/node_path.h
+++ b/core/node_path.h
@@ -54,15 +54,6 @@ class NodePath {
void _update_hash_cache() const;
public:
- _FORCE_INLINE_ StringName get_sname() const {
-
- if (data && data->path.size() == 1 && data->subpath.empty()) {
- return data->path[0];
- } else {
- return operator String();
- }
- }
-
bool is_absolute() const;
int get_name_count() const;
StringName get_name(int p_idx) const;
diff --git a/core/object.cpp b/core/object.cpp
index edf7b51543..140ee811fe 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -646,10 +646,10 @@ Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::Cal
return Variant();
}
- if (p_args[0]->get_type() != Variant::STRING) {
+ if (p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
@@ -666,10 +666,10 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Call
return Variant();
}
- if (p_args[0]->get_type() != Variant::STRING) {
+ if (p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
@@ -1108,11 +1108,11 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::C
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
ERR_FAIL_COND_V(p_argcount < 1, Variant());
- if (p_args[0]->get_type() != Variant::STRING) {
+ if (p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::STRING;
- ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING, Variant());
+ r_error.expected = Variant::STRING_NAME;
+ ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING, Variant());
}
r_error.error = Callable::CallError::CALL_OK;
@@ -1207,7 +1207,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) {
//most likely object is not initialized yet, do not throw error.
} else {
- ERR_PRINT("Error calling from signal '" + String(p_name) + "': " + Variant::get_callable_error_text(c.callable, args, argc, ce) + ".");
+ ERR_PRINT("Error calling from signal '" + String(p_name) + "' to callable: " + Variant::get_callable_error_text(c.callable, args, argc, ce) + ".");
err = ERR_METHOD_NOT_FOUND;
}
}
@@ -1669,7 +1669,7 @@ void Object::_bind_methods() {
{
MethodInfo mi;
mi.name = "emit_signal";
- mi.arguments.push_back(PropertyInfo(Variant::STRING, "signal"));
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "signal"));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "emit_signal", &Object::_emit_signal, mi, varray(), false);
}
@@ -1677,7 +1677,7 @@ void Object::_bind_methods() {
{
MethodInfo mi;
mi.name = "call";
- mi.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call", &Object::_call_bind, mi);
}
@@ -1685,7 +1685,7 @@ void Object::_bind_methods() {
{
MethodInfo mi;
mi.name = "call_deferred";
- mi.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi, varray(), false);
}
@@ -1719,9 +1719,9 @@ void Object::_bind_methods() {
ADD_SIGNAL(MethodInfo("script_changed"));
BIND_VMETHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value")));
#ifdef TOOLS_ENABLED
- MethodInfo miget("_get", PropertyInfo(Variant::STRING, "property"));
+ MethodInfo miget("_get", PropertyInfo(Variant::STRING_NAME, "property"));
miget.return_val.name = "Variant";
miget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
BIND_VMETHOD(miget);
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 2e863c9c76..7d1ae872f4 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -1098,7 +1098,7 @@ void InputEventAction::_bind_methods() {
// ClassDB::bind_method(D_METHOD("is_action", "name"), &InputEventAction::is_action);
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action", "get_action");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "action"), "set_action", "get_action");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_strength", "get_strength");
}
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index ae5f89e870..6a4fac971c 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -225,8 +225,8 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
string_cache[s] = tmpdata.size();
- FALLTHROUGH;
- };
+ [[fallthrough]];
+ }
case Variant::NIL:
case Variant::BOOL:
case Variant::INT:
@@ -247,6 +247,7 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
case Variant::PACKED_VECTOR2_ARRAY:
case Variant::PACKED_VECTOR3_ARRAY:
case Variant::PACKED_COLOR_ARRAY:
+ case Variant::STRING_NAME:
case Variant::NODE_PATH: {
uint32_t pos = tmpdata.size();
diff --git a/core/resource.cpp b/core/resource.cpp
index 30e09716aa..2afc9e4042 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -423,7 +423,7 @@ void Resource::_bind_methods() {
ADD_GROUP("Resource", "resource_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resource_local_to_scene"), "set_local_to_scene", "is_local_to_scene");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_path", "get_path");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_name"), "set_name", "get_name");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "resource_name"), "set_name", "get_name");
BIND_VMETHOD(MethodInfo("_setup_local_to_scene"));
}
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
new file mode 100644
index 0000000000..fdb6135edd
--- /dev/null
+++ b/core/script_debugger_remote.cpp
@@ -0,0 +1,1145 @@
+/*************************************************************************/
+/* script_debugger_remote.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "script_debugger_remote.h"
+
+#include "core/engine.h"
+#include "core/io/ip.h"
+#include "core/io/marshalls.h"
+#include "core/os/input.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
+#include "servers/visual_server.h"
+
+#define CHECK_SIZE(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() < (uint32_t)(expected), false, String("Malformed ") + what + " message from script debugger, message too short. Exptected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
+#define CHECK_END(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() > (uint32_t)expected, false, String("Malformed ") + what + " message from script debugger, message too short. Exptected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
+
+Array ScriptDebuggerRemote::ScriptStackDump::serialize() {
+ Array arr;
+ arr.push_back(frames.size() * 3);
+ for (int i = 0; i < frames.size(); i++) {
+ arr.push_back(frames[i].file);
+ arr.push_back(frames[i].line);
+ arr.push_back(frames[i].func);
+ }
+ return arr;
+}
+
+bool ScriptDebuggerRemote::ScriptStackDump::deserialize(const Array &p_arr) {
+ CHECK_SIZE(p_arr, 1, "ScriptStackDump");
+ uint32_t size = p_arr[0];
+ CHECK_SIZE(p_arr, size, "ScriptStackDump");
+ int idx = 1;
+ for (uint32_t i = 0; i < size / 3; i++) {
+ ScriptLanguage::StackInfo sf;
+ sf.file = p_arr[idx];
+ sf.line = p_arr[idx + 1];
+ sf.func = p_arr[idx + 2];
+ frames.push_back(sf);
+ idx += 3;
+ }
+ CHECK_END(p_arr, idx, "ScriptStackDump");
+ return true;
+}
+
+Array ScriptDebuggerRemote::ScriptStackVariable::serialize(int max_size) {
+ Array arr;
+ arr.push_back(name);
+ arr.push_back(type);
+
+ Variant var = value;
+ if (value.get_type() == Variant::OBJECT && value.get_validated_object() == nullptr) {
+ var = Variant();
+ }
+
+ int len = 0;
+ Error err = encode_variant(var, NULL, len, true);
+ if (err != OK)
+ ERR_PRINT("Failed to encode variant.");
+
+ if (len > max_size) {
+ arr.push_back(Variant());
+ } else {
+ arr.push_back(var);
+ }
+ return arr;
+}
+
+bool ScriptDebuggerRemote::ScriptStackVariable::deserialize(const Array &p_arr) {
+ CHECK_SIZE(p_arr, 3, "ScriptStackVariable");
+ name = p_arr[0];
+ type = p_arr[1];
+ value = p_arr[2];
+ CHECK_END(p_arr, 3, "ScriptStackVariable");
+ return true;
+}
+
+Array ScriptDebuggerRemote::OutputError::serialize() {
+ Array arr;
+ arr.push_back(hr);
+ arr.push_back(min);
+ arr.push_back(sec);
+ arr.push_back(msec);
+ arr.push_back(source_file);
+ arr.push_back(source_func);
+ arr.push_back(source_line);
+ arr.push_back(error);
+ arr.push_back(error_descr);
+ arr.push_back(warning);
+ unsigned int size = callstack.size();
+ const ScriptLanguage::StackInfo *r = callstack.ptr();
+ arr.push_back(size * 3);
+ for (int i = 0; i < callstack.size(); i++) {
+ arr.push_back(r[i].file);
+ arr.push_back(r[i].func);
+ arr.push_back(r[i].line);
+ }
+ return arr;
+}
+
+bool ScriptDebuggerRemote::OutputError::deserialize(const Array &p_arr) {
+ CHECK_SIZE(p_arr, 11, "OutputError");
+ hr = p_arr[0];
+ min = p_arr[1];
+ sec = p_arr[2];
+ msec = p_arr[3];
+ source_file = p_arr[4];
+ source_func = p_arr[5];
+ source_line = p_arr[6];
+ error = p_arr[7];
+ error_descr = p_arr[8];
+ warning = p_arr[9];
+ unsigned int stack_size = p_arr[10];
+ CHECK_SIZE(p_arr, stack_size, "OutputError");
+ int idx = 11;
+ callstack.resize(stack_size / 3);
+ ScriptLanguage::StackInfo *w = callstack.ptrw();
+ for (unsigned int i = 0; i < stack_size / 3; i++) {
+ w[i].file = p_arr[idx];
+ w[i].func = p_arr[idx + 1];
+ w[i].line = p_arr[idx + 2];
+ idx += 3;
+ }
+ CHECK_END(p_arr, idx, "OutputError");
+ return true;
+}
+
+Array ScriptDebuggerRemote::ResourceUsage::serialize() {
+ infos.sort();
+
+ Array arr;
+ arr.push_back(infos.size() * 4);
+ for (List<ResourceInfo>::Element *E = infos.front(); E; E = E->next()) {
+ arr.push_back(E->get().path);
+ arr.push_back(E->get().format);
+ arr.push_back(E->get().type);
+ arr.push_back(E->get().vram);
+ }
+ return arr;
+}
+
+bool ScriptDebuggerRemote::ResourceUsage::deserialize(const Array &p_arr) {
+ CHECK_SIZE(p_arr, 1, "ResourceUsage");
+ uint32_t size = p_arr[0];
+ CHECK_SIZE(p_arr, size, "ResourceUsage");
+ int idx = 1;
+ for (uint32_t i = 0; i < size / 4; i++) {
+ ResourceInfo info;
+ info.path = p_arr[idx];
+ info.format = p_arr[idx + 1];
+ info.type = p_arr[idx + 2];
+ info.vram = p_arr[idx + 3];
+ infos.push_back(info);
+ }
+ CHECK_END(p_arr, idx, "ResourceUsage");
+ return true;
+}
+
+Array ScriptDebuggerRemote::ProfilerSignature::serialize() {
+ Array arr;
+ arr.push_back(name);
+ arr.push_back(id);
+ return arr;
+}
+
+bool ScriptDebuggerRemote::ProfilerSignature::deserialize(const Array &p_arr) {
+ CHECK_SIZE(p_arr, 2, "ProfilerSignature");
+ name = p_arr[0];
+ id = p_arr[1];
+ CHECK_END(p_arr, 2, "ProfilerSignature");
+ return true;
+}
+
+Array ScriptDebuggerRemote::ProfilerFrame::serialize() {
+ Array arr;
+ arr.push_back(frame_number);
+ arr.push_back(frame_time);
+ arr.push_back(idle_time);
+ arr.push_back(physics_time);
+ arr.push_back(physics_frame_time);
+ arr.push_back(USEC_TO_SEC(script_time));
+
+ arr.push_back(frames_data.size());
+ arr.push_back(frame_functions.size() * 4);
+
+ // Servers profiling info.
+ for (int i = 0; i < frames_data.size(); i++) {
+ arr.push_back(frames_data[i].name); // Type (physics/process/audio/...)
+ arr.push_back(frames_data[i].data.size());
+ for (int j = 0; j < frames_data[i].data.size() / 2; j++) {
+ arr.push_back(frames_data[i].data[2 * j]); // NAME
+ arr.push_back(frames_data[i].data[2 * j + 1]); // TIME
+ }
+ }
+ for (int i = 0; i < frame_functions.size(); i++) {
+ arr.push_back(frame_functions[i].sig_id);
+ arr.push_back(frame_functions[i].call_count);
+ arr.push_back(frame_functions[i].self_time);
+ arr.push_back(frame_functions[i].total_time);
+ }
+ return arr;
+}
+
+bool ScriptDebuggerRemote::ProfilerFrame::deserialize(const Array &p_arr) {
+ CHECK_SIZE(p_arr, 8, "ProfilerFrame");
+ frame_number = p_arr[0];
+ frame_time = p_arr[1];
+ idle_time = p_arr[2];
+ physics_time = p_arr[3];
+ physics_frame_time = p_arr[4];
+ script_time = p_arr[5];
+ uint32_t frame_data_size = p_arr[6];
+ int frame_func_size = p_arr[7];
+ int idx = 8;
+ while (frame_data_size) {
+ CHECK_SIZE(p_arr, idx + 2, "ProfilerFrame");
+ frame_data_size--;
+ FrameData fd;
+ fd.name = p_arr[idx];
+ int sub_data_size = p_arr[idx + 1];
+ idx += 2;
+ CHECK_SIZE(p_arr, idx + sub_data_size, "ProfilerFrame");
+ for (int j = 0; j < sub_data_size / 2; j++) {
+ fd.data.push_back(p_arr[idx]); // NAME
+ fd.data.push_back(p_arr[idx + 1]); // TIME
+ idx += 2;
+ }
+ frames_data.push_back(fd);
+ }
+ CHECK_SIZE(p_arr, idx + frame_func_size, "ProfilerFrame");
+ for (int i = 0; i < frame_func_size / 4; i++) {
+ FrameFunction ff;
+ ff.sig_id = p_arr[idx];
+ ff.call_count = p_arr[idx + 1];
+ ff.self_time = p_arr[idx + 2];
+ ff.total_time = p_arr[idx + 3];
+ frame_functions.push_back(ff);
+ idx += 4;
+ }
+ CHECK_END(p_arr, idx, "ProfilerFrame");
+ return true;
+}
+
+Array ScriptDebuggerRemote::NetworkProfilerFrame::serialize() {
+ Array arr;
+ arr.push_back(infos.size() * 6);
+ for (int i = 0; i < infos.size(); ++i) {
+ arr.push_back(uint64_t(infos[i].node));
+ arr.push_back(infos[i].node_path);
+ arr.push_back(infos[i].incoming_rpc);
+ arr.push_back(infos[i].incoming_rset);
+ arr.push_back(infos[i].outgoing_rpc);
+ arr.push_back(infos[i].outgoing_rset);
+ }
+ return arr;
+}
+
+bool ScriptDebuggerRemote::NetworkProfilerFrame::deserialize(const Array &p_arr) {
+ CHECK_SIZE(p_arr, 1, "NetworkProfilerFrame");
+ uint32_t size = p_arr[0];
+ CHECK_SIZE(p_arr, size, "NetworkProfilerFrame");
+ infos.resize(size);
+ int idx = 1;
+ for (uint32_t i = 0; i < size / 6; ++i) {
+ infos.write[i].node = uint64_t(p_arr[idx]);
+ infos.write[i].node_path = p_arr[idx + 1];
+ infos.write[i].incoming_rpc = p_arr[idx + 2];
+ infos.write[i].incoming_rset = p_arr[idx + 3];
+ infos.write[i].outgoing_rpc = p_arr[idx + 4];
+ infos.write[i].outgoing_rset = p_arr[idx + 5];
+ }
+ CHECK_END(p_arr, idx, "NetworkProfilerFrame");
+ return true;
+}
+
+void ScriptDebuggerRemote::_put_msg(String p_message, Array p_data) {
+ Array msg;
+ msg.push_back(p_message);
+ msg.push_back(p_data);
+ packet_peer_stream->put_var(msg);
+}
+
+bool ScriptDebuggerRemote::is_peer_connected() {
+ return tcp_client->is_connected_to_host() && tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED;
+}
+
+void ScriptDebuggerRemote::_send_video_memory() {
+
+ ResourceUsage usage;
+ if (resource_usage_func)
+ resource_usage_func(&usage);
+
+ _put_msg("message:video_mem", usage.serialize());
+}
+
+Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_port) {
+
+ IP_Address ip;
+ if (p_host.is_valid_ip_address())
+ ip = p_host;
+ else
+ ip = IP::get_singleton()->resolve_hostname(p_host);
+
+ int port = p_port;
+
+ const int tries = 6;
+ int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
+
+ tcp_client->connect_to_host(ip, port);
+
+ for (int i = 0; i < tries; i++) {
+
+ if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
+ print_verbose("Remote Debugger: Connected!");
+ break;
+ } else {
+
+ const int ms = waits[i];
+ OS::get_singleton()->delay_usec(ms * 1000);
+ print_verbose("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec.");
+ };
+ };
+
+ if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
+
+ ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + ".");
+ return FAILED;
+ };
+
+ packet_peer_stream->set_stream_peer(tcp_client);
+ Array msg;
+ msg.push_back(OS::get_singleton()->get_process_id());
+ send_message("set_pid", msg);
+
+ return OK;
+}
+
+void ScriptDebuggerRemote::_parse_message(const String p_command, const Array &p_data, ScriptLanguage *p_script) {
+
+ if (p_command == "request_video_mem") {
+ _send_video_memory();
+
+ } else if (p_command == "start_profiling") {
+ ERR_FAIL_COND(p_data.size() < 1);
+
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->profiling_start();
+ }
+
+ max_frame_functions = p_data[0];
+ profiler_function_signature_map.clear();
+ profiling = true;
+ frame_time = 0;
+ idle_time = 0;
+ physics_time = 0;
+ physics_frame_time = 0;
+ print_line("PROFILING ALRIGHT!");
+
+ } else if (p_command == "stop_profiling") {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->profiling_stop();
+ }
+ profiling = false;
+ _send_profiling_data(false);
+ print_line("PROFILING END!");
+
+ } else if (p_command == "start_visual_profiling") {
+
+ visual_profiling = true;
+ VS::get_singleton()->set_frame_profiling_enabled(true);
+ } else if (p_command == "stop_visual_profiling") {
+
+ visual_profiling = false;
+ VS::get_singleton()->set_frame_profiling_enabled(false);
+
+ } else if (p_command == "start_network_profiling") {
+
+ network_profiling = true;
+ multiplayer->profiling_start();
+
+ } else if (p_command == "stop_network_profiling") {
+
+ network_profiling = false;
+ multiplayer->profiling_end();
+
+ } else if (p_command == "reload_scripts") {
+ reload_all_scripts = true;
+
+ } else if (p_command == "breakpoint") {
+ ERR_FAIL_COND(p_data.size() < 3);
+ bool set = p_data[2];
+ if (set)
+ insert_breakpoint(p_data[1], p_data[0]);
+ else
+ remove_breakpoint(p_data[1], p_data[0]);
+
+ } else if (p_command == "set_skip_breakpoints") {
+ ERR_FAIL_COND(p_data.size() < 1);
+ skip_breakpoints = p_data[0];
+
+ } else if (p_command == "get_stack_dump") {
+ ERR_FAIL_COND(!p_script);
+ ScriptStackDump dump;
+ int slc = p_script->debug_get_stack_level_count();
+ for (int i = 0; i < slc; i++) {
+ ScriptLanguage::StackInfo frame;
+ frame.file = p_script->debug_get_stack_level_source(i);
+ frame.line = p_script->debug_get_stack_level_line(i);
+ frame.func = p_script->debug_get_stack_level_function(i);
+ dump.frames.push_back(frame);
+ }
+ _put_msg("stack_dump", dump.serialize());
+
+ } else if (p_command == "get_stack_frame_vars") {
+ ERR_FAIL_COND(p_data.size() != 1);
+ ERR_FAIL_COND(!p_script);
+ int lv = p_data[0];
+
+ List<String> members;
+ List<Variant> member_vals;
+ if (ScriptInstance *inst = p_script->debug_get_stack_level_instance(lv)) {
+ members.push_back("self");
+ member_vals.push_back(inst->get_owner());
+ }
+ p_script->debug_get_stack_level_members(lv, &members, &member_vals);
+ ERR_FAIL_COND(members.size() != member_vals.size());
+
+ List<String> locals;
+ List<Variant> local_vals;
+ p_script->debug_get_stack_level_locals(lv, &locals, &local_vals);
+ ERR_FAIL_COND(locals.size() != local_vals.size());
+
+ List<String> globals;
+ List<Variant> globals_vals;
+ p_script->debug_get_globals(&globals, &globals_vals);
+ ERR_FAIL_COND(globals.size() != globals_vals.size());
+
+ _put_msg("stack_frame_vars", Array());
+
+ ScriptStackVariable stvar;
+ { //locals
+ List<String>::Element *E = locals.front();
+ List<Variant>::Element *F = local_vals.front();
+ while (E) {
+ stvar.name = E->get();
+ stvar.value = F->get();
+ stvar.type = 0;
+ _put_msg("stack_frame_var", stvar.serialize());
+
+ E = E->next();
+ F = F->next();
+ }
+ }
+
+ { //members
+ List<String>::Element *E = members.front();
+ List<Variant>::Element *F = member_vals.front();
+ while (E) {
+ stvar.name = E->get();
+ stvar.value = F->get();
+ stvar.type = 1;
+ _put_msg("stack_frame_var", stvar.serialize());
+
+ E = E->next();
+ F = F->next();
+ }
+ }
+
+ { //globals
+ List<String>::Element *E = globals.front();
+ List<Variant>::Element *F = globals_vals.front();
+ while (E) {
+ stvar.name = E->get();
+ stvar.value = F->get();
+ stvar.type = 2;
+ _put_msg("stack_frame_var", stvar.serialize());
+
+ E = E->next();
+ F = F->next();
+ }
+ }
+
+ } else {
+ if (scene_tree_parse_func) {
+ scene_tree_parse_func(p_command, p_data);
+ }
+ // Unknown message...
+ }
+}
+
+void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue, bool p_is_error_breakpoint) {
+
+ //this function is called when there is a debugger break (bug on script)
+ //or when execution is paused from editor
+
+ if (skip_breakpoints && !p_is_error_breakpoint)
+ return;
+
+ ERR_FAIL_COND_MSG(!is_peer_connected(), "Script Debugger failed to connect, but being used anyway.");
+
+ Array msg;
+ msg.push_back(p_can_continue);
+ msg.push_back(p_script->debug_get_error());
+ _put_msg("debug_enter", msg);
+
+ skip_profile_frame = true; // to avoid super long frame time for the frame
+
+ Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode();
+ if (mouse_mode != Input::MOUSE_MODE_VISIBLE)
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+
+ uint64_t loop_begin_usec = 0;
+ uint64_t loop_time_sec = 0;
+ while (true) {
+ loop_begin_usec = OS::get_singleton()->get_ticks_usec();
+
+ _get_output();
+
+ if (packet_peer_stream->get_available_packet_count() > 0) {
+
+ Variant var;
+ Error err = packet_peer_stream->get_var(var);
+
+ ERR_CONTINUE(err != OK);
+ ERR_CONTINUE(var.get_type() != Variant::ARRAY);
+
+ Array cmd = var;
+
+ ERR_CONTINUE(cmd.size() != 2);
+ ERR_CONTINUE(cmd[0].get_type() != Variant::STRING);
+ ERR_CONTINUE(cmd[1].get_type() != Variant::ARRAY);
+
+ String command = cmd[0];
+ Array data = cmd[1];
+ if (command == "step") {
+
+ set_depth(-1);
+ set_lines_left(1);
+ break;
+ } else if (command == "next") {
+
+ set_depth(0);
+ set_lines_left(1);
+ break;
+
+ } else if (command == "continue") {
+ set_depth(-1);
+ set_lines_left(-1);
+ OS::get_singleton()->move_window_to_foreground();
+ break;
+ } else if (command == "break") {
+ ERR_PRINT("Got break when already broke!");
+ break;
+ }
+
+ _parse_message(command, data, p_script);
+ } else {
+ OS::get_singleton()->delay_usec(10000);
+ OS::get_singleton()->process_and_drop_events();
+ }
+
+ // This is for the camera override to stay live even when the game is paused from the editor
+ loop_time_sec = (OS::get_singleton()->get_ticks_usec() - loop_begin_usec) / 1000000.0f;
+ VisualServer::get_singleton()->sync();
+ if (VisualServer::get_singleton()->has_changed()) {
+ VisualServer::get_singleton()->draw(true, loop_time_sec * Engine::get_singleton()->get_time_scale());
+ }
+ }
+
+ _put_msg("debug_exit", Array());
+
+ if (mouse_mode != Input::MOUSE_MODE_VISIBLE)
+ Input::get_singleton()->set_mouse_mode(mouse_mode);
+}
+
+void ScriptDebuggerRemote::_get_output() {
+
+ mutex->lock();
+ if (output_strings.size()) {
+
+ locking = true;
+
+ while (output_strings.size()) {
+
+ Array arr;
+ arr.push_back(output_strings.front()->get());
+ _put_msg("output", arr);
+ output_strings.pop_front();
+ }
+ locking = false;
+ }
+
+ if (n_messages_dropped > 0) {
+ Message msg;
+ msg.message = "Too many messages! " + String::num_int64(n_messages_dropped) + " messages were dropped.";
+ messages.push_back(msg);
+ n_messages_dropped = 0;
+ }
+
+ while (messages.size()) {
+ locking = true;
+ Message msg = messages.front()->get();
+ _put_msg("message:" + msg.message, msg.data);
+ messages.pop_front();
+ locking = false;
+ }
+
+ if (n_errors_dropped == 1) {
+ // Only print one message about dropping per second
+ OutputError oe;
+ oe.error = "TOO_MANY_ERRORS";
+ oe.error_descr = "Too many errors! Ignoring errors for up to 1 second.";
+ oe.warning = false;
+ uint64_t time = OS::get_singleton()->get_ticks_msec();
+ oe.hr = time / 3600000;
+ oe.min = (time / 60000) % 60;
+ oe.sec = (time / 1000) % 60;
+ oe.msec = time % 1000;
+ errors.push_back(oe);
+ }
+
+ if (n_warnings_dropped == 1) {
+ // Only print one message about dropping per second
+ OutputError oe;
+ oe.error = "TOO_MANY_WARNINGS";
+ oe.error_descr = "Too many warnings! Ignoring warnings for up to 1 second.";
+ oe.warning = true;
+ uint64_t time = OS::get_singleton()->get_ticks_msec();
+ oe.hr = time / 3600000;
+ oe.min = (time / 60000) % 60;
+ oe.sec = (time / 1000) % 60;
+ oe.msec = time % 1000;
+ errors.push_back(oe);
+ }
+
+ while (errors.size()) {
+ locking = true;
+ OutputError oe = errors.front()->get();
+ _put_msg("error", oe.serialize());
+ errors.pop_front();
+ locking = false;
+ }
+ mutex->unlock();
+}
+
+void ScriptDebuggerRemote::line_poll() {
+
+ //the purpose of this is just processing events every now and then when the script might get too busy
+ //otherwise bugs like infinite loops can't be caught
+ if (poll_every % 2048 == 0)
+ _poll_events();
+ poll_every++;
+}
+
+void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type) {
+
+ if (p_type == ERR_HANDLER_SCRIPT)
+ return; //ignore script errors, those go through debugger
+
+ Vector<ScriptLanguage::StackInfo> si;
+
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ si = ScriptServer::get_language(i)->debug_get_current_stack_info();
+ if (si.size())
+ break;
+ }
+
+ ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)ud;
+ sdr->send_error(p_func, p_file, p_line, p_err, p_descr, p_type, si);
+}
+
+void ScriptDebuggerRemote::_poll_events() {
+
+ //this si called from ::idle_poll, happens only when running the game,
+ //does not get called while on debug break
+
+ while (packet_peer_stream->get_available_packet_count() > 0) {
+
+ _get_output();
+
+ //send over output_strings
+
+ Variant var;
+ Error err = packet_peer_stream->get_var(var);
+
+ ERR_CONTINUE(err != OK);
+ ERR_CONTINUE(var.get_type() != Variant::ARRAY);
+
+ Array cmd = var;
+
+ ERR_CONTINUE(cmd.size() < 2);
+ ERR_CONTINUE(cmd[0].get_type() != Variant::STRING);
+ ERR_CONTINUE(cmd[1].get_type() != Variant::ARRAY);
+
+ String command = cmd[0];
+ Array data = cmd[1];
+
+ if (command == "break") {
+
+ if (get_break_language())
+ debug(get_break_language());
+ } else {
+ _parse_message(command, data);
+ }
+ }
+}
+
+void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) {
+
+ int ofs = 0;
+
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ if (p_for_frame)
+ ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&profile_info.write[ofs], profile_info.size() - ofs);
+ else
+ ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&profile_info.write[ofs], profile_info.size() - ofs);
+ }
+
+ for (int i = 0; i < ofs; i++) {
+ profile_info_ptrs.write[i] = &profile_info.write[i];
+ }
+
+ SortArray<ScriptLanguage::ProfilingInfo *, ProfileInfoSort> sa;
+ sa.sort(profile_info_ptrs.ptrw(), ofs);
+
+ int to_send = MIN(ofs, max_frame_functions);
+
+ //check signatures first
+ uint64_t total_script_time = 0;
+
+ for (int i = 0; i < to_send; i++) {
+
+ if (!profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) {
+
+ int idx = profiler_function_signature_map.size();
+ ProfilerSignature sig;
+ sig.name = profile_info_ptrs[i]->signature;
+ sig.id = idx;
+ _put_msg("profile_sig", sig.serialize());
+ profiler_function_signature_map[profile_info_ptrs[i]->signature] = idx;
+ }
+
+ total_script_time += profile_info_ptrs[i]->self_time;
+ }
+
+ //send frames then
+ ProfilerFrame metric;
+ metric.frame_number = Engine::get_singleton()->get_frames_drawn();
+ metric.frame_time = frame_time;
+ metric.idle_time = idle_time;
+ metric.physics_time = physics_time;
+ metric.physics_frame_time = physics_frame_time;
+ metric.script_time = total_script_time;
+
+ // Add script functions information.
+ metric.frame_functions.resize(to_send);
+ FrameFunction *w = metric.frame_functions.ptrw();
+ for (int i = 0; i < to_send; i++) {
+
+ if (profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) {
+ w[i].sig_id = profiler_function_signature_map[profile_info_ptrs[i]->signature];
+ }
+
+ w[i].call_count = profile_info_ptrs[i]->call_count;
+ w[i].total_time = profile_info_ptrs[i]->total_time / 1000000.0;
+ w[i].self_time = profile_info_ptrs[i]->self_time / 1000000.0;
+ }
+ if (p_for_frame) {
+ // Add profile frame data information.
+ metric.frames_data.append_array(profile_frame_data);
+ _put_msg("profile_frame", metric.serialize());
+ profile_frame_data.clear();
+ } else {
+ _put_msg("profile_total", metric.serialize());
+ }
+}
+
+void ScriptDebuggerRemote::idle_poll() {
+
+ // this function is called every frame, except when there is a debugger break (::debug() in this class)
+ // execution stops and remains in the ::debug function
+
+ _get_output();
+
+ if (requested_quit) {
+
+ _put_msg("kill_me", Array());
+ requested_quit = false;
+ }
+
+ if (performance) {
+
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_perf_time > 1000) {
+
+ last_perf_time = pt;
+ int max = performance->get("MONITOR_MAX");
+ Array arr;
+ arr.resize(max);
+ for (int i = 0; i < max; i++) {
+ arr[i] = performance->call("get_monitor", i);
+ }
+ _put_msg("performance", arr);
+ }
+ }
+
+ if (visual_profiling) {
+ Vector<VS::FrameProfileArea> profile_areas = VS::get_singleton()->get_frame_profile();
+ if (profile_areas.size()) {
+ Vector<String> area_names;
+ Vector<real_t> area_times;
+ area_names.resize(profile_areas.size());
+ area_times.resize(profile_areas.size() * 2);
+ {
+ String *area_namesw = area_names.ptrw();
+ real_t *area_timesw = area_times.ptrw();
+
+ for (int i = 0; i < profile_areas.size(); i++) {
+ area_namesw[i] = profile_areas[i].name;
+ area_timesw[i * 2 + 0] = profile_areas[i].cpu_msec;
+ area_timesw[i * 2 + 1] = profile_areas[i].gpu_msec;
+ }
+ }
+ Array msg;
+ msg.push_back(VS::get_singleton()->get_frame_profile_frame());
+ msg.push_back(area_names);
+ msg.push_back(area_times);
+ _put_msg("visual_profile", msg);
+ }
+ }
+
+ if (profiling) {
+
+ if (skip_profile_frame) {
+ skip_profile_frame = false;
+ } else {
+ //send profiling info normally
+ _send_profiling_data(true);
+ }
+ }
+
+ if (network_profiling) {
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_net_bandwidth_time > 200) {
+ last_net_bandwidth_time = pt;
+ _send_network_bandwidth_usage();
+ }
+ if (pt - last_net_prof_time > 100) {
+ last_net_prof_time = pt;
+ _send_network_profiling_data();
+ }
+ }
+
+ if (reload_all_scripts) {
+
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->reload_all_scripts();
+ }
+ reload_all_scripts = false;
+ }
+
+ _poll_events();
+}
+
+void ScriptDebuggerRemote::_send_network_profiling_data() {
+ ERR_FAIL_COND(multiplayer.is_null());
+
+ int n_nodes = multiplayer->get_profiling_frame(&network_profile_info.write[0]);
+
+ NetworkProfilerFrame frame;
+ for (int i = 0; i < n_nodes; i++) {
+ frame.infos.push_back(network_profile_info[i]);
+ }
+ _put_msg("network_profile", frame.serialize());
+}
+
+void ScriptDebuggerRemote::_send_network_bandwidth_usage() {
+ ERR_FAIL_COND(multiplayer.is_null());
+
+ int incoming_bandwidth = multiplayer->get_incoming_bandwidth_usage();
+ int outgoing_bandwidth = multiplayer->get_outgoing_bandwidth_usage();
+
+ Array arr;
+ arr.push_back(incoming_bandwidth);
+ arr.push_back(outgoing_bandwidth);
+ _put_msg("network_bandwidth", arr);
+}
+
+void ScriptDebuggerRemote::send_message(const String &p_message, const Array &p_args) {
+
+ mutex->lock();
+ if (!locking && is_peer_connected()) {
+
+ if (messages.size() >= max_messages_per_frame) {
+ n_messages_dropped++;
+ } else {
+ Message msg;
+ msg.message = p_message;
+ msg.data = p_args;
+ messages.push_back(msg);
+ }
+ }
+ mutex->unlock();
+}
+
+void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) {
+
+ OutputError oe;
+ oe.error = p_err;
+ oe.error_descr = p_descr;
+ oe.source_file = p_file;
+ oe.source_line = p_line;
+ oe.source_func = p_func;
+ oe.warning = p_type == ERR_HANDLER_WARNING;
+ uint64_t time = OS::get_singleton()->get_ticks_msec();
+ oe.hr = time / 3600000;
+ oe.min = (time / 60000) % 60;
+ oe.sec = (time / 1000) % 60;
+ oe.msec = time % 1000;
+ Array cstack;
+
+ uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000;
+ msec_count += ticks - last_msec;
+ last_msec = ticks;
+
+ if (msec_count > 1000) {
+ msec_count = 0;
+
+ err_count = 0;
+ n_errors_dropped = 0;
+ warn_count = 0;
+ n_warnings_dropped = 0;
+ }
+
+ cstack.resize(p_stack_info.size() * 3);
+ for (int i = 0; i < p_stack_info.size(); i++) {
+ cstack[i * 3 + 0] = p_stack_info[i].file;
+ cstack[i * 3 + 1] = p_stack_info[i].func;
+ cstack[i * 3 + 2] = p_stack_info[i].line;
+ }
+
+ //oe.callstack = cstack;
+ if (oe.warning) {
+ warn_count++;
+ } else {
+ err_count++;
+ }
+
+ mutex->lock();
+
+ if (!locking && is_peer_connected()) {
+
+ if (oe.warning) {
+ if (warn_count > max_warnings_per_second) {
+ n_warnings_dropped++;
+ } else {
+ errors.push_back(oe);
+ }
+ } else {
+ if (err_count > max_errors_per_second) {
+ n_errors_dropped++;
+ } else {
+ errors.push_back(oe);
+ }
+ }
+ }
+
+ mutex->unlock();
+}
+
+void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string, bool p_error) {
+
+ ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)p_this;
+
+ uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000;
+ sdr->msec_count += ticks - sdr->last_msec;
+ sdr->last_msec = ticks;
+
+ if (sdr->msec_count > 1000) {
+ sdr->char_count = 0;
+ sdr->msec_count = 0;
+ }
+
+ String s = p_string;
+ int allowed_chars = MIN(MAX(sdr->max_cps - sdr->char_count, 0), s.length());
+
+ if (allowed_chars == 0)
+ return;
+
+ if (allowed_chars < s.length()) {
+ s = s.substr(0, allowed_chars);
+ }
+
+ sdr->char_count += allowed_chars;
+ bool overflowed = sdr->char_count >= sdr->max_cps;
+
+ sdr->mutex->lock();
+ if (!sdr->locking && sdr->is_peer_connected()) {
+
+ if (overflowed)
+ s += "[...]";
+
+ sdr->output_strings.push_back(s);
+
+ if (overflowed) {
+ sdr->output_strings.push_back("[output overflow, print less text!]");
+ }
+ }
+ sdr->mutex->unlock();
+}
+
+void ScriptDebuggerRemote::request_quit() {
+
+ requested_quit = true;
+}
+
+void ScriptDebuggerRemote::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
+ multiplayer = p_multiplayer;
+}
+
+bool ScriptDebuggerRemote::is_profiling() const {
+
+ return profiling;
+}
+void ScriptDebuggerRemote::add_profiling_frame_data(const StringName &p_name, const Array &p_data) {
+
+ int idx = -1;
+ for (int i = 0; i < profile_frame_data.size(); i++) {
+ if (profile_frame_data[i].name == p_name) {
+ idx = i;
+ break;
+ }
+ }
+
+ FrameData fd;
+ fd.name = p_name;
+ fd.data = p_data;
+
+ if (idx == -1) {
+ profile_frame_data.push_back(fd);
+ } else {
+ profile_frame_data.write[idx] = fd;
+ }
+}
+
+void ScriptDebuggerRemote::profiling_start() {
+ //ignores this, uses it via connection
+}
+
+void ScriptDebuggerRemote::profiling_end() {
+ //ignores this, uses it via connection
+}
+
+void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+
+ frame_time = p_frame_time;
+ idle_time = p_idle_time;
+ physics_time = p_physics_time;
+ physics_frame_time = p_physics_frame_time;
+}
+
+void ScriptDebuggerRemote::set_skip_breakpoints(bool p_skip_breakpoints) {
+ skip_breakpoints = p_skip_breakpoints;
+}
+
+ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func = NULL;
+ScriptDebuggerRemote::ParseMessageFunc ScriptDebuggerRemote::scene_tree_parse_func = NULL;
+
+ScriptDebuggerRemote::ScriptDebuggerRemote() :
+ profiling(false),
+ visual_profiling(false),
+ network_profiling(false),
+ max_frame_functions(16),
+ skip_profile_frame(false),
+ reload_all_scripts(false),
+ tcp_client(Ref<StreamPeerTCP>(memnew(StreamPeerTCP))),
+ packet_peer_stream(Ref<PacketPeerStream>(memnew(PacketPeerStream))),
+ last_perf_time(0),
+ last_net_prof_time(0),
+ last_net_bandwidth_time(0),
+ performance(Engine::get_singleton()->get_singleton_object("Performance")),
+ requested_quit(false),
+ mutex(Mutex::create()),
+ max_messages_per_frame(GLOBAL_GET("network/limits/debugger_stdout/max_messages_per_frame")),
+ n_messages_dropped(0),
+ max_errors_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_errors_per_second")),
+ max_warnings_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_warnings_per_second")),
+ n_errors_dropped(0),
+ max_cps(GLOBAL_GET("network/limits/debugger_stdout/max_chars_per_second")),
+ char_count(0),
+ err_count(0),
+ warn_count(0),
+ last_msec(0),
+ msec_count(0),
+ locking(false),
+ poll_every(0) {
+
+ packet_peer_stream->set_stream_peer(tcp_client);
+ packet_peer_stream->set_output_buffer_max_size((1024 * 1024 * 8) - 4); // 8 MiB should be way more than enough, minus 4 bytes for separator.
+
+ phl.printfunc = _print_handler;
+ phl.userdata = this;
+ add_print_handler(&phl);
+
+ eh.errfunc = _err_handler;
+ eh.userdata = this;
+ add_error_handler(&eh);
+
+ profile_info.resize(GLOBAL_GET("debug/settings/profiler/max_functions"));
+ network_profile_info.resize(GLOBAL_GET("debug/settings/profiler/max_functions"));
+ profile_info_ptrs.resize(profile_info.size());
+}
+
+ScriptDebuggerRemote::~ScriptDebuggerRemote() {
+
+ remove_print_handler(&phl);
+ remove_error_handler(&eh);
+ memdelete(mutex);
+}
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
new file mode 100644
index 0000000000..682da1d276
--- /dev/null
+++ b/core/script_debugger_remote.h
@@ -0,0 +1,316 @@
+/*************************************************************************/
+/* script_debugger_remote.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SCRIPT_DEBUGGER_REMOTE_H
+#define SCRIPT_DEBUGGER_REMOTE_H
+
+#include "core/io/packet_peer.h"
+#include "core/io/stream_peer_tcp.h"
+#include "core/list.h"
+#include "core/os/os.h"
+#include "core/script_language.h"
+
+class ScriptDebuggerRemote : public ScriptDebugger {
+
+public:
+ class ResourceInfo {
+ public:
+ String path;
+ String format;
+ String type;
+ RID id;
+ int vram;
+ bool operator<(const ResourceInfo &p_img) const { return vram == p_img.vram ? id < p_img.id : vram > p_img.vram; }
+ ResourceInfo() {
+ vram = 0;
+ }
+ };
+
+ class ResourceUsage {
+ public:
+ List<ResourceInfo> infos;
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+ class FrameInfo {
+ public:
+ StringName name;
+ float self_time;
+ float total_time;
+
+ FrameInfo() {
+ self_time = 0;
+ total_time = 0;
+ }
+ };
+
+ class FrameFunction {
+ public:
+ int sig_id;
+ int call_count;
+ StringName name;
+ float self_time;
+ float total_time;
+
+ FrameFunction() {
+ sig_id = -1;
+ call_count = 0;
+ self_time = 0;
+ total_time = 0;
+ }
+ };
+
+ class ScriptStackVariable {
+ public:
+ String name;
+ Variant value;
+ int type;
+ ScriptStackVariable() {
+ type = -1;
+ }
+
+ Array serialize(int max_size = 1 << 20); // 1 MiB default.
+ bool deserialize(const Array &p_arr);
+ };
+
+ class ScriptStackDump {
+ public:
+ List<ScriptLanguage::StackInfo> frames;
+ ScriptStackDump() {}
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+ class Message {
+
+ public:
+ String message;
+ Array data;
+
+ Message() {}
+ };
+
+ class OutputError {
+ public:
+ int hr;
+ int min;
+ int sec;
+ int msec;
+ String source_file;
+ String source_func;
+ int source_line;
+ String error;
+ String error_descr;
+ bool warning;
+ Vector<ScriptLanguage::StackInfo> callstack;
+
+ OutputError() {
+ hr = -1;
+ min = -1;
+ sec = -1;
+ msec = -1;
+ source_line = -1;
+ warning = false;
+ }
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+ struct FrameData {
+
+ StringName name;
+ Array data;
+ };
+
+ class ProfilerSignature {
+ public:
+ StringName name;
+ int id;
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+
+ ProfilerSignature() {
+ id = -1;
+ };
+ };
+
+ class ProfilerFrame {
+ public:
+ int frame_number;
+ float frame_time;
+ float idle_time;
+ float physics_time;
+ float physics_frame_time;
+ float script_time;
+
+ Vector<FrameData> frames_data;
+ Vector<FrameFunction> frame_functions;
+
+ ProfilerFrame() {
+ frame_number = 0;
+ frame_time = 0;
+ idle_time = 0;
+ physics_time = 0;
+ physics_frame_time = 0;
+ }
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+ class NetworkProfilerFrame {
+ public:
+ Vector<MultiplayerAPI::ProfilingInfo> infos;
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+
+ NetworkProfilerFrame(){};
+ };
+
+protected:
+ struct ProfileInfoSort {
+
+ bool operator()(ScriptLanguage::ProfilingInfo *A, ScriptLanguage::ProfilingInfo *B) const {
+ return A->total_time < B->total_time;
+ }
+ };
+
+ Vector<ScriptLanguage::ProfilingInfo> profile_info;
+ Vector<ScriptLanguage::ProfilingInfo *> profile_info_ptrs;
+ Vector<MultiplayerAPI::ProfilingInfo> network_profile_info;
+
+ Map<StringName, int> profiler_function_signature_map;
+ float frame_time, idle_time, physics_time, physics_frame_time;
+
+ bool profiling;
+ bool visual_profiling;
+ bool network_profiling;
+ int max_frame_functions;
+ bool skip_profile_frame;
+ bool reload_all_scripts;
+
+ Ref<StreamPeerTCP> tcp_client;
+ Ref<PacketPeerStream> packet_peer_stream;
+
+ uint64_t last_perf_time;
+ uint64_t last_net_prof_time;
+ uint64_t last_net_bandwidth_time;
+ Object *performance;
+ bool requested_quit;
+ Mutex *mutex;
+
+ List<String> output_strings;
+ List<Message> messages;
+ int max_messages_per_frame;
+ int n_messages_dropped;
+ List<OutputError> errors;
+ int max_errors_per_second;
+ int max_warnings_per_second;
+ int n_errors_dropped;
+ int n_warnings_dropped;
+
+ int max_cps;
+ int char_count;
+ int err_count;
+ int warn_count;
+ uint64_t last_msec;
+ uint64_t msec_count;
+
+ bool locking; //hack to avoid a deadloop
+ static void _print_handler(void *p_this, const String &p_string, bool p_error);
+
+ PrintHandlerList phl;
+
+ void _get_output();
+ void _poll_events();
+ uint32_t poll_every;
+
+ void _parse_message(const String p_command, const Array &p_data, ScriptLanguage *p_script = NULL);
+
+ void _set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value);
+
+ void _send_object_id(ObjectID p_id);
+ void _send_video_memory();
+
+ Ref<MultiplayerAPI> multiplayer;
+
+ ErrorHandlerList eh;
+ static void _err_handler(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type);
+
+ void _put_msg(String p_message, Array p_data);
+ void _send_profiling_data(bool p_for_frame);
+ void _send_network_profiling_data();
+ void _send_network_bandwidth_usage();
+
+ Vector<FrameData> profile_frame_data;
+
+ bool skip_breakpoints;
+
+public:
+ typedef void (*ResourceUsageFunc)(ResourceUsage *);
+ typedef Error (*ParseMessageFunc)(const String &p_name, const Array &p_msg); // Returns true if something was found (stopping propagation).
+
+ static ResourceUsageFunc resource_usage_func;
+ static ParseMessageFunc scene_tree_parse_func; // Could be made into list, extensible...
+
+ Error connect_to_host(const String &p_host, uint16_t p_port);
+ bool is_peer_connected();
+ virtual void debug(ScriptLanguage *p_script, bool p_can_continue = true, bool p_is_error_breakpoint = false);
+ virtual void idle_poll();
+ virtual void line_poll();
+
+ virtual bool is_remote() const { return true; }
+ virtual void request_quit();
+
+ virtual void send_message(const String &p_message, const Array &p_args);
+ virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info);
+
+ virtual void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
+
+ virtual bool is_profiling() const;
+ virtual void add_profiling_frame_data(const StringName &p_name, const Array &p_data);
+
+ virtual void profiling_start();
+ virtual void profiling_end();
+ virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time);
+
+ virtual void set_skip_breakpoints(bool p_skip_breakpoints);
+
+ ScriptDebuggerRemote();
+ ~ScriptDebuggerRemote();
+};
+
+#endif // SCRIPT_DEBUGGER_REMOTE_H
diff --git a/core/type_info.h b/core/type_info.h
index 8e86567f51..6861531fbd 100644
--- a/core/type_info.h
+++ b/core/type_info.h
@@ -151,6 +151,7 @@ MAKE_TYPE_INFO(AABB, Variant::AABB)
MAKE_TYPE_INFO(Basis, Variant::BASIS)
MAKE_TYPE_INFO(Transform, Variant::TRANSFORM)
MAKE_TYPE_INFO(Color, Variant::COLOR)
+MAKE_TYPE_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH)
MAKE_TYPE_INFO(RID, Variant::_RID)
MAKE_TYPE_INFO(Callable, Variant::CALLABLE)
@@ -165,7 +166,6 @@ MAKE_TYPE_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPE_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPE_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
-MAKE_TYPE_INFO(StringName, Variant::STRING)
MAKE_TYPE_INFO(IP_Address, Variant::STRING)
//objectID
diff --git a/core/typedefs.h b/core/typedefs.h
index 0bb80cb2dd..5376b0718a 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -335,26 +335,16 @@ struct _GlobalLock {
*/
#define CAST_INT_TO_UCHAR_PTR(ptr) ((uint8_t *)(uintptr_t)(ptr))
-/** Hint for compilers that this fallthrough in a switch is intentional.
- * Can be replaced by [[fallthrough]] annotation if we move to C++17.
- * Including conditional support for it for people who set -std=c++17
- * themselves.
- * Requires a trailing semicolon when used.
- */
-#if __cplusplus >= 201703L
-#define FALLTHROUGH [[fallthrough]]
-#elif defined(__GNUC__) && __GNUC__ >= 7
-#define FALLTHROUGH __attribute__((fallthrough))
-#elif defined(__llvm__) && __cplusplus >= 201103L && defined(__has_feature)
-#if __has_feature(cxx_attributes) && defined(__has_warning)
-#if __has_warning("-Wimplicit-fallthrough")
-#define FALLTHROUGH [[clang::fallthrough]]
-#endif
-#endif
-#endif
+// Home-made index sequence trick, so it can be used everywhere without the costly include of std::tuple.
+// https://stackoverflow.com/questions/15014096/c-index-of-type-during-variadic-template-expansion
-#ifndef FALLTHROUGH
-#define FALLTHROUGH
-#endif
+template <size_t... Is>
+struct IndexSequence {};
+
+template <size_t N, size_t... Is>
+struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
+
+template <size_t... Is>
+struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
#endif // TYPEDEFS_H
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 0eef75d587..02f460c93d 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -105,7 +105,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
action_level++;
}
-void UndoRedo::add_do_method(Object *p_object, const String &p_method, VARIANT_ARG_DECLARE) {
+void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
VARIANT_ARGPTRS
ERR_FAIL_COND(p_object == NULL);
@@ -125,7 +125,7 @@ void UndoRedo::add_do_method(Object *p_object, const String &p_method, VARIANT_A
actions.write[current_action + 1].do_ops.push_back(do_op);
}
-void UndoRedo::add_undo_method(Object *p_object, const String &p_method, VARIANT_ARG_DECLARE) {
+void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
VARIANT_ARGPTRS
ERR_FAIL_COND(p_object == NULL);
@@ -149,7 +149,7 @@ void UndoRedo::add_undo_method(Object *p_object, const String &p_method, VARIANT
}
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
-void UndoRedo::add_do_property(Object *p_object, const String &p_property, const Variant &p_value) {
+void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, const Variant &p_value) {
ERR_FAIL_COND(p_object == NULL);
ERR_FAIL_COND(action_level <= 0);
@@ -164,7 +164,7 @@ void UndoRedo::add_do_property(Object *p_object, const String &p_property, const
do_op.args[0] = p_value;
actions.write[current_action + 1].do_ops.push_back(do_op);
}
-void UndoRedo::add_undo_property(Object *p_object, const String &p_property, const Variant &p_value) {
+void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value) {
ERR_FAIL_COND(p_object == NULL);
ERR_FAIL_COND(action_level <= 0);
@@ -446,17 +446,17 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl
return Variant();
}
- if (p_args[1]->get_type() != Variant::STRING) {
+ if (p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
r_error.error = Callable::CallError::CALL_OK;
Object *object = *p_args[0];
- String method = *p_args[1];
+ StringName method = *p_args[1];
Variant v[VARIANT_ARG_MAX];
@@ -484,17 +484,17 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla
return Variant();
}
- if (p_args[1]->get_type() != Variant::STRING) {
+ if (p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
r_error.error = Callable::CallError::CALL_OK;
Object *object = *p_args[0];
- String method = *p_args[1];
+ StringName method = *p_args[1];
Variant v[VARIANT_ARG_MAX];
@@ -518,7 +518,7 @@ void UndoRedo::_bind_methods() {
MethodInfo mi;
mi.name = "add_do_method";
mi.arguments.push_back(PropertyInfo(Variant::OBJECT, "object"));
- mi.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "add_do_method", &UndoRedo::_add_do_method, mi, varray(), false);
}
@@ -527,7 +527,7 @@ void UndoRedo::_bind_methods() {
MethodInfo mi;
mi.name = "add_undo_method";
mi.arguments.push_back(PropertyInfo(Variant::OBJECT, "object"));
- mi.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "add_undo_method", &UndoRedo::_add_undo_method, mi, varray(), false);
}
diff --git a/core/undo_redo.h b/core/undo_redo.h
index e707979291..3b91e9ce36 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -65,7 +65,7 @@ private:
Type type;
Ref<Resource> resref;
ObjectID object;
- String name;
+ StringName name;
Variant args[VARIANT_ARG_MAX];
};
@@ -103,10 +103,10 @@ protected:
public:
void create_action(const String &p_name = "", MergeMode p_mode = MERGE_DISABLE);
- void add_do_method(Object *p_object, const String &p_method, VARIANT_ARG_LIST);
- void add_undo_method(Object *p_object, const String &p_method, VARIANT_ARG_LIST);
- void add_do_property(Object *p_object, const String &p_property, const Variant &p_value);
- void add_undo_property(Object *p_object, const String &p_property, const Variant &p_value);
+ void add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
+ void add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
+ void add_do_property(Object *p_object, const StringName &p_property, const Variant &p_value);
+ void add_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value);
void add_do_reference(Object *p_object);
void add_undo_reference(Object *p_object);
diff --git a/core/ustring.cpp b/core/ustring.cpp
index c4543b89da..1d4d9c2dfd 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -2169,6 +2169,7 @@ int64_t String::to_int(const CharType *p_str, int p_len) {
} else {
break;
}
+ [[fallthrough]];
}
case READING_INT: {
diff --git a/core/variant.cpp b/core/variant.cpp
index a215eee624..1e09df98c7 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -72,10 +72,18 @@ String Variant::get_type_name(Variant::Type p_type) {
return "Vector2";
} break;
+ case VECTOR2I: {
+
+ return "Vector2i";
+ } break;
case RECT2: {
return "Rect2";
} break;
+ case RECT2I: {
+
+ return "Rect2i";
+ } break;
case TRANSFORM2D: {
return "Transform2D";
@@ -84,6 +92,10 @@ String Variant::get_type_name(Variant::Type p_type) {
return "Vector3";
} break;
+ case VECTOR3I: {
+
+ return "Vector3i";
+ } break;
case PLANE: {
return "Plane";
@@ -136,6 +148,11 @@ String Variant::get_type_name(Variant::Type p_type) {
return "Signal";
} break;
+ case STRING_NAME: {
+
+ return "StringName";
+
+ } break;
case NODE_PATH: {
return "NodePath";
@@ -253,6 +270,46 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
invalid_types = invalid;
} break;
+ case VECTOR2: {
+
+ static const Type valid[] = {
+ VECTOR2I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case VECTOR2I: {
+
+ static const Type valid[] = {
+ VECTOR2,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case RECT2: {
+
+ static const Type valid[] = {
+ RECT2I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case RECT2I: {
+
+ static const Type valid[] = {
+ RECT2,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
case TRANSFORM2D: {
static const Type valid[] = {
@@ -262,6 +319,27 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
valid_types = valid;
} break;
+ case VECTOR3: {
+
+ static const Type valid[] = {
+ VECTOR3I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case VECTOR3I: {
+
+ static const Type valid[] = {
+ VECTOR3,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+
case QUAT: {
static const Type valid[] = {
@@ -325,6 +403,15 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
valid_types = valid;
} break;
+ case STRING_NAME: {
+
+ static const Type valid[] = {
+ STRING,
+ NIL
+ };
+
+ valid_types = valid;
+ } break;
case NODE_PATH: {
static const Type valid[] = {
@@ -495,11 +582,52 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
static const Type valid[] = {
NODE_PATH,
+ STRING_NAME,
NIL
};
valid_types = valid;
} break;
+ case VECTOR2: {
+
+ static const Type valid[] = {
+ VECTOR2I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case VECTOR2I: {
+
+ static const Type valid[] = {
+ VECTOR2,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case RECT2: {
+
+ static const Type valid[] = {
+ RECT2I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case RECT2I: {
+
+ static const Type valid[] = {
+ RECT2,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
case TRANSFORM2D: {
static const Type valid[] = {
@@ -509,6 +637,27 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
valid_types = valid;
} break;
+ case VECTOR3: {
+
+ static const Type valid[] = {
+ VECTOR3I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case VECTOR3I: {
+
+ static const Type valid[] = {
+ VECTOR3,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+
case QUAT: {
static const Type valid[] = {
@@ -572,6 +721,15 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
valid_types = valid;
} break;
+ case STRING_NAME: {
+
+ static const Type valid[] = {
+ STRING,
+ NIL
+ };
+
+ valid_types = valid;
+ } break;
case NODE_PATH: {
static const Type valid[] = {
@@ -741,11 +899,21 @@ bool Variant::is_zero() const {
return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2();
} break;
+ case VECTOR2I: {
+
+ return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i();
+
+ } break;
case RECT2: {
return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2();
} break;
+ case RECT2I: {
+
+ return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i();
+
+ } break;
case TRANSFORM2D: {
return *_data._transform2d == Transform2D();
@@ -756,6 +924,11 @@ bool Variant::is_zero() const {
return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3();
} break;
+ case VECTOR3I: {
+
+ return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i();
+
+ } break;
case PLANE: {
return *reinterpret_cast<const Plane *>(_data._mem) == Plane();
@@ -808,6 +981,11 @@ bool Variant::is_zero() const {
return reinterpret_cast<const Signal *>(_data._mem)->is_null();
} break;
+ case STRING_NAME: {
+
+ return *reinterpret_cast<const StringName *>(_data._mem) != StringName();
+
+ } break;
case NODE_PATH: {
return reinterpret_cast<const NodePath *>(_data._mem)->is_empty();
@@ -827,37 +1005,37 @@ bool Variant::is_zero() const {
// arrays
case PACKED_BYTE_ARRAY: {
- return reinterpret_cast<const Vector<uint8_t> *>(_data._mem)->size() == 0;
+ return PackedArrayRef<uint8_t>::get_array(_data.packed_array).size() == 0;
} break;
case PACKED_INT_ARRAY: {
- return reinterpret_cast<const Vector<int> *>(_data._mem)->size() == 0;
+ return PackedArrayRef<int32_t>::get_array(_data.packed_array).size() == 0;
} break;
case PACKED_REAL_ARRAY: {
- return reinterpret_cast<const Vector<real_t> *>(_data._mem)->size() == 0;
+ return PackedArrayRef<real_t>::get_array(_data.packed_array).size() == 0;
} break;
case PACKED_STRING_ARRAY: {
- return reinterpret_cast<const Vector<String> *>(_data._mem)->size() == 0;
+ return PackedArrayRef<String>::get_array(_data.packed_array).size() == 0;
} break;
case PACKED_VECTOR2_ARRAY: {
- return reinterpret_cast<const Vector<Vector2> *>(_data._mem)->size() == 0;
+ return PackedArrayRef<Vector2>::get_array(_data.packed_array).size() == 0;
} break;
case PACKED_VECTOR3_ARRAY: {
- return reinterpret_cast<const Vector<Vector3> *>(_data._mem)->size() == 0;
+ return PackedArrayRef<Vector3>::get_array(_data.packed_array).size() == 0;
} break;
case PACKED_COLOR_ARRAY: {
- return reinterpret_cast<const Vector<Color> *>(_data._mem)->size() == 0;
+ return PackedArrayRef<Color>::get_array(_data.packed_array).size() == 0;
} break;
default: {
@@ -895,16 +1073,31 @@ bool Variant::is_one() const {
return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2(1, 1);
} break;
+ case VECTOR2I: {
+
+ return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i(1, 1);
+
+ } break;
case RECT2: {
return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2(1, 1, 1, 1);
} break;
+ case RECT2I: {
+
+ return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i(1, 1, 1, 1);
+
+ } break;
case VECTOR3: {
return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3(1, 1, 1);
} break;
+ case VECTOR3I: {
+
+ return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(1, 1, 1);
+
+ } break;
case PLANE: {
return *reinterpret_cast<const Plane *>(_data._mem) == Plane(1, 1, 1, 1);
@@ -975,10 +1168,18 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem)));
} break;
+ case VECTOR2I: {
+
+ memnew_placement(_data._mem, Vector2i(*reinterpret_cast<const Vector2i *>(p_variant._data._mem)));
+ } break;
case RECT2: {
memnew_placement(_data._mem, Rect2(*reinterpret_cast<const Rect2 *>(p_variant._data._mem)));
} break;
+ case RECT2I: {
+
+ memnew_placement(_data._mem, Rect2i(*reinterpret_cast<const Rect2i *>(p_variant._data._mem)));
+ } break;
case TRANSFORM2D: {
_data._transform2d = memnew(Transform2D(*p_variant._data._transform2d));
@@ -987,6 +1188,10 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem)));
} break;
+ case VECTOR3I: {
+
+ memnew_placement(_data._mem, Vector3i(*reinterpret_cast<const Vector3i *>(p_variant._data._mem)));
+ } break;
case PLANE: {
memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem)));
@@ -1046,6 +1251,11 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, Signal(*reinterpret_cast<const Signal *>(p_variant._data._mem)));
} break;
+ case STRING_NAME: {
+
+ memnew_placement(_data._mem, StringName(*reinterpret_cast<const StringName *>(p_variant._data._mem)));
+
+ } break;
case NODE_PATH: {
memnew_placement(_data._mem, NodePath(*reinterpret_cast<const NodePath *>(p_variant._data._mem)));
@@ -1065,37 +1275,58 @@ void Variant::reference(const Variant &p_variant) {
// arrays
case PACKED_BYTE_ARRAY: {
- memnew_placement(_data._mem, Vector<uint8_t>(*reinterpret_cast<const Vector<uint8_t> *>(p_variant._data._mem)));
+ _data.packed_array = static_cast<PackedArrayRef<uint8_t> *>(p_variant._data.packed_array)->reference();
+ if (!_data.packed_array) {
+ _data.packed_array = PackedArrayRef<uint8_t>::create();
+ }
} break;
case PACKED_INT_ARRAY: {
- memnew_placement(_data._mem, Vector<int>(*reinterpret_cast<const Vector<int> *>(p_variant._data._mem)));
+ _data.packed_array = static_cast<PackedArrayRef<int32_t> *>(p_variant._data.packed_array)->reference();
+ if (!_data.packed_array) {
+ _data.packed_array = PackedArrayRef<int32_t>::create();
+ }
} break;
case PACKED_REAL_ARRAY: {
- memnew_placement(_data._mem, Vector<real_t>(*reinterpret_cast<const Vector<real_t> *>(p_variant._data._mem)));
+ _data.packed_array = static_cast<PackedArrayRef<real_t> *>(p_variant._data.packed_array)->reference();
+ if (!_data.packed_array) {
+ _data.packed_array = PackedArrayRef<real_t>::create();
+ }
} break;
case PACKED_STRING_ARRAY: {
- memnew_placement(_data._mem, Vector<String>(*reinterpret_cast<const Vector<String> *>(p_variant._data._mem)));
+ _data.packed_array = static_cast<PackedArrayRef<String> *>(p_variant._data.packed_array)->reference();
+ if (!_data.packed_array) {
+ _data.packed_array = PackedArrayRef<String>::create();
+ }
} break;
case PACKED_VECTOR2_ARRAY: {
- memnew_placement(_data._mem, Vector<Vector2>(*reinterpret_cast<const Vector<Vector2> *>(p_variant._data._mem)));
+ _data.packed_array = static_cast<PackedArrayRef<Vector2> *>(p_variant._data.packed_array)->reference();
+ if (!_data.packed_array) {
+ _data.packed_array = PackedArrayRef<Vector2>::create();
+ }
} break;
case PACKED_VECTOR3_ARRAY: {
- memnew_placement(_data._mem, Vector<Vector3>(*reinterpret_cast<const Vector<Vector3> *>(p_variant._data._mem)));
+ _data.packed_array = static_cast<PackedArrayRef<Vector3> *>(p_variant._data.packed_array)->reference();
+ if (!_data.packed_array) {
+ _data.packed_array = PackedArrayRef<Vector3>::create();
+ }
} break;
case PACKED_COLOR_ARRAY: {
- memnew_placement(_data._mem, Vector<Color>(*reinterpret_cast<const Vector<Color> *>(p_variant._data._mem)));
+ _data.packed_array = static_cast<PackedArrayRef<Color> *>(p_variant._data.packed_array)->reference();
+ if (!_data.packed_array) {
+ _data.packed_array = PackedArrayRef<Color>::create();
+ }
} break;
default: {
@@ -1110,8 +1341,11 @@ void Variant::zero() {
case INT: this->_data._int = 0; break;
case REAL: this->_data._real = 0; break;
case VECTOR2: *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2(); break;
+ case VECTOR2I: *reinterpret_cast<Vector2i *>(this->_data._mem) = Vector2i(); break;
case RECT2: *reinterpret_cast<Rect2 *>(this->_data._mem) = Rect2(); break;
+ case RECT2I: *reinterpret_cast<Rect2i *>(this->_data._mem) = Rect2i(); break;
case VECTOR3: *reinterpret_cast<Vector3 *>(this->_data._mem) = Vector3(); break;
+ case VECTOR3I: *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i(); break;
case PLANE: *reinterpret_cast<Plane *>(this->_data._mem) = Plane(); break;
case QUAT: *reinterpret_cast<Quat *>(this->_data._mem) = Quat(); break;
case COLOR: *reinterpret_cast<Color *>(this->_data._mem) = Color(); break;
@@ -1152,7 +1386,11 @@ void Variant::clear() {
memdelete(_data._transform);
} break;
- // misc types
+ // misc types
+ case STRING_NAME: {
+
+ reinterpret_cast<StringName *>(_data._mem)->~StringName();
+ } break;
case NODE_PATH: {
reinterpret_cast<NodePath *>(_data._mem)->~NodePath();
@@ -1192,31 +1430,31 @@ void Variant::clear() {
// arrays
case PACKED_BYTE_ARRAY: {
- reinterpret_cast<Vector<uint8_t> *>(_data._mem)->~Vector<uint8_t>();
+ PackedArrayRefBase::destroy(_data.packed_array);
} break;
case PACKED_INT_ARRAY: {
- reinterpret_cast<Vector<int> *>(_data._mem)->~Vector<int>();
+ PackedArrayRefBase::destroy(_data.packed_array);
} break;
case PACKED_REAL_ARRAY: {
- reinterpret_cast<Vector<real_t> *>(_data._mem)->~Vector<real_t>();
+ PackedArrayRefBase::destroy(_data.packed_array);
} break;
case PACKED_STRING_ARRAY: {
- reinterpret_cast<Vector<String> *>(_data._mem)->~Vector<String>();
+ PackedArrayRefBase::destroy(_data.packed_array);
} break;
case PACKED_VECTOR2_ARRAY: {
- reinterpret_cast<Vector<Vector2> *>(_data._mem)->~Vector<Vector2>();
+ PackedArrayRefBase::destroy(_data.packed_array);
} break;
case PACKED_VECTOR3_ARRAY: {
- reinterpret_cast<Vector<Vector3> *>(_data._mem)->~Vector<Vector3>();
+ PackedArrayRefBase::destroy(_data.packed_array);
} break;
case PACKED_COLOR_ARRAY: {
- reinterpret_cast<Vector<Color> *>(_data._mem)->~Vector<Color>();
+ PackedArrayRefBase::destroy(_data.packed_array);
} break;
default: {
} /* not needed */
@@ -1455,10 +1693,13 @@ Variant::operator double() const {
Variant::operator StringName() const {
- if (type == NODE_PATH) {
- return reinterpret_cast<const NodePath *>(_data._mem)->get_sname();
+ if (type == STRING_NAME) {
+ return *reinterpret_cast<const StringName *>(_data._mem);
+ } else if (type == STRING) {
+ return *reinterpret_cast<const String *>(_data._mem);
}
- return StringName(operator String());
+
+ return StringName();
}
struct _VariantStrPair {
@@ -1487,13 +1728,16 @@ String Variant::stringify(List<const void *> &stack) const {
case REAL: return rtos(_data._real);
case STRING: return *reinterpret_cast<const String *>(_data._mem);
case VECTOR2: return "(" + operator Vector2() + ")";
+ case VECTOR2I: return "(" + operator Vector2i() + ")";
case RECT2: return "(" + operator Rect2() + ")";
+ case RECT2I: return "(" + operator Rect2i() + ")";
case TRANSFORM2D: {
Transform2D mat32 = operator Transform2D();
return "(" + Variant(mat32.elements[0]).operator String() + ", " + Variant(mat32.elements[1]).operator String() + ", " + Variant(mat32.elements[2]).operator String() + ")";
} break;
case VECTOR3: return "(" + operator Vector3() + ")";
+ case VECTOR3I: return "(" + operator Vector3i() + ")";
case PLANE:
return operator Plane();
//case QUAT:
@@ -1525,6 +1769,7 @@ String Variant::stringify(List<const void *> &stack) const {
return mtx + ")";
} break;
case TRANSFORM: return operator Transform();
+ case STRING_NAME: return operator StringName();
case NODE_PATH: return operator NodePath();
case COLOR: return String::num(operator Color().r) + "," + String::num(operator Color().g) + "," + String::num(operator Color().b) + "," + String::num(operator Color().a);
case DICTIONARY: {
@@ -1685,28 +1930,78 @@ Variant::operator Vector2() const {
if (type == VECTOR2)
return *reinterpret_cast<const Vector2 *>(_data._mem);
+ else if (type == VECTOR2I)
+ return *reinterpret_cast<const Vector2i *>(_data._mem);
else if (type == VECTOR3)
return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y);
+ else if (type == VECTOR3I)
+ return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y);
else
return Vector2();
}
+
+Variant::operator Vector2i() const {
+
+ if (type == VECTOR2I)
+ return *reinterpret_cast<const Vector2i *>(_data._mem);
+ else if (type == VECTOR2)
+ return *reinterpret_cast<const Vector2 *>(_data._mem);
+ else if (type == VECTOR3)
+ return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y);
+ else if (type == VECTOR3I)
+ return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y);
+ else
+ return Vector2i();
+}
+
Variant::operator Rect2() const {
if (type == RECT2)
return *reinterpret_cast<const Rect2 *>(_data._mem);
+ else if (type == RECT2I)
+ return *reinterpret_cast<const Rect2i *>(_data._mem);
else
return Rect2();
}
+Variant::operator Rect2i() const {
+
+ if (type == RECT2I)
+ return *reinterpret_cast<const Rect2i *>(_data._mem);
+ else if (type == RECT2)
+ return *reinterpret_cast<const Rect2 *>(_data._mem);
+ else
+ return Rect2i();
+}
+
Variant::operator Vector3() const {
if (type == VECTOR3)
return *reinterpret_cast<const Vector3 *>(_data._mem);
+ else if (type == VECTOR3I)
+ return *reinterpret_cast<const Vector3i *>(_data._mem);
else if (type == VECTOR2)
return Vector3(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0);
+ else if (type == VECTOR2I)
+ return Vector3(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0);
else
return Vector3();
}
+
+Variant::operator Vector3i() const {
+
+ if (type == VECTOR3I)
+ return *reinterpret_cast<const Vector3i *>(_data._mem);
+ else if (type == VECTOR3)
+ return *reinterpret_cast<const Vector3 *>(_data._mem);
+ else if (type == VECTOR2)
+ return Vector3i(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0);
+ else if (type == VECTOR2I)
+ return Vector3i(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0);
+ else
+ return Vector3i();
+}
+
Variant::operator Plane() const {
if (type == PLANE)
@@ -1958,21 +2253,21 @@ Variant::operator Array() const {
Variant::operator Vector<uint8_t>() const {
if (type == PACKED_BYTE_ARRAY)
- return *reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+ return static_cast<PackedArrayRef<uint8_t> *>(_data.packed_array)->array;
else
return _convert_array_from_variant<Vector<uint8_t> >(*this);
}
Variant::operator Vector<int>() const {
if (type == PACKED_INT_ARRAY)
- return *reinterpret_cast<const Vector<int> *>(_data._mem);
+ return static_cast<PackedArrayRef<int32_t> *>(_data.packed_array)->array;
else
return _convert_array_from_variant<Vector<int> >(*this);
}
Variant::operator Vector<real_t>() const {
if (type == PACKED_REAL_ARRAY)
- return *reinterpret_cast<const Vector<real_t> *>(_data._mem);
+ return static_cast<PackedArrayRef<real_t> *>(_data.packed_array)->array;
else
return _convert_array_from_variant<Vector<real_t> >(*this);
}
@@ -1980,21 +2275,21 @@ Variant::operator Vector<real_t>() const {
Variant::operator Vector<String>() const {
if (type == PACKED_STRING_ARRAY)
- return *reinterpret_cast<const Vector<String> *>(_data._mem);
+ return static_cast<PackedArrayRef<String> *>(_data.packed_array)->array;
else
return _convert_array_from_variant<Vector<String> >(*this);
}
Variant::operator Vector<Vector3>() const {
if (type == PACKED_VECTOR3_ARRAY)
- return *reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+ return static_cast<PackedArrayRef<Vector3> *>(_data.packed_array)->array;
else
return _convert_array_from_variant<Vector<Vector3> >(*this);
}
Variant::operator Vector<Vector2>() const {
if (type == PACKED_VECTOR2_ARRAY)
- return *reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+ return static_cast<PackedArrayRef<Vector2> *>(_data.packed_array)->array;
else
return _convert_array_from_variant<Vector<Vector2> >(*this);
}
@@ -2002,7 +2297,7 @@ Variant::operator Vector<Vector2>() const {
Variant::operator Vector<Color>() const {
if (type == PACKED_COLOR_ARRAY)
- return *reinterpret_cast<const Vector<Color> *>(_data._mem);
+ return static_cast<PackedArrayRef<Color> *>(_data.packed_array)->array;
else
return _convert_array_from_variant<Vector<Color> >(*this);
}
@@ -2193,8 +2488,8 @@ Variant::Variant(const ObjectID &p_id) {
Variant::Variant(const StringName &p_string) {
- type = STRING;
- memnew_placement(_data._mem, String(p_string.operator String()));
+ type = STRING_NAME;
+ memnew_placement(_data._mem, StringName(p_string));
}
Variant::Variant(const String &p_string) {
@@ -2218,17 +2513,36 @@ Variant::Variant(const Vector3 &p_vector3) {
type = VECTOR3;
memnew_placement(_data._mem, Vector3(p_vector3));
}
+Variant::Variant(const Vector3i &p_vector3i) {
+
+ type = VECTOR3I;
+ memnew_placement(_data._mem, Vector3i(p_vector3i));
+}
+
Variant::Variant(const Vector2 &p_vector2) {
type = VECTOR2;
memnew_placement(_data._mem, Vector2(p_vector2));
}
+
+Variant::Variant(const Vector2i &p_vector2i) {
+
+ type = VECTOR2I;
+ memnew_placement(_data._mem, Vector2i(p_vector2i));
+}
+
Variant::Variant(const Rect2 &p_rect2) {
type = RECT2;
memnew_placement(_data._mem, Rect2(p_rect2));
}
+Variant::Variant(const Rect2i &p_rect2i) {
+
+ type = RECT2I;
+ memnew_placement(_data._mem, Rect2i(p_rect2i));
+}
+
Variant::Variant(const Plane &p_plane) {
type = PLANE;
@@ -2359,38 +2673,39 @@ Variant::Variant(const Vector<RID> &p_array) {
Variant::Variant(const Vector<uint8_t> &p_raw_array) {
type = PACKED_BYTE_ARRAY;
- memnew_placement(_data._mem, Vector<uint8_t>(p_raw_array));
+
+ _data.packed_array = PackedArrayRef<uint8_t>::create(p_raw_array);
}
Variant::Variant(const Vector<int> &p_int_array) {
type = PACKED_INT_ARRAY;
- memnew_placement(_data._mem, Vector<int>(p_int_array));
+ _data.packed_array = PackedArrayRef<int32_t>::create(p_int_array);
}
Variant::Variant(const Vector<real_t> &p_real_array) {
type = PACKED_REAL_ARRAY;
- memnew_placement(_data._mem, Vector<real_t>(p_real_array));
+ _data.packed_array = PackedArrayRef<real_t>::create(p_real_array);
}
Variant::Variant(const Vector<String> &p_string_array) {
type = PACKED_STRING_ARRAY;
- memnew_placement(_data._mem, Vector<String>(p_string_array));
+ _data.packed_array = PackedArrayRef<String>::create(p_string_array);
}
Variant::Variant(const Vector<Vector3> &p_vector3_array) {
type = PACKED_VECTOR3_ARRAY;
- memnew_placement(_data._mem, Vector<Vector3>(p_vector3_array));
+ _data.packed_array = PackedArrayRef<Vector3>::create(p_vector3_array);
}
Variant::Variant(const Vector<Vector2> &p_vector2_array) {
type = PACKED_VECTOR2_ARRAY;
- memnew_placement(_data._mem, Vector<Vector2>(p_vector2_array));
+ _data.packed_array = PackedArrayRef<Vector2>::create(p_vector2_array);
}
Variant::Variant(const Vector<Color> &p_color_array) {
type = PACKED_COLOR_ARRAY;
- memnew_placement(_data._mem, Vector<Color>(p_color_array));
+ _data.packed_array = PackedArrayRef<Color>::create(p_color_array);
}
Variant::Variant(const Vector<Face3> &p_face_array) {
@@ -2476,10 +2791,18 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<Vector2 *>(_data._mem) = *reinterpret_cast<const Vector2 *>(p_variant._data._mem);
} break;
+ case VECTOR2I: {
+
+ *reinterpret_cast<Vector2i *>(_data._mem) = *reinterpret_cast<const Vector2i *>(p_variant._data._mem);
+ } break;
case RECT2: {
*reinterpret_cast<Rect2 *>(_data._mem) = *reinterpret_cast<const Rect2 *>(p_variant._data._mem);
} break;
+ case RECT2I: {
+
+ *reinterpret_cast<Rect2i *>(_data._mem) = *reinterpret_cast<const Rect2i *>(p_variant._data._mem);
+ } break;
case TRANSFORM2D: {
*_data._transform2d = *(p_variant._data._transform2d);
@@ -2488,6 +2811,10 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<Vector3 *>(_data._mem) = *reinterpret_cast<const Vector3 *>(p_variant._data._mem);
} break;
+ case VECTOR3I: {
+
+ *reinterpret_cast<Vector3i *>(_data._mem) = *reinterpret_cast<const Vector3i *>(p_variant._data._mem);
+ } break;
case PLANE: {
*reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem);
@@ -2551,6 +2878,10 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<Signal *>(_data._mem) = *reinterpret_cast<const Signal *>(p_variant._data._mem);
} break;
+ case STRING_NAME: {
+
+ *reinterpret_cast<StringName *>(_data._mem) = *reinterpret_cast<const StringName *>(p_variant._data._mem);
+ } break;
case NODE_PATH: {
*reinterpret_cast<NodePath *>(_data._mem) = *reinterpret_cast<const NodePath *>(p_variant._data._mem);
@@ -2567,31 +2898,31 @@ void Variant::operator=(const Variant &p_variant) {
// arrays
case PACKED_BYTE_ARRAY: {
- *reinterpret_cast<Vector<uint8_t> *>(_data._mem) = *reinterpret_cast<const Vector<uint8_t> *>(p_variant._data._mem);
+ _data.packed_array = PackedArrayRef<uint8_t>::reference_from(_data.packed_array, p_variant._data.packed_array);
} break;
case PACKED_INT_ARRAY: {
- *reinterpret_cast<Vector<int> *>(_data._mem) = *reinterpret_cast<const Vector<int> *>(p_variant._data._mem);
+ _data.packed_array = PackedArrayRef<int32_t>::reference_from(_data.packed_array, p_variant._data.packed_array);
} break;
case PACKED_REAL_ARRAY: {
- *reinterpret_cast<Vector<real_t> *>(_data._mem) = *reinterpret_cast<const Vector<real_t> *>(p_variant._data._mem);
+ _data.packed_array = PackedArrayRef<real_t>::reference_from(_data.packed_array, p_variant._data.packed_array);
} break;
case PACKED_STRING_ARRAY: {
- *reinterpret_cast<Vector<String> *>(_data._mem) = *reinterpret_cast<const Vector<String> *>(p_variant._data._mem);
+ _data.packed_array = PackedArrayRef<String>::reference_from(_data.packed_array, p_variant._data.packed_array);
} break;
case PACKED_VECTOR2_ARRAY: {
- *reinterpret_cast<Vector<Vector2> *>(_data._mem) = *reinterpret_cast<const Vector<Vector2> *>(p_variant._data._mem);
+ _data.packed_array = PackedArrayRef<Vector2>::reference_from(_data.packed_array, p_variant._data.packed_array);
} break;
case PACKED_VECTOR3_ARRAY: {
- *reinterpret_cast<Vector<Vector3> *>(_data._mem) = *reinterpret_cast<const Vector<Vector3> *>(p_variant._data._mem);
+ _data.packed_array = PackedArrayRef<Vector3>::reference_from(_data.packed_array, p_variant._data.packed_array);
} break;
case PACKED_COLOR_ARRAY: {
- *reinterpret_cast<Vector<Color> *>(_data._mem) = *reinterpret_cast<const Vector<Color> *>(p_variant._data._mem);
+ _data.packed_array = PackedArrayRef<Color>::reference_from(_data.packed_array, p_variant._data.packed_array);
} break;
default: {
}
@@ -2646,6 +2977,11 @@ uint32_t Variant::hash() const {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->x);
return hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->y, hash);
} break;
+ case VECTOR2I: {
+
+ uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Vector2i *>(_data._mem)->x);
+ return hash_djb2_one_32(reinterpret_cast<const Vector2i *>(_data._mem)->y, hash);
+ } break;
case RECT2: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.x);
@@ -2653,6 +2989,13 @@ uint32_t Variant::hash() const {
hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.x, hash);
return hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.y, hash);
} break;
+ case RECT2I: {
+
+ uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->position.x);
+ hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->position.y, hash);
+ hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->size.x, hash);
+ return hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->size.y, hash);
+ } break;
case TRANSFORM2D: {
uint32_t hash = 5831;
@@ -2671,6 +3014,12 @@ uint32_t Variant::hash() const {
hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->y, hash);
return hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->z, hash);
} break;
+ case VECTOR3I: {
+
+ uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->x);
+ hash = hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->y, hash);
+ return hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->z, hash);
+ } break;
case PLANE: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.x);
@@ -2749,6 +3098,10 @@ uint32_t Variant::hash() const {
return hash_djb2_one_64(make_uint64_t(_get_obj().obj));
} break;
+ case STRING_NAME: {
+
+ return reinterpret_cast<const StringName *>(_data._mem)->hash();
+ } break;
case NODE_PATH: {
return reinterpret_cast<const NodePath *>(_data._mem)->hash();
@@ -2777,7 +3130,7 @@ uint32_t Variant::hash() const {
} break;
case PACKED_BYTE_ARRAY: {
- const Vector<uint8_t> &arr = *reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+ const Vector<uint8_t> &arr = PackedArrayRef<uint8_t>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
const uint8_t *r = arr.ptr();
@@ -2789,7 +3142,7 @@ uint32_t Variant::hash() const {
} break;
case PACKED_INT_ARRAY: {
- const Vector<int> &arr = *reinterpret_cast<const Vector<int> *>(_data._mem);
+ const Vector<int32_t> &arr = PackedArrayRef<int32_t>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
const int *r = arr.ptr();
@@ -2801,7 +3154,7 @@ uint32_t Variant::hash() const {
} break;
case PACKED_REAL_ARRAY: {
- const Vector<real_t> &arr = *reinterpret_cast<const Vector<real_t> *>(_data._mem);
+ const Vector<real_t> &arr = PackedArrayRef<real_t>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -2815,7 +3168,7 @@ uint32_t Variant::hash() const {
case PACKED_STRING_ARRAY: {
uint32_t hash = 5831;
- const Vector<String> &arr = *reinterpret_cast<const Vector<String> *>(_data._mem);
+ const Vector<String> &arr = PackedArrayRef<String>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -2831,7 +3184,7 @@ uint32_t Variant::hash() const {
case PACKED_VECTOR2_ARRAY: {
uint32_t hash = 5831;
- const Vector<Vector2> &arr = *reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+ const Vector<Vector2> &arr = PackedArrayRef<Vector2>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -2848,7 +3201,7 @@ uint32_t Variant::hash() const {
case PACKED_VECTOR3_ARRAY: {
uint32_t hash = 5831;
- const Vector<Vector3> &arr = *reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+ const Vector<Vector3> &arr = PackedArrayRef<Vector3>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -2866,7 +3219,7 @@ uint32_t Variant::hash() const {
case PACKED_COLOR_ARRAY: {
uint32_t hash = 5831;
- const Vector<Color> &arr = *reinterpret_cast<const Vector<Color> *>(_data._mem);
+ const Vector<Color> &arr = PackedArrayRef<Color>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -2945,6 +3298,11 @@ bool Variant::hash_compare(const Variant &p_variant) const {
return hash_compare_vector2(*l, *r);
} break;
+ case VECTOR2I: {
+ const Vector2i *l = reinterpret_cast<const Vector2i *>(_data._mem);
+ const Vector2i *r = reinterpret_cast<const Vector2i *>(p_variant._data._mem);
+ return *l == *r;
+ } break;
case RECT2: {
const Rect2 *l = reinterpret_cast<const Rect2 *>(_data._mem);
@@ -2953,6 +3311,12 @@ bool Variant::hash_compare(const Variant &p_variant) const {
return (hash_compare_vector2(l->position, r->position)) &&
(hash_compare_vector2(l->size, r->size));
} break;
+ case RECT2I: {
+ const Rect2i *l = reinterpret_cast<const Rect2i *>(_data._mem);
+ const Rect2i *r = reinterpret_cast<const Rect2i *>(p_variant._data._mem);
+
+ return *l == *r;
+ } break;
case TRANSFORM2D: {
Transform2D *l = _data._transform2d;
@@ -2972,6 +3336,12 @@ bool Variant::hash_compare(const Variant &p_variant) const {
return hash_compare_vector3(*l, *r);
} break;
+ case VECTOR3I: {
+ const Vector3i *l = reinterpret_cast<const Vector3i *>(_data._mem);
+ const Vector3i *r = reinterpret_cast<const Vector3i *>(p_variant._data._mem);
+
+ return *l == *r;
+ } break;
case PLANE: {
const Plane *l = reinterpret_cast<const Plane *>(_data._mem);
diff --git a/core/variant.h b/core/variant.h
index d41144f4c5..c126540001 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -44,9 +44,9 @@
#include "core/math/transform.h"
#include "core/math/transform_2d.h"
#include "core/math/vector3.h"
+#include "core/math/vector3i.h"
#include "core/node_path.h"
#include "core/object_id.h"
-
#include "core/rid.h"
#include "core/ustring.h"
@@ -88,8 +88,11 @@ public:
// math types
VECTOR2, // 5
+ VECTOR2I,
RECT2,
+ RECT2I,
VECTOR3,
+ VECTOR3I,
TRANSFORM2D,
PLANE,
QUAT, // 10
@@ -99,6 +102,7 @@ public:
// misc types
COLOR,
+ STRING_NAME,
NODE_PATH, // 15
_RID,
OBJECT,
@@ -132,6 +136,65 @@ private:
Object *obj;
};
+ /* array helpers */
+ struct PackedArrayRefBase {
+ SafeRefCount refcount;
+ _FORCE_INLINE_ PackedArrayRefBase *reference() {
+ if (this->refcount.ref()) {
+ return this;
+ } else {
+ return nullptr;
+ }
+ }
+ static _FORCE_INLINE_ PackedArrayRefBase *reference_from(PackedArrayRefBase *p_base, PackedArrayRefBase *p_from) {
+ if (p_base == p_from) {
+ return p_base; //same thing, do nothing
+ }
+
+ if (p_from->reference()) {
+ if (p_base->refcount.unref()) {
+ memdelete(p_base);
+ }
+ return p_from;
+ } else {
+ return p_base; //keep, could not reference new
+ }
+ }
+ static _FORCE_INLINE_ void destroy(PackedArrayRefBase *p_array) {
+ if (p_array->refcount.unref()) {
+ memdelete(p_array);
+ }
+ }
+ _FORCE_INLINE_ virtual ~PackedArrayRefBase() {} //needs virtual destructor, but make inline
+ };
+
+ template <class T>
+ struct PackedArrayRef : public PackedArrayRefBase {
+ Vector<T> array;
+ static _FORCE_INLINE_ PackedArrayRef<T> *create() {
+ return memnew(PackedArrayRef<T>);
+ }
+ static _FORCE_INLINE_ PackedArrayRef<T> *create(const Vector<T> &p_from) {
+ return memnew(PackedArrayRef<T>(p_from));
+ }
+
+ static _FORCE_INLINE_ const Vector<T> &get_array(PackedArrayRefBase *p_base) {
+ return static_cast<PackedArrayRef<T> *>(p_base)->array;
+ }
+ static _FORCE_INLINE_ Vector<T> *get_array_ptr(const PackedArrayRefBase *p_base) {
+ return &const_cast<PackedArrayRef<T> *>(static_cast<const PackedArrayRef<T> *>(p_base))->array;
+ }
+
+ _FORCE_INLINE_ PackedArrayRef(const Vector<T> &p_from) {
+ array = p_from;
+ refcount.init();
+ }
+ _FORCE_INLINE_ PackedArrayRef() {
+ refcount.init();
+ }
+ };
+
+ /* end of array helpers */
_ALWAYS_INLINE_ ObjData &_get_obj();
_ALWAYS_INLINE_ const ObjData &_get_obj() const;
@@ -143,6 +206,7 @@ private:
::AABB *_aabb;
Basis *_basis;
Transform *_transform;
+ PackedArrayRefBase *packed_array;
void *_ptr; //generic pointer
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
} _data GCC_ALIGNED_8;
@@ -151,14 +215,20 @@ private:
void clear();
public:
- _FORCE_INLINE_ Type get_type() const { return type; }
+ _FORCE_INLINE_ Type get_type() const {
+ return type;
+ }
static String get_type_name(Variant::Type p_type);
static bool can_convert(Type p_type_from, Type p_type_to);
static bool can_convert_strict(Type p_type_from, Type p_type_to);
bool is_ref() const;
- _FORCE_INLINE_ bool is_num() const { return type == INT || type == REAL; };
- _FORCE_INLINE_ bool is_array() const { return type >= ARRAY; };
+ _FORCE_INLINE_ bool is_num() const {
+ return type == INT || type == REAL;
+ };
+ _FORCE_INLINE_ bool is_array() const {
+ return type >= ARRAY;
+ };
bool is_shared() const;
bool is_zero() const;
bool is_one() const;
@@ -187,8 +257,11 @@ public:
operator String() const;
operator StringName() const;
operator Vector2() const;
+ operator Vector2i() const;
operator Rect2() const;
+ operator Rect2i() const;
operator Vector3() const;
+ operator Vector3i() const;
operator Plane() const;
operator ::AABB() const;
operator Quat() const;
@@ -255,8 +328,11 @@ public:
Variant(const char *const p_cstring);
Variant(const CharType *p_wstring);
Variant(const Vector2 &p_vector2);
+ Variant(const Vector2i &p_vector2i);
Variant(const Rect2 &p_rect2);
+ Variant(const Rect2i &p_rect2i);
Variant(const Vector3 &p_vector3);
+ Variant(const Vector3i &p_vector3i);
Variant(const Plane &p_plane);
Variant(const ::AABB &p_aabb);
Variant(const Quat &p_quat);
@@ -395,7 +471,9 @@ public:
void operator=(const Variant &p_variant); // only this is enough for all the other types
Variant(const Variant &p_variant);
- _FORCE_INLINE_ Variant() { type = NIL; }
+ _FORCE_INLINE_ Variant() {
+ type = NIL;
+ }
_FORCE_INLINE_ ~Variant() {
if (type != Variant::NIL) clear();
}
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 37c35d7c64..a876cff180 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -383,6 +383,10 @@ struct _VariantCall {
VCALL_LOCALMEM1R(Vector2, clamped);
VCALL_LOCALMEM0R(Vector2, sign);
+ VCALL_LOCALMEM0R(Vector2i, aspect);
+ VCALL_LOCALMEM0R(Vector2i, sign);
+ VCALL_LOCALMEM0R(Vector2i, abs);
+
VCALL_LOCALMEM0R(Rect2, get_area);
VCALL_LOCALMEM0R(Rect2, has_no_area);
VCALL_LOCALMEM1R(Rect2, has_point);
@@ -397,6 +401,19 @@ struct _VariantCall {
VCALL_LOCALMEM4R(Rect2, grow_individual);
VCALL_LOCALMEM0R(Rect2, abs);
+ VCALL_LOCALMEM0R(Rect2i, get_area);
+ VCALL_LOCALMEM0R(Rect2i, has_no_area);
+ VCALL_LOCALMEM1R(Rect2i, has_point);
+ VCALL_LOCALMEM1R(Rect2i, intersects);
+ VCALL_LOCALMEM1R(Rect2i, encloses);
+ VCALL_LOCALMEM1R(Rect2i, clip);
+ VCALL_LOCALMEM1R(Rect2i, merge);
+ VCALL_LOCALMEM1R(Rect2i, expand);
+ VCALL_LOCALMEM1R(Rect2i, grow);
+ VCALL_LOCALMEM2R(Rect2i, grow_margin);
+ VCALL_LOCALMEM4R(Rect2i, grow_individual);
+ VCALL_LOCALMEM0R(Rect2i, abs);
+
VCALL_LOCALMEM0R(Vector3, min_axis);
VCALL_LOCALMEM0R(Vector3, max_axis);
VCALL_LOCALMEM1R(Vector3, distance_to);
@@ -431,6 +448,10 @@ struct _VariantCall {
VCALL_LOCALMEM1R(Vector3, reflect);
VCALL_LOCALMEM0R(Vector3, sign);
+ VCALL_LOCALMEM0R(Vector3i, min_axis);
+ VCALL_LOCALMEM0R(Vector3i, max_axis);
+ VCALL_LOCALMEM0R(Vector3i, sign);
+
VCALL_LOCALMEM0R(Plane, normalized);
VCALL_LOCALMEM0R(Plane, center);
VCALL_LOCALMEM0R(Plane, get_any_point);
@@ -645,90 +666,115 @@ struct _VariantCall {
r_ret = s;
}
- VCALL_LOCALMEM0R(PackedByteArray, size);
- VCALL_LOCALMEM0R(PackedByteArray, empty);
- VCALL_LOCALMEM2(PackedByteArray, set);
- VCALL_LOCALMEM1R(PackedByteArray, get);
- VCALL_LOCALMEM1(PackedByteArray, push_back);
- VCALL_LOCALMEM1(PackedByteArray, resize);
- VCALL_LOCALMEM2R(PackedByteArray, insert);
- VCALL_LOCALMEM1(PackedByteArray, remove);
- VCALL_LOCALMEM1(PackedByteArray, append);
- VCALL_LOCALMEM1(PackedByteArray, append_array);
- VCALL_LOCALMEM0(PackedByteArray, invert);
- VCALL_LOCALMEM2R(PackedByteArray, subarray);
-
- VCALL_LOCALMEM0R(PackedIntArray, size);
- VCALL_LOCALMEM0R(PackedIntArray, empty);
- VCALL_LOCALMEM2(PackedIntArray, set);
- VCALL_LOCALMEM1R(PackedIntArray, get);
- VCALL_LOCALMEM1(PackedIntArray, push_back);
- VCALL_LOCALMEM1(PackedIntArray, resize);
- VCALL_LOCALMEM2R(PackedIntArray, insert);
- VCALL_LOCALMEM1(PackedIntArray, remove);
- VCALL_LOCALMEM1(PackedIntArray, append);
- VCALL_LOCALMEM1(PackedIntArray, append_array);
- VCALL_LOCALMEM0(PackedIntArray, invert);
-
- VCALL_LOCALMEM0R(PackedRealArray, size);
- VCALL_LOCALMEM0R(PackedRealArray, empty);
- VCALL_LOCALMEM2(PackedRealArray, set);
- VCALL_LOCALMEM1R(PackedRealArray, get);
- VCALL_LOCALMEM1(PackedRealArray, push_back);
- VCALL_LOCALMEM1(PackedRealArray, resize);
- VCALL_LOCALMEM2R(PackedRealArray, insert);
- VCALL_LOCALMEM1(PackedRealArray, remove);
- VCALL_LOCALMEM1(PackedRealArray, append);
- VCALL_LOCALMEM1(PackedRealArray, append_array);
- VCALL_LOCALMEM0(PackedRealArray, invert);
-
- VCALL_LOCALMEM0R(PackedStringArray, size);
- VCALL_LOCALMEM0R(PackedStringArray, empty);
- VCALL_LOCALMEM2(PackedStringArray, set);
- VCALL_LOCALMEM1R(PackedStringArray, get);
- VCALL_LOCALMEM1(PackedStringArray, push_back);
- VCALL_LOCALMEM1(PackedStringArray, resize);
- VCALL_LOCALMEM2R(PackedStringArray, insert);
- VCALL_LOCALMEM1(PackedStringArray, remove);
- VCALL_LOCALMEM1(PackedStringArray, append);
- VCALL_LOCALMEM1(PackedStringArray, append_array);
- VCALL_LOCALMEM0(PackedStringArray, invert);
-
- VCALL_LOCALMEM0R(PackedVector2Array, size);
- VCALL_LOCALMEM0R(PackedVector2Array, empty);
- VCALL_LOCALMEM2(PackedVector2Array, set);
- VCALL_LOCALMEM1R(PackedVector2Array, get);
- VCALL_LOCALMEM1(PackedVector2Array, push_back);
- VCALL_LOCALMEM1(PackedVector2Array, resize);
- VCALL_LOCALMEM2R(PackedVector2Array, insert);
- VCALL_LOCALMEM1(PackedVector2Array, remove);
- VCALL_LOCALMEM1(PackedVector2Array, append);
- VCALL_LOCALMEM1(PackedVector2Array, append_array);
- VCALL_LOCALMEM0(PackedVector2Array, invert);
-
- VCALL_LOCALMEM0R(PackedVector3Array, size);
- VCALL_LOCALMEM0R(PackedVector3Array, empty);
- VCALL_LOCALMEM2(PackedVector3Array, set);
- VCALL_LOCALMEM1R(PackedVector3Array, get);
- VCALL_LOCALMEM1(PackedVector3Array, push_back);
- VCALL_LOCALMEM1(PackedVector3Array, resize);
- VCALL_LOCALMEM2R(PackedVector3Array, insert);
- VCALL_LOCALMEM1(PackedVector3Array, remove);
- VCALL_LOCALMEM1(PackedVector3Array, append);
- VCALL_LOCALMEM1(PackedVector3Array, append_array);
- VCALL_LOCALMEM0(PackedVector3Array, invert);
-
- VCALL_LOCALMEM0R(PackedColorArray, size);
- VCALL_LOCALMEM0R(PackedColorArray, empty);
- VCALL_LOCALMEM2(PackedColorArray, set);
- VCALL_LOCALMEM1R(PackedColorArray, get);
- VCALL_LOCALMEM1(PackedColorArray, push_back);
- VCALL_LOCALMEM1(PackedColorArray, resize);
- VCALL_LOCALMEM2R(PackedColorArray, insert);
- VCALL_LOCALMEM1(PackedColorArray, remove);
- VCALL_LOCALMEM1(PackedColorArray, append);
- VCALL_LOCALMEM1(PackedColorArray, append_array);
- VCALL_LOCALMEM0(PackedColorArray, invert);
+#define VCALL_PARRMEM0(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(); }
+#define VCALL_PARRMEM0R(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(); }
+#define VCALL_PARRMEM1(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0]); }
+#define VCALL_PARRMEM1R(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0]); }
+#define VCALL_PARRMEM2(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1]); }
+#define VCALL_PARRMEM2R(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1]); }
+#define VCALL_PARRMEM3(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2]); }
+#define VCALL_PARRMEM3R(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2]); }
+#define VCALL_PARRMEM4(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); }
+#define VCALL_PARRMEM4R(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); }
+#define VCALL_PARRMEM5(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); }
+#define VCALL_PARRMEM5R(m_type, m_elemtype, m_method) \
+ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); }
+
+ VCALL_PARRMEM0R(PackedByteArray, uint8_t, size);
+ VCALL_PARRMEM0R(PackedByteArray, uint8_t, empty);
+ VCALL_PARRMEM2(PackedByteArray, uint8_t, set);
+ VCALL_PARRMEM1R(PackedByteArray, uint8_t, get);
+ VCALL_PARRMEM1(PackedByteArray, uint8_t, push_back);
+ VCALL_PARRMEM1(PackedByteArray, uint8_t, resize);
+ VCALL_PARRMEM2R(PackedByteArray, uint8_t, insert);
+ VCALL_PARRMEM1(PackedByteArray, uint8_t, remove);
+ VCALL_PARRMEM1(PackedByteArray, uint8_t, append);
+ VCALL_PARRMEM1(PackedByteArray, uint8_t, append_array);
+ VCALL_PARRMEM0(PackedByteArray, uint8_t, invert);
+ VCALL_PARRMEM2R(PackedByteArray, uint8_t, subarray);
+
+ VCALL_PARRMEM0R(PackedIntArray, int32_t, size);
+ VCALL_PARRMEM0R(PackedIntArray, int32_t, empty);
+ VCALL_PARRMEM2(PackedIntArray, int32_t, set);
+ VCALL_PARRMEM1R(PackedIntArray, int32_t, get);
+ VCALL_PARRMEM1(PackedIntArray, int32_t, push_back);
+ VCALL_PARRMEM1(PackedIntArray, int32_t, resize);
+ VCALL_PARRMEM2R(PackedIntArray, int32_t, insert);
+ VCALL_PARRMEM1(PackedIntArray, int32_t, remove);
+ VCALL_PARRMEM1(PackedIntArray, int32_t, append);
+ VCALL_PARRMEM1(PackedIntArray, int32_t, append_array);
+ VCALL_PARRMEM0(PackedIntArray, int32_t, invert);
+
+ VCALL_PARRMEM0R(PackedRealArray, real_t, size);
+ VCALL_PARRMEM0R(PackedRealArray, real_t, empty);
+ VCALL_PARRMEM2(PackedRealArray, real_t, set);
+ VCALL_PARRMEM1R(PackedRealArray, real_t, get);
+ VCALL_PARRMEM1(PackedRealArray, real_t, push_back);
+ VCALL_PARRMEM1(PackedRealArray, real_t, resize);
+ VCALL_PARRMEM2R(PackedRealArray, real_t, insert);
+ VCALL_PARRMEM1(PackedRealArray, real_t, remove);
+ VCALL_PARRMEM1(PackedRealArray, real_t, append);
+ VCALL_PARRMEM1(PackedRealArray, real_t, append_array);
+ VCALL_PARRMEM0(PackedRealArray, real_t, invert);
+
+ VCALL_PARRMEM0R(PackedStringArray, String, size);
+ VCALL_PARRMEM0R(PackedStringArray, String, empty);
+ VCALL_PARRMEM2(PackedStringArray, String, set);
+ VCALL_PARRMEM1R(PackedStringArray, String, get);
+ VCALL_PARRMEM1(PackedStringArray, String, push_back);
+ VCALL_PARRMEM1(PackedStringArray, String, resize);
+ VCALL_PARRMEM2R(PackedStringArray, String, insert);
+ VCALL_PARRMEM1(PackedStringArray, String, remove);
+ VCALL_PARRMEM1(PackedStringArray, String, append);
+ VCALL_PARRMEM1(PackedStringArray, String, append_array);
+ VCALL_PARRMEM0(PackedStringArray, String, invert);
+
+ VCALL_PARRMEM0R(PackedVector2Array, Vector2, size);
+ VCALL_PARRMEM0R(PackedVector2Array, Vector2, empty);
+ VCALL_PARRMEM2(PackedVector2Array, Vector2, set);
+ VCALL_PARRMEM1R(PackedVector2Array, Vector2, get);
+ VCALL_PARRMEM1(PackedVector2Array, Vector2, push_back);
+ VCALL_PARRMEM1(PackedVector2Array, Vector2, resize);
+ VCALL_PARRMEM2R(PackedVector2Array, Vector2, insert);
+ VCALL_PARRMEM1(PackedVector2Array, Vector2, remove);
+ VCALL_PARRMEM1(PackedVector2Array, Vector2, append);
+ VCALL_PARRMEM1(PackedVector2Array, Vector2, append_array);
+ VCALL_PARRMEM0(PackedVector2Array, Vector2, invert);
+
+ VCALL_PARRMEM0R(PackedVector3Array, Vector3, size);
+ VCALL_PARRMEM0R(PackedVector3Array, Vector3, empty);
+ VCALL_PARRMEM2(PackedVector3Array, Vector3, set);
+ VCALL_PARRMEM1R(PackedVector3Array, Vector3, get);
+ VCALL_PARRMEM1(PackedVector3Array, Vector3, push_back);
+ VCALL_PARRMEM1(PackedVector3Array, Vector3, resize);
+ VCALL_PARRMEM2R(PackedVector3Array, Vector3, insert);
+ VCALL_PARRMEM1(PackedVector3Array, Vector3, remove);
+ VCALL_PARRMEM1(PackedVector3Array, Vector3, append);
+ VCALL_PARRMEM1(PackedVector3Array, Vector3, append_array);
+ VCALL_PARRMEM0(PackedVector3Array, Vector3, invert);
+
+ VCALL_PARRMEM0R(PackedColorArray, Color, size);
+ VCALL_PARRMEM0R(PackedColorArray, Color, empty);
+ VCALL_PARRMEM2(PackedColorArray, Color, set);
+ VCALL_PARRMEM1R(PackedColorArray, Color, get);
+ VCALL_PARRMEM1(PackedColorArray, Color, push_back);
+ VCALL_PARRMEM1(PackedColorArray, Color, resize);
+ VCALL_PARRMEM2R(PackedColorArray, Color, insert);
+ VCALL_PARRMEM1(PackedColorArray, Color, remove);
+ VCALL_PARRMEM1(PackedColorArray, Color, append);
+ VCALL_PARRMEM1(PackedColorArray, Color, append_array);
+ VCALL_PARRMEM0(PackedColorArray, Color, invert);
#define VCALL_PTR0(m_type, m_method) \
static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(); }
@@ -909,6 +955,11 @@ struct _VariantCall {
r_ret = Vector2(*p_args[0], *p_args[1]);
}
+ static void Vector2i_init1(Variant &r_ret, const Variant **p_args) {
+
+ r_ret = Vector2i(*p_args[0], *p_args[1]);
+ }
+
static void Rect2_init1(Variant &r_ret, const Variant **p_args) {
r_ret = Rect2(*p_args[0], *p_args[1]);
@@ -919,6 +970,16 @@ struct _VariantCall {
r_ret = Rect2(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
}
+ static void Rect2i_init1(Variant &r_ret, const Variant **p_args) {
+
+ r_ret = Rect2i(*p_args[0], *p_args[1]);
+ }
+
+ static void Rect2i_init2(Variant &r_ret, const Variant **p_args) {
+
+ r_ret = Rect2i(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
+ }
+
static void Transform2D_init2(Variant &r_ret, const Variant **p_args) {
Transform2D m(*p_args[0], *p_args[1]);
@@ -939,6 +1000,11 @@ struct _VariantCall {
r_ret = Vector3(*p_args[0], *p_args[1], *p_args[2]);
}
+ static void Vector3i_init1(Variant &r_ret, const Variant **p_args) {
+
+ r_ret = Vector3i(*p_args[0], *p_args[1], *p_args[2]);
+ }
+
static void Plane_init1(Variant &r_ret, const Variant **p_args) {
r_ret = Plane(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
@@ -1215,6 +1281,8 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
// misc types
case COLOR: return Color();
+ case STRING_NAME:
+ return StringName(); // 15
case NODE_PATH:
return NodePath(); // 15
case _RID: return RID();
@@ -1260,8 +1328,13 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
case VECTOR2: {
return Vector2(*p_args[0]);
}
+ case VECTOR2I: {
+ return Vector2i(*p_args[0]);
+ }
case RECT2: return (Rect2(*p_args[0]));
+ case RECT2I: return (Rect2i(*p_args[0]));
case VECTOR3: return (Vector3(*p_args[0]));
+ case VECTOR3I: return (Vector3i(*p_args[0]));
case PLANE: return (Plane(*p_args[0]));
case QUAT: return (p_args[0]->operator Quat());
case AABB:
@@ -1272,10 +1345,14 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
// misc types
case COLOR: return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]);
+ case STRING_NAME:
+ return (StringName(p_args[0]->operator StringName())); // 15
case NODE_PATH:
return (NodePath(p_args[0]->operator NodePath())); // 15
case _RID: return (RID(*p_args[0]));
case OBJECT: return ((Object *)(p_args[0]->operator Object *()));
+ case CALLABLE: return ((Callable)(p_args[0]->operator Callable()));
+ case SIGNAL: return ((Signal)(p_args[0]->operator Signal()));
case DICTIONARY: return p_args[0]->operator Dictionary();
case ARRAY:
return p_args[0]->operator Array(); // 20
@@ -1721,6 +1798,10 @@ void register_variant_methods() {
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
ADDFUNC0R(VECTOR2, VECTOR2, Vector2, sign, varray());
+ ADDFUNC0R(VECTOR2I, REAL, Vector2i, aspect, varray());
+ ADDFUNC0R(VECTOR2I, VECTOR2I, Vector2i, sign, varray());
+ ADDFUNC0R(VECTOR2I, VECTOR2I, Vector2i, abs, varray());
+
ADDFUNC0R(RECT2, REAL, Rect2, get_area, varray());
ADDFUNC0R(RECT2, BOOL, Rect2, has_no_area, varray());
ADDFUNC1R(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray());
@@ -1735,6 +1816,19 @@ void register_variant_methods() {
ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
ADDFUNC0R(RECT2, RECT2, Rect2, abs, varray());
+ ADDFUNC0R(RECT2I, INT, Rect2i, get_area, varray());
+ ADDFUNC0R(RECT2I, BOOL, Rect2i, has_no_area, varray());
+ ADDFUNC1R(RECT2I, BOOL, Rect2i, has_point, VECTOR2I, "point", varray());
+ ADDFUNC1R(RECT2I, BOOL, Rect2i, intersects, RECT2I, "b", varray());
+ ADDFUNC1R(RECT2I, BOOL, Rect2i, encloses, RECT2I, "b", varray());
+ ADDFUNC1R(RECT2I, RECT2I, Rect2i, clip, RECT2I, "b", varray());
+ ADDFUNC1R(RECT2I, RECT2I, Rect2i, merge, RECT2I, "b", varray());
+ ADDFUNC1R(RECT2I, RECT2I, Rect2i, expand, VECTOR2I, "to", varray());
+ ADDFUNC1R(RECT2I, RECT2I, Rect2i, grow, INT, "by", varray());
+ ADDFUNC2R(RECT2I, RECT2I, Rect2i, grow_margin, INT, "margin", INT, "by", varray());
+ ADDFUNC4R(RECT2I, RECT2I, Rect2i, grow_individual, INT, "left", INT, "top", INT, "right", INT, " bottom", varray());
+ ADDFUNC0R(RECT2I, RECT2I, Rect2i, abs, varray());
+
ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray());
ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray());
ADDFUNC1R(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray());
@@ -1769,6 +1863,10 @@ void register_variant_methods() {
ADDFUNC1R(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray());
ADDFUNC0R(VECTOR3, VECTOR3, Vector3, sign, varray());
+ ADDFUNC0R(VECTOR3I, INT, Vector3i, min_axis, varray());
+ ADDFUNC0R(VECTOR3I, INT, Vector3i, max_axis, varray());
+ ADDFUNC0R(VECTOR3I, VECTOR3I, Vector3i, sign, varray());
+
ADDFUNC0R(PLANE, PLANE, Plane, normalized, varray());
ADDFUNC0R(PLANE, VECTOR3, Plane, center, varray());
ADDFUNC0R(PLANE, VECTOR3, Plane, get_any_point, varray());
@@ -1840,13 +1938,13 @@ void register_variant_methods() {
ADDFUNC0R(CALLABLE, BOOL, Callable, is_standard, varray());
ADDFUNC0R(CALLABLE, OBJECT, Callable, get_object, varray());
ADDFUNC0R(CALLABLE, INT, Callable, get_object_id, varray());
- ADDFUNC0R(CALLABLE, STRING, Callable, get_method, varray());
+ ADDFUNC0R(CALLABLE, STRING_NAME, Callable, get_method, varray());
ADDFUNC0R(CALLABLE, INT, Callable, hash, varray());
ADDFUNC0R(SIGNAL, BOOL, Signal, is_null, varray());
ADDFUNC0R(SIGNAL, OBJECT, Signal, get_object, varray());
ADDFUNC0R(SIGNAL, INT, Signal, get_object_id, varray());
- ADDFUNC0R(SIGNAL, STRING, Signal, get_name, varray());
+ ADDFUNC0R(SIGNAL, STRING_NAME, Signal, get_name, varray());
ADDFUNC3R(SIGNAL, INT, Signal, connect, CALLABLE, "callable", ARRAY, "binds", INT, "flags", varray(Array(), 0));
@@ -2042,14 +2140,19 @@ void register_variant_methods() {
/* REGISTER CONSTRUCTORS */
_VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::REAL, "y", Variant::REAL);
+ _VariantCall::add_constructor(_VariantCall::Vector2i_init1, Variant::VECTOR2I, "x", Variant::INT, "y", Variant::INT);
_VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Rect2_init2, Variant::RECT2, "x", Variant::REAL, "y", Variant::REAL, "width", Variant::REAL, "height", Variant::REAL);
+ _VariantCall::add_constructor(_VariantCall::Rect2i_init1, Variant::RECT2I, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
+ _VariantCall::add_constructor(_VariantCall::Rect2i_init2, Variant::RECT2I, "x", Variant::INT, "y", Variant::INT, "width", Variant::INT, "height", Variant::INT);
+
_VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rotation", Variant::REAL, "position", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Transform2D_init3, Variant::TRANSFORM2D, "x_axis", Variant::VECTOR2, "y_axis", Variant::VECTOR2, "origin", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Vector3_init1, Variant::VECTOR3, "x", Variant::REAL, "y", Variant::REAL, "z", Variant::REAL);
+ _VariantCall::add_constructor(_VariantCall::Vector3i_init1, Variant::VECTOR3I, "x", Variant::INT, "y", Variant::INT, "z", Variant::INT);
_VariantCall::add_constructor(_VariantCall::Plane_init1, Variant::PLANE, "a", Variant::REAL, "b", Variant::REAL, "c", Variant::REAL, "d", Variant::REAL);
_VariantCall::add_constructor(_VariantCall::Plane_init2, Variant::PLANE, "v1", Variant::VECTOR3, "v2", Variant::VECTOR3, "v3", Variant::VECTOR3);
@@ -2070,8 +2173,8 @@ void register_variant_methods() {
_VariantCall::add_constructor(_VariantCall::Transform_init1, Variant::TRANSFORM, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3, "origin", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Transform_init2, Variant::TRANSFORM, "basis", Variant::BASIS, "origin", Variant::VECTOR3);
- _VariantCall::add_constructor(_VariantCall::Callable_init2, Variant::CALLABLE, "object", Variant::OBJECT, "method_name", Variant::STRING);
- _VariantCall::add_constructor(_VariantCall::Signal_init2, Variant::SIGNAL, "object", Variant::OBJECT, "signal_name", Variant::STRING);
+ _VariantCall::add_constructor(_VariantCall::Callable_init2, Variant::CALLABLE, "object", Variant::OBJECT, "method_name", Variant::STRING_NAME);
+ _VariantCall::add_constructor(_VariantCall::Signal_init2, Variant::SIGNAL, "object", Variant::OBJECT, "signal_name", Variant::STRING_NAME);
/* REGISTER CONSTANTS */
@@ -2094,9 +2197,25 @@ void register_variant_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1));
_VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1));
+ _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3::AXIS_X);
+ _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3::AXIS_Y);
+ _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3::AXIS_Z);
+
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1));
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "RIGHT", Vector3i(1, 0, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "UP", Vector3i(0, 1, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "DOWN", Vector3i(0, -1, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "FORWARD", Vector3i(0, 0, -1));
+ _VariantCall::add_variant_constant(Variant::VECTOR3I, "BACK", Vector3i(0, 0, 1));
+
_VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X);
_VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y);
+ _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_X", Vector2::AXIS_X);
+ _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_Y", Vector2::AXIS_Y);
+
_VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1));
_VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF));
@@ -2105,6 +2224,13 @@ void register_variant_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR2, "UP", Vector2(0, -1));
_VariantCall::add_variant_constant(Variant::VECTOR2, "DOWN", Vector2(0, 1));
+ _VariantCall::add_variant_constant(Variant::VECTOR2I, "ZERO", Vector2i(0, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR2I, "ONE", Vector2i(1, 1));
+ _VariantCall::add_variant_constant(Variant::VECTOR2I, "LEFT", Vector2i(-1, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR2I, "RIGHT", Vector2i(1, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR2I, "UP", Vector2i(0, -1));
+ _VariantCall::add_variant_constant(Variant::VECTOR2I, "DOWN", Vector2i(0, 1));
+
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D());
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 6c98cf4de1..37f890e069 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -44,8 +44,11 @@
CASE_TYPE(PREFIX, OP, REAL) \
CASE_TYPE(PREFIX, OP, STRING) \
CASE_TYPE(PREFIX, OP, VECTOR2) \
+ CASE_TYPE(PREFIX, OP, VECTOR2I) \
CASE_TYPE(PREFIX, OP, RECT2) \
+ CASE_TYPE(PREFIX, OP, RECT2I) \
CASE_TYPE(PREFIX, OP, VECTOR3) \
+ CASE_TYPE(PREFIX, OP, VECTOR3I) \
CASE_TYPE(PREFIX, OP, TRANSFORM2D) \
CASE_TYPE(PREFIX, OP, PLANE) \
CASE_TYPE(PREFIX, OP, QUAT) \
@@ -53,6 +56,7 @@
CASE_TYPE(PREFIX, OP, BASIS) \
CASE_TYPE(PREFIX, OP, TRANSFORM) \
CASE_TYPE(PREFIX, OP, COLOR) \
+ CASE_TYPE(PREFIX, OP, STRING_NAME) \
CASE_TYPE(PREFIX, OP, NODE_PATH) \
CASE_TYPE(PREFIX, OP, _RID) \
CASE_TYPE(PREFIX, OP, OBJECT) \
@@ -79,8 +83,11 @@
TYPE(PREFIX, OP, REAL), \
TYPE(PREFIX, OP, STRING), \
TYPE(PREFIX, OP, VECTOR2), \
+ TYPE(PREFIX, OP, VECTOR2I), \
TYPE(PREFIX, OP, RECT2), \
+ TYPE(PREFIX, OP, RECT2I), \
TYPE(PREFIX, OP, VECTOR3), \
+ TYPE(PREFIX, OP, VECTOR3I), \
TYPE(PREFIX, OP, TRANSFORM2D), \
TYPE(PREFIX, OP, PLANE), \
TYPE(PREFIX, OP, QUAT), \
@@ -88,6 +95,7 @@
TYPE(PREFIX, OP, BASIS), \
TYPE(PREFIX, OP, TRANSFORM), \
TYPE(PREFIX, OP, COLOR), \
+ TYPE(PREFIX, OP, STRING_NAME), \
TYPE(PREFIX, OP, NODE_PATH), \
TYPE(PREFIX, OP, _RID), \
TYPE(PREFIX, OP, OBJECT), \
@@ -226,33 +234,47 @@ bool Variant::booleanize() const {
_RETURN(p_a._data.m_type); \
};
-#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \
- CASE_TYPE(m_prefix, m_op_name, m_name) { \
- if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
- if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
- if (p_b.type == VECTOR2) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
- if (p_b.type == VECTOR3) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
- \
- _RETURN_FAIL \
+#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
+ if (p_b.type == VECTOR2) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
+ if (p_b.type == VECTOR3) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
+ if (p_b.type == VECTOR2I) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
+ if (p_b.type == VECTOR3I) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
+ \
+ _RETURN_FAIL \
};
-#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
- CASE_TYPE(m_prefix, m_op_name, m_name) { \
- if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \
- if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \
- \
- _RETURN_FAIL \
+#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \
+ if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const StringName *>(p_a._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \
+ \
+ _RETURN_FAIL \
};
-#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \
- CASE_TYPE(m_prefix, m_op_name, m_name) { \
- if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
- if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
- \
- _RETURN_FAIL \
+#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
+ if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
+ if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
+ if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \
+ \
+ _RETURN_FAIL \
};
-#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
+#define DEFAULT_OP_STR_NULL_NP(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
@@ -261,6 +283,15 @@ bool Variant::booleanize() const {
_RETURN_FAIL \
};
+#define DEFAULT_OP_STR_NULL_SN(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
+ if (p_b.type == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \
+ if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \
+ \
+ _RETURN_FAIL \
+ };
+
#define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
if (p_b.type == m_name) \
@@ -361,8 +392,8 @@ bool Variant::booleanize() const {
if (p_a.type != p_b.type) \
_RETURN_FAIL \
\
- const Vector<m_type> &array_a = *reinterpret_cast<const Vector<m_type> *>(p_a._data._mem); \
- const Vector<m_type> &array_b = *reinterpret_cast<const Vector<m_type> *>(p_b._data._mem); \
+ const Vector<m_type> &array_a = PackedArrayRef<m_type>::get_array(p_a._data.packed_array); \
+ const Vector<m_type> &array_b = PackedArrayRef<m_type>::get_array(p_b._data.packed_array); \
\
int a_len = array_a.size(); \
if (a_len m_opa array_b.size()) { \
@@ -385,8 +416,8 @@ bool Variant::booleanize() const {
if (p_a.type != p_b.type) \
_RETURN_FAIL; \
\
- const Vector<m_type> &array_a = *reinterpret_cast<const Vector<m_type> *>(p_a._data._mem); \
- const Vector<m_type> &array_b = *reinterpret_cast<const Vector<m_type> *>(p_b._data._mem); \
+ const Vector<m_type> &array_a = PackedArrayRef<m_type>::get_array(p_a._data.packed_array); \
+ const Vector<m_type> &array_b = PackedArrayRef<m_type>::get_array(p_b._data.packed_array); \
Vector<m_type> sum = array_a; \
sum.append_array(array_b); \
_RETURN(sum); \
@@ -468,16 +499,20 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM_NULL(math, OP_EQUAL, REAL, ==, _real);
DEFAULT_OP_STR_NULL(math, OP_EQUAL, STRING, ==, String);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2, ==, Vector2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2I, ==, Vector2i);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2, ==, Rect2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2I, ==, Rect2i);
DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3, ==, Vector3);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3I, ==, Vector3i);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, PLANE, ==, Plane);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, QUAT, ==, Quat);
DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, AABB, ==, _aabb);
DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, BASIS, ==, _basis);
DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM, ==, _transform);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, COLOR, ==, Color);
- DEFAULT_OP_STR_NULL(math, OP_EQUAL, NODE_PATH, ==, NodePath);
+ DEFAULT_OP_STR_NULL_SN(math, OP_EQUAL, STRING_NAME, ==, StringName);
+ DEFAULT_OP_STR_NULL_NP(math, OP_EQUAL, NODE_PATH, ==, NodePath);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, _RID, ==, RID);
DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_BYTE_ARRAY, uint8_t);
@@ -561,16 +596,20 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, REAL, !=, _real);
DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, STRING, !=, String);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2I, !=, Vector2i);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2, !=, Rect2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2I, !=, Rect2i);
DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3I, !=, Vector3i);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, PLANE, !=, Plane);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, QUAT, !=, Quat);
DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, AABB, !=, _aabb);
DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, BASIS, !=, _basis);
DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, COLOR, !=, Color);
- DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath);
+ DEFAULT_OP_STR_NULL_SN(math, OP_NOT_EQUAL, STRING_NAME, !=, StringName);
+ DEFAULT_OP_STR_NULL_NP(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, _RID, !=, RID);
DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_BYTE_ARRAY, uint8_t);
@@ -628,7 +667,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM(math, OP_LESS, REAL, <, _real);
DEFAULT_OP_STR(math, OP_LESS, STRING, <, String);
DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2I, <, Vector2i);
DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3I, <, Vector3i);
DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID);
DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_BYTE_ARRAY, uint8_t);
DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_INT_ARRAY, int);
@@ -640,6 +681,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_LESS, NIL)
CASE_TYPE(math, OP_LESS, RECT2)
+ CASE_TYPE(math, OP_LESS, RECT2I)
CASE_TYPE(math, OP_LESS, TRANSFORM2D)
CASE_TYPE(math, OP_LESS, PLANE)
CASE_TYPE(math, OP_LESS, QUAT)
@@ -647,6 +689,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_LESS, BASIS)
CASE_TYPE(math, OP_LESS, TRANSFORM)
CASE_TYPE(math, OP_LESS, COLOR)
+ CASE_TYPE(math, OP_LESS, STRING_NAME)
CASE_TYPE(math, OP_LESS, NODE_PATH)
CASE_TYPE(math, OP_LESS, DICTIONARY)
_RETURN_FAIL;
@@ -663,12 +706,15 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM(math, OP_LESS_EQUAL, REAL, <=, _real);
DEFAULT_OP_STR(math, OP_LESS_EQUAL, STRING, <=, String);
DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2, <=, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2I, <=, Vector2i);
DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3, <=, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3I, <=, Vector3i);
DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, _RID, <=, RID);
CASE_TYPE(math, OP_LESS_EQUAL, NIL)
CASE_TYPE(math, OP_LESS_EQUAL, BOOL)
CASE_TYPE(math, OP_LESS_EQUAL, RECT2)
+ CASE_TYPE(math, OP_LESS_EQUAL, RECT2I)
CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D)
CASE_TYPE(math, OP_LESS_EQUAL, PLANE)
CASE_TYPE(math, OP_LESS_EQUAL, QUAT)
@@ -676,6 +722,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_LESS_EQUAL, BASIS)
CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM)
CASE_TYPE(math, OP_LESS_EQUAL, COLOR)
+ CASE_TYPE(math, OP_LESS_EQUAL, STRING_NAME)
CASE_TYPE(math, OP_LESS_EQUAL, NODE_PATH)
CASE_TYPE(math, OP_LESS_EQUAL, CALLABLE)
CASE_TYPE(math, OP_LESS_EQUAL, SIGNAL)
@@ -735,7 +782,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM(math, OP_GREATER, REAL, >, _real);
DEFAULT_OP_STR_REV(math, OP_GREATER, STRING, <, String);
DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2I, <, Vector2i);
DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3I, <, Vector3i);
DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID);
DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_BYTE_ARRAY, uint8_t);
DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_INT_ARRAY, int);
@@ -747,6 +796,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_GREATER, NIL)
CASE_TYPE(math, OP_GREATER, RECT2)
+ CASE_TYPE(math, OP_GREATER, RECT2I)
CASE_TYPE(math, OP_GREATER, TRANSFORM2D)
CASE_TYPE(math, OP_GREATER, PLANE)
CASE_TYPE(math, OP_GREATER, QUAT)
@@ -754,6 +804,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_GREATER, BASIS)
CASE_TYPE(math, OP_GREATER, TRANSFORM)
CASE_TYPE(math, OP_GREATER, COLOR)
+ CASE_TYPE(math, OP_GREATER, STRING_NAME)
CASE_TYPE(math, OP_GREATER, NODE_PATH)
CASE_TYPE(math, OP_GREATER, DICTIONARY)
CASE_TYPE(math, OP_GREATER, CALLABLE)
@@ -773,12 +824,15 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, REAL, >=, _real);
DEFAULT_OP_STR_REV(math, OP_GREATER_EQUAL, STRING, <=, String);
DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2, <=, Vector2);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2I, <=, Vector2i);
DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3, <=, Vector3);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3I, <=, Vector3i);
DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, _RID, <=, RID);
CASE_TYPE(math, OP_GREATER_EQUAL, NIL)
CASE_TYPE(math, OP_GREATER_EQUAL, BOOL)
CASE_TYPE(math, OP_GREATER_EQUAL, RECT2)
+ CASE_TYPE(math, OP_GREATER_EQUAL, RECT2I)
CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D)
CASE_TYPE(math, OP_GREATER_EQUAL, PLANE)
CASE_TYPE(math, OP_GREATER_EQUAL, QUAT)
@@ -786,6 +840,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_GREATER_EQUAL, BASIS)
CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM)
CASE_TYPE(math, OP_GREATER_EQUAL, COLOR)
+ CASE_TYPE(math, OP_GREATER_EQUAL, STRING_NAME)
CASE_TYPE(math, OP_GREATER_EQUAL, NODE_PATH)
CASE_TYPE(math, OP_GREATER_EQUAL, CALLABLE)
CASE_TYPE(math, OP_GREATER_EQUAL, SIGNAL)
@@ -824,7 +879,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM(math, OP_ADD, REAL, +, _real);
DEFAULT_OP_STR(math, OP_ADD, STRING, +, String);
DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2, +, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2I, +, Vector2i);
DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3, +, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3I, +, Vector3i);
DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat);
DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color);
@@ -839,11 +896,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_ADD, NIL)
CASE_TYPE(math, OP_ADD, BOOL)
CASE_TYPE(math, OP_ADD, RECT2)
+ CASE_TYPE(math, OP_ADD, RECT2I)
CASE_TYPE(math, OP_ADD, TRANSFORM2D)
CASE_TYPE(math, OP_ADD, PLANE)
CASE_TYPE(math, OP_ADD, AABB)
CASE_TYPE(math, OP_ADD, BASIS)
CASE_TYPE(math, OP_ADD, TRANSFORM)
+ CASE_TYPE(math, OP_ADD, STRING_NAME)
CASE_TYPE(math, OP_ADD, NODE_PATH)
CASE_TYPE(math, OP_ADD, _RID)
CASE_TYPE(math, OP_ADD, OBJECT)
@@ -858,7 +917,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM(math, OP_SUBTRACT, INT, -, _int);
DEFAULT_OP_NUM(math, OP_SUBTRACT, REAL, -, _real);
DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2, -, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2I, -, Vector2i);
DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3, -, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3I, -, Vector3i);
DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, QUAT, -, Quat);
DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, COLOR, -, Color);
@@ -866,11 +927,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_SUBTRACT, BOOL)
CASE_TYPE(math, OP_SUBTRACT, STRING)
CASE_TYPE(math, OP_SUBTRACT, RECT2)
+ CASE_TYPE(math, OP_SUBTRACT, RECT2I)
CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D)
CASE_TYPE(math, OP_SUBTRACT, PLANE)
CASE_TYPE(math, OP_SUBTRACT, AABB)
CASE_TYPE(math, OP_SUBTRACT, BASIS)
CASE_TYPE(math, OP_SUBTRACT, TRANSFORM)
+ CASE_TYPE(math, OP_SUBTRACT, STRING_NAME)
CASE_TYPE(math, OP_SUBTRACT, NODE_PATH)
CASE_TYPE(math, OP_SUBTRACT, _RID)
CASE_TYPE(math, OP_SUBTRACT, OBJECT)
@@ -944,15 +1007,19 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int);
DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, REAL, *, _real);
DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2I, *, Vector2i);
DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3I, *, Vector3i);
DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, COLOR, *, Color);
CASE_TYPE(math, OP_MULTIPLY, NIL)
CASE_TYPE(math, OP_MULTIPLY, BOOL)
CASE_TYPE(math, OP_MULTIPLY, STRING)
CASE_TYPE(math, OP_MULTIPLY, RECT2)
+ CASE_TYPE(math, OP_MULTIPLY, RECT2I)
CASE_TYPE(math, OP_MULTIPLY, PLANE)
CASE_TYPE(math, OP_MULTIPLY, AABB)
+ CASE_TYPE(math, OP_MULTIPLY, STRING_NAME)
CASE_TYPE(math, OP_MULTIPLY, NODE_PATH)
CASE_TYPE(math, OP_MULTIPLY, _RID)
CASE_TYPE(math, OP_MULTIPLY, OBJECT)
@@ -987,18 +1054,22 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int);
DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, REAL, _real);
DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2, /, Vector2);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2I, /, Vector2i);
DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3, /, Vector3);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3I, /, Vector3i);
DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, COLOR, /, Color);
CASE_TYPE(math, OP_DIVIDE, NIL)
CASE_TYPE(math, OP_DIVIDE, BOOL)
CASE_TYPE(math, OP_DIVIDE, STRING)
CASE_TYPE(math, OP_DIVIDE, RECT2)
+ CASE_TYPE(math, OP_DIVIDE, RECT2I)
CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D)
CASE_TYPE(math, OP_DIVIDE, PLANE)
CASE_TYPE(math, OP_DIVIDE, AABB)
CASE_TYPE(math, OP_DIVIDE, BASIS)
CASE_TYPE(math, OP_DIVIDE, TRANSFORM)
+ CASE_TYPE(math, OP_DIVIDE, STRING_NAME)
CASE_TYPE(math, OP_DIVIDE, NODE_PATH)
CASE_TYPE(math, OP_DIVIDE, _RID)
CASE_TYPE(math, OP_DIVIDE, OBJECT)
@@ -1021,19 +1092,23 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM_POS(math, OP_POSITIVE, INT, _int);
DEFAULT_OP_NUM_POS(math, OP_POSITIVE, REAL, _real);
DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3, Vector3);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3I, Vector3i);
DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, PLANE, Plane);
DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, QUAT, Quat);
DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2, Vector2);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2I, Vector2i);
CASE_TYPE(math, OP_POSITIVE, NIL)
CASE_TYPE(math, OP_POSITIVE, BOOL)
CASE_TYPE(math, OP_POSITIVE, STRING)
CASE_TYPE(math, OP_POSITIVE, RECT2)
+ CASE_TYPE(math, OP_POSITIVE, RECT2I)
CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D)
CASE_TYPE(math, OP_POSITIVE, AABB)
CASE_TYPE(math, OP_POSITIVE, BASIS)
CASE_TYPE(math, OP_POSITIVE, TRANSFORM)
CASE_TYPE(math, OP_POSITIVE, COLOR)
+ CASE_TYPE(math, OP_POSITIVE, STRING_NAME)
CASE_TYPE(math, OP_POSITIVE, NODE_PATH)
CASE_TYPE(math, OP_POSITIVE, _RID)
CASE_TYPE(math, OP_POSITIVE, OBJECT)
@@ -1057,7 +1132,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_NUM_NEG(math, OP_NEGATE, REAL, _real);
DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2, Vector2);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2I, Vector2i);
DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3, Vector3);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3I, Vector3i);
DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, PLANE, Plane);
DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, QUAT, Quat);
DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, COLOR, Color);
@@ -1066,10 +1143,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_NEGATE, BOOL)
CASE_TYPE(math, OP_NEGATE, STRING)
CASE_TYPE(math, OP_NEGATE, RECT2)
+ CASE_TYPE(math, OP_NEGATE, RECT2I)
CASE_TYPE(math, OP_NEGATE, TRANSFORM2D)
CASE_TYPE(math, OP_NEGATE, AABB)
CASE_TYPE(math, OP_NEGATE, BASIS)
CASE_TYPE(math, OP_NEGATE, TRANSFORM)
+ CASE_TYPE(math, OP_NEGATE, STRING_NAME)
CASE_TYPE(math, OP_NEGATE, NODE_PATH)
CASE_TYPE(math, OP_NEGATE, _RID)
CASE_TYPE(math, OP_NEGATE, OBJECT)
@@ -1124,8 +1203,11 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_MODULE, BOOL)
CASE_TYPE(math, OP_MODULE, REAL)
CASE_TYPE(math, OP_MODULE, VECTOR2)
+ CASE_TYPE(math, OP_MODULE, VECTOR2I)
CASE_TYPE(math, OP_MODULE, RECT2)
+ CASE_TYPE(math, OP_MODULE, RECT2I)
CASE_TYPE(math, OP_MODULE, VECTOR3)
+ CASE_TYPE(math, OP_MODULE, VECTOR3I)
CASE_TYPE(math, OP_MODULE, TRANSFORM2D)
CASE_TYPE(math, OP_MODULE, PLANE)
CASE_TYPE(math, OP_MODULE, QUAT)
@@ -1133,6 +1215,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_MODULE, BASIS)
CASE_TYPE(math, OP_MODULE, TRANSFORM)
CASE_TYPE(math, OP_MODULE, COLOR)
+ CASE_TYPE(math, OP_MODULE, STRING_NAME)
CASE_TYPE(math, OP_MODULE, NODE_PATH)
CASE_TYPE(math, OP_MODULE, _RID)
CASE_TYPE(math, OP_MODULE, OBJECT)
@@ -1292,6 +1375,28 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
}
} break;
+ case VECTOR2I: {
+ if (p_value.type == Variant::INT) {
+ Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ }
+ }
+
+ } break;
case RECT2: {
if (p_value.type == Variant::VECTOR2) {
@@ -1309,6 +1414,23 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
}
}
} break;
+ case RECT2I: {
+
+ if (p_value.type == Variant::VECTOR2I) {
+ Rect2i *v = reinterpret_cast<Rect2i *>(_data._mem);
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ v->position = *reinterpret_cast<const Vector2i *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ v->size = *reinterpret_cast<const Vector2i *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ v->size = *reinterpret_cast<const Vector2i *>(p_value._data._mem) - v->position;
+ valid = true;
+ }
+ }
+ } break;
case TRANSFORM2D: {
if (p_value.type == Variant::VECTOR2) {
@@ -1355,6 +1477,35 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
}
} break;
+ case VECTOR3I: {
+
+ if (p_value.type == Variant::INT) {
+ Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._real;
+ valid = true;
+ }
+ }
+
+ } break;
case PLANE: {
if (p_value.type == Variant::INT) {
@@ -1591,6 +1742,15 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
}
} break;
+ case VECTOR2I: {
+ const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ }
+
+ } break;
case RECT2: {
const Rect2 *v = reinterpret_cast<const Rect2 *>(_data._mem);
@@ -1603,6 +1763,18 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
return v->size + v->position;
}
} break;
+ case RECT2I: {
+
+ const Rect2i *v = reinterpret_cast<const Rect2i *>(_data._mem);
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ return v->position;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ return v->size;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ return v->size + v->position;
+ }
+ } break;
case TRANSFORM2D: {
const Transform2D *v = _data._transform2d;
@@ -1627,6 +1799,18 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
}
} break;
+ case VECTOR3I: {
+
+ const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->z;
+ }
+
+ } break;
case PLANE: {
const Plane *v = reinterpret_cast<const Plane *>(_data._mem);
@@ -1767,11 +1951,38 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
} \
} break;
-#define DEFAULT_OP_DVECTOR_SET(m_name, dv_type, skip_cond) \
- DEFAULT_OP_ARRAY_CMD(m_name, Vector<dv_type>, if (skip_cond) return;, arr->set(index, p_value); return )
+#define DEFAULT_OP_DVECTOR_SET(m_name, m_type, skip_cond) \
+ case m_name: { \
+ if (skip_cond) return; \
+ \
+ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) { \
+ int index = p_index; \
+ Vector<m_type> *arr = PackedArrayRef<m_type>::get_array_ptr(_data.packed_array); \
+ \
+ if (index < 0) \
+ index += arr->size(); \
+ if (index >= 0 && index < arr->size()) { \
+ valid = true; \
+ arr->set(index, p_value); \
+ } \
+ } \
+ } break;
-#define DEFAULT_OP_DVECTOR_GET(m_name, dv_type) \
- DEFAULT_OP_ARRAY_CMD(m_name, const Vector<dv_type>, ;, return arr->get(index))
+#define DEFAULT_OP_DVECTOR_GET(m_name, m_type) \
+ case m_name: { \
+ \
+ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) { \
+ int index = p_index; \
+ const Vector<m_type> *arr = &PackedArrayRef<m_type>::get_array(_data.packed_array); \
+ \
+ if (index < 0) \
+ index += arr->size(); \
+ if (index >= 0 && index < arr->size()) { \
+ valid = true; \
+ return arr->get(index); \
+ } \
+ } \
+ } break;
void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) {
@@ -1857,6 +2068,41 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
}
} break; // 5
+ case VECTOR2I: {
+
+ if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
+ return;
+
+ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+ // scalar index
+ int idx = p_index;
+
+ if (idx < 0)
+ idx += 2;
+ if (idx >= 0 && idx < 2) {
+
+ Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+ valid = true;
+ (*v)[idx] = p_value;
+ return;
+ }
+ } else if (p_index.get_type() == Variant::STRING) {
+ //scalar name
+
+ const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+ Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+ if (*str == "x") {
+ valid = true;
+ v->x = p_value;
+ return;
+ } else if (*str == "y") {
+ valid = true;
+ v->y = p_value;
+ return;
+ }
+ }
+
+ } break; // 5
case RECT2: {
if (p_value.type != Variant::VECTOR2)
@@ -1882,6 +2128,31 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
}
}
} break;
+ case RECT2I: {
+
+ if (p_value.type != Variant::VECTOR2I)
+ return;
+
+ if (p_index.get_type() == Variant::STRING) {
+ //scalar name
+
+ const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+ Rect2i *v = reinterpret_cast<Rect2i *>(_data._mem);
+ if (*str == "position") {
+ valid = true;
+ v->position = p_value;
+ return;
+ } else if (*str == "size") {
+ valid = true;
+ v->size = p_value;
+ return;
+ } else if (*str == "end") {
+ valid = true;
+ v->size = Vector2i(p_value) - v->position;
+ return;
+ }
+ }
+ } break;
case TRANSFORM2D: {
if (p_value.type != Variant::VECTOR2)
@@ -1959,6 +2230,44 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
}
} break;
+ case VECTOR3I: {
+
+ if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
+ return;
+
+ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+ //scalar index
+ int idx = p_index;
+ if (idx < 0)
+ idx += 3;
+ if (idx >= 0 && idx < 3) {
+
+ Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+ valid = true;
+ (*v)[idx] = p_value;
+ return;
+ }
+ } else if (p_index.get_type() == Variant::STRING) {
+
+ //scalar name
+ const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+ Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+ if (*str == "x") {
+ valid = true;
+ v->x = p_value;
+ return;
+ } else if (*str == "y") {
+ valid = true;
+ v->y = p_value;
+ return;
+ } else if (*str == "z") {
+ valid = true;
+ v->z = p_value;
+ return;
+ }
+ }
+
+ } break;
case PLANE: {
if (p_index.get_type() == Variant::STRING) {
@@ -2204,6 +2513,8 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
}
} break;
+ case STRING_NAME: {
+ } break; // 15
case NODE_PATH: {
} break; // 15
case _RID: {
@@ -2223,7 +2534,7 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
}
#endif
- if (p_index.get_type() != Variant::STRING) {
+ if (p_index.get_type() != Variant::STRING_NAME && p_index.get_type() != Variant::STRING) {
obj->setvar(p_index, p_value, r_valid);
return;
}
@@ -2318,6 +2629,34 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
}
} break; // 5
+ case VECTOR2I: {
+
+ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+ // scalar index
+ int idx = p_index;
+ if (idx < 0)
+ idx += 2;
+ if (idx >= 0 && idx < 2) {
+
+ const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem);
+ valid = true;
+ return (*v)[idx];
+ }
+ } else if (p_index.get_type() == Variant::STRING) {
+ //scalar name
+
+ const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+ const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem);
+ if (*str == "x") {
+ valid = true;
+ return v->x;
+ } else if (*str == "y") {
+ valid = true;
+ return v->y;
+ }
+ }
+
+ } break; // 5
case RECT2: {
if (p_index.get_type() == Variant::STRING) {
@@ -2337,6 +2676,25 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
}
}
} break;
+ case RECT2I: {
+
+ if (p_index.get_type() == Variant::STRING) {
+ //scalar name
+
+ const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+ const Rect2i *v = reinterpret_cast<const Rect2i *>(_data._mem);
+ if (*str == "position") {
+ valid = true;
+ return v->position;
+ } else if (*str == "size") {
+ valid = true;
+ return v->size;
+ } else if (*str == "end") {
+ valid = true;
+ return v->size + v->position;
+ }
+ }
+ } break;
case VECTOR3: {
if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
@@ -2368,6 +2726,37 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
}
} break;
+ case VECTOR3I: {
+
+ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+ //scalar index
+ int idx = p_index;
+ if (idx < 0)
+ idx += 3;
+ if (idx >= 0 && idx < 3) {
+
+ const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem);
+ valid = true;
+ return (*v)[idx];
+ }
+ } else if (p_index.get_type() == Variant::STRING) {
+
+ //scalar name
+ const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+ const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem);
+ if (*str == "x") {
+ valid = true;
+ return v->x;
+ } else if (*str == "y") {
+ valid = true;
+ return v->y;
+ } else if (*str == "z") {
+ valid = true;
+ return v->z;
+ }
+ }
+
+ } break;
case TRANSFORM2D: {
if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
@@ -2578,6 +2967,8 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
}
} break;
+ case STRING_NAME: {
+ } break; // 15
case NODE_PATH: {
} break; // 15
case _RID: {
@@ -2698,7 +3089,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
int index = p_index;
- const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+ const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
int l = arr->size();
if (l) {
const uint8_t *r = arr->ptr();
@@ -2716,7 +3107,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
int index = p_index;
- const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+ const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
int l = arr->size();
if (l) {
const int *r = arr->ptr();
@@ -2734,7 +3125,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
real_t index = p_index;
- const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+ const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
int l = arr->size();
if (l) {
const real_t *r = arr->ptr();
@@ -2752,7 +3143,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
if (p_index.get_type() == Variant::STRING) {
String index = p_index;
- const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+ const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
int l = arr->size();
if (l) {
@@ -2771,7 +3162,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
if (p_index.get_type() == Variant::VECTOR2) {
Vector2 index = p_index;
- const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+ const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
int l = arr->size();
if (l) {
@@ -2790,7 +3181,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
if (p_index.get_type() == Variant::VECTOR3) {
Vector3 index = p_index;
- const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+ const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
int l = arr->size();
if (l) {
@@ -2810,7 +3201,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
if (p_index.get_type() == Variant::COLOR) {
Color index = p_index;
- const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+ const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
int l = arr->size();
if (l) {
@@ -2842,6 +3233,12 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::REAL, "y"));
} break; // 5
+ case VECTOR2I: {
+
+ p_list->push_back(PropertyInfo(Variant::INT, "x"));
+ p_list->push_back(PropertyInfo(Variant::INT, "y"));
+
+ } break; // 5
case RECT2: {
p_list->push_back(PropertyInfo(Variant::VECTOR2, "position"));
@@ -2849,6 +3246,13 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::VECTOR2, "end"));
} break;
+ case RECT2I: {
+
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "position"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, "end"));
+
+ } break;
case VECTOR3: {
p_list->push_back(PropertyInfo(Variant::REAL, "x"));
@@ -2856,6 +3260,13 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::REAL, "z"));
} break;
+ case VECTOR3I: {
+
+ p_list->push_back(PropertyInfo(Variant::INT, "x"));
+ p_list->push_back(PropertyInfo(Variant::INT, "y"));
+ p_list->push_back(PropertyInfo(Variant::INT, "z"));
+
+ } break;
case TRANSFORM2D: {
p_list->push_back(PropertyInfo(Variant::VECTOR2, "x"));
@@ -2912,6 +3323,8 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, "a8"));
} break;
+ case STRING_NAME: {
+ } break; // 15
case NODE_PATH: {
} break; // 15
case _RID: {
@@ -3056,7 +3469,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
return true;
} break;
case PACKED_BYTE_ARRAY: {
- const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+ const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
if (arr->size() == 0)
return false;
r_iter = 0;
@@ -3064,7 +3477,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
} break;
case PACKED_INT_ARRAY: {
- const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+ const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
if (arr->size() == 0)
return false;
r_iter = 0;
@@ -3072,7 +3485,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
} break;
case PACKED_REAL_ARRAY: {
- const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+ const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
if (arr->size() == 0)
return false;
r_iter = 0;
@@ -3080,7 +3493,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
} break;
case PACKED_STRING_ARRAY: {
- const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+ const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
if (arr->size() == 0)
return false;
r_iter = 0;
@@ -3088,7 +3501,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
} break;
case PACKED_VECTOR2_ARRAY: {
- const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+ const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
if (arr->size() == 0)
return false;
r_iter = 0;
@@ -3096,7 +3509,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
} break;
case PACKED_VECTOR3_ARRAY: {
- const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+ const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
if (arr->size() == 0)
return false;
r_iter = 0;
@@ -3104,7 +3517,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
} break;
case PACKED_COLOR_ARRAY: {
- const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+ const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
if (arr->size() == 0)
return false;
r_iter = 0;
@@ -3231,7 +3644,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
return true;
} break;
case PACKED_BYTE_ARRAY: {
- const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+ const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
int idx = r_iter;
idx++;
if (idx >= arr->size())
@@ -3241,7 +3654,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
} break;
case PACKED_INT_ARRAY: {
- const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+ const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
int idx = r_iter;
idx++;
if (idx >= arr->size())
@@ -3251,7 +3664,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
} break;
case PACKED_REAL_ARRAY: {
- const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+ const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
int idx = r_iter;
idx++;
if (idx >= arr->size())
@@ -3261,7 +3674,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
} break;
case PACKED_STRING_ARRAY: {
- const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+ const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
int idx = r_iter;
idx++;
if (idx >= arr->size())
@@ -3271,7 +3684,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
} break;
case PACKED_VECTOR2_ARRAY: {
- const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+ const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
int idx = r_iter;
idx++;
if (idx >= arr->size())
@@ -3281,7 +3694,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
} break;
case PACKED_VECTOR3_ARRAY: {
- const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+ const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
int idx = r_iter;
idx++;
if (idx >= arr->size())
@@ -3291,7 +3704,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
} break;
case PACKED_COLOR_ARRAY: {
- const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+ const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
int idx = r_iter;
idx++;
if (idx >= arr->size())
@@ -3378,7 +3791,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
return arr->get(idx);
} break;
case PACKED_BYTE_ARRAY: {
- const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem);
+ const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
int idx = r_iter;
#ifdef DEBUG_ENABLED
if (idx < 0 || idx >= arr->size()) {
@@ -3389,7 +3802,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
return arr->get(idx);
} break;
case PACKED_INT_ARRAY: {
- const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem);
+ const Vector<int> *arr = &PackedArrayRef<int>::get_array(_data.packed_array);
int idx = r_iter;
#ifdef DEBUG_ENABLED
if (idx < 0 || idx >= arr->size()) {
@@ -3400,7 +3813,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
return arr->get(idx);
} break;
case PACKED_REAL_ARRAY: {
- const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem);
+ const Vector<real_t> *arr = &PackedArrayRef<real_t>::get_array(_data.packed_array);
int idx = r_iter;
#ifdef DEBUG_ENABLED
if (idx < 0 || idx >= arr->size()) {
@@ -3411,7 +3824,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
return arr->get(idx);
} break;
case PACKED_STRING_ARRAY: {
- const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem);
+ const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
int idx = r_iter;
#ifdef DEBUG_ENABLED
if (idx < 0 || idx >= arr->size()) {
@@ -3423,7 +3836,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
} break;
case PACKED_VECTOR2_ARRAY: {
- const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem);
+ const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
int idx = r_iter;
#ifdef DEBUG_ENABLED
if (idx < 0 || idx >= arr->size()) {
@@ -3435,7 +3848,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
} break;
case PACKED_VECTOR3_ARRAY: {
- const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem);
+ const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
int idx = r_iter;
#ifdef DEBUG_ENABLED
if (idx < 0 || idx >= arr->size()) {
@@ -3447,7 +3860,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
} break;
case PACKED_COLOR_ARRAY: {
- const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem);
+ const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
int idx = r_iter;
#ifdef DEBUG_ENABLED
if (idx < 0 || idx >= arr->size()) {
@@ -3520,16 +3933,50 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst)
r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) + *reinterpret_cast<const Vector2 *>(b._data._mem) * c;
}
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 * c + 0.5), int32_t(vay + vby * c + 0.5));
+ }
+ 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 * c, ra->size + rb->size * c);
}
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 * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
+ }
+ return;
case VECTOR3: {
r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) + *reinterpret_cast<const Vector3 *>(b._data._mem) * c;
}
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 * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
+ }
+ return;
case AABB: {
const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
@@ -3646,14 +4093,51 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Vector2 *>(b._data._mem), c);
}
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 * c + 0.5), int32_t(vay + vby * c + 0.5));
+ }
+ return;
+
case RECT2: {
r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.linear_interpolate(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.linear_interpolate(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c));
}
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 * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
+ }
+ return;
+
case VECTOR3: {
r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Vector3 *>(b._data._mem), c);
}
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 * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
+ }
+ return;
+
case TRANSFORM2D: {
r_dst = a._data._transform2d->interpolate_with(*b._data._transform2d, c);
}
@@ -3682,6 +4166,10 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
r_dst = reinterpret_cast<const Color *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Color *>(b._data._mem), c);
}
return;
+ case STRING_NAME: {
+ r_dst = a;
+ }
+ return;
case NODE_PATH: {
r_dst = a;
}
@@ -3706,8 +4194,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case PACKED_INT_ARRAY: {
- const Vector<int> *arr_a = reinterpret_cast<const Vector<int> *>(a._data._mem);
- const Vector<int> *arr_b = reinterpret_cast<const Vector<int> *>(b._data._mem);
+ const Vector<int> *arr_a = &PackedArrayRef<int>::get_array(a._data.packed_array);
+ const Vector<int> *arr_b = &PackedArrayRef<int>::get_array(b._data.packed_array);
int sz = arr_a->size();
if (sz == 0 || arr_b->size() != sz) {
@@ -3732,8 +4220,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case PACKED_REAL_ARRAY: {
- const Vector<real_t> *arr_a = reinterpret_cast<const Vector<real_t> *>(a._data._mem);
- const Vector<real_t> *arr_b = reinterpret_cast<const Vector<real_t> *>(b._data._mem);
+ const Vector<real_t> *arr_a = &PackedArrayRef<real_t>::get_array(a._data.packed_array);
+ const Vector<real_t> *arr_b = &PackedArrayRef<real_t>::get_array(b._data.packed_array);
int sz = arr_a->size();
if (sz == 0 || arr_b->size() != sz) {
@@ -3762,8 +4250,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case PACKED_VECTOR2_ARRAY: {
- const Vector<Vector2> *arr_a = reinterpret_cast<const Vector<Vector2> *>(a._data._mem);
- const Vector<Vector2> *arr_b = reinterpret_cast<const Vector<Vector2> *>(b._data._mem);
+ const Vector<Vector2> *arr_a = &PackedArrayRef<Vector2>::get_array(a._data.packed_array);
+ const Vector<Vector2> *arr_b = &PackedArrayRef<Vector2>::get_array(b._data.packed_array);
int sz = arr_a->size();
if (sz == 0 || arr_b->size() != sz) {
@@ -3787,8 +4275,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
return;
case PACKED_VECTOR3_ARRAY: {
- const Vector<Vector3> *arr_a = reinterpret_cast<const Vector<Vector3> *>(a._data._mem);
- const Vector<Vector3> *arr_b = reinterpret_cast<const Vector<Vector3> *>(b._data._mem);
+ const Vector<Vector3> *arr_a = &PackedArrayRef<Vector3>::get_array(a._data.packed_array);
+ const Vector<Vector3> *arr_b = &PackedArrayRef<Vector3>::get_array(b._data.packed_array);
int sz = arr_a->size();
if (sz == 0 || arr_b->size() != sz) {
@@ -3811,8 +4299,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case PACKED_COLOR_ARRAY: {
- const Vector<Color> *arr_a = reinterpret_cast<const Vector<Color> *>(a._data._mem);
- const Vector<Color> *arr_b = reinterpret_cast<const Vector<Color> *>(b._data._mem);
+ const Vector<Color> *arr_a = &PackedArrayRef<Color>::get_array(a._data.packed_array);
+ const Vector<Color> *arr_b = &PackedArrayRef<Color>::get_array(b._data.packed_array);
int sz = arr_a->size();
if (sz == 0 || arr_b->size() != sz) {
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index f036e00ed5..56d33c10f4 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -81,6 +81,7 @@ const char *VariantParser::tk_name[TK_MAX] = {
"')'",
"identifier",
"string",
+ "string_name",
"number",
"color",
"':'",
@@ -93,6 +94,8 @@ const char *VariantParser::tk_name[TK_MAX] = {
Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, String &r_err_str) {
+ bool string_name = false;
+
while (true) {
CharType cchar;
@@ -204,6 +207,17 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
r_token.type = TK_COLOR;
return OK;
};
+ case '@': {
+ cchar = p_stream->get_char();
+ if (cchar != '"') {
+ r_err_str = "Expected '\"' after '@'";
+ r_token.type = TK_ERROR;
+ return ERR_PARSE_ERROR;
+ }
+
+ string_name = true;
+ [[fallthrough]];
+ }
case '"': {
String str;
@@ -285,8 +299,14 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
if (p_stream->is_utf8()) {
str.parse_utf8(str.ascii(true).get_data());
}
- r_token.type = TK_STRING;
- r_token.value = str;
+ 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;
+ }
return OK;
} break;
@@ -525,6 +545,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Vector2(args[0], args[1]);
return OK;
+ } else if (id == "Vector2i") {
+
+ Vector<int32_t> args;
+ Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
+ if (err)
+ return err;
+
+ if (args.size() != 2) {
+ r_err_str = "Expected 2 arguments for constructor";
+ }
+
+ value = Vector2i(args[0], args[1]);
+ return OK;
} else if (id == "Rect2") {
Vector<float> args;
@@ -538,6 +571,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Rect2(args[0], args[1], args[2], args[3]);
return OK;
+ } else if (id == "Rect2i") {
+
+ Vector<int32_t> args;
+ Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
+ if (err)
+ return err;
+
+ if (args.size() != 4) {
+ r_err_str = "Expected 4 arguments for constructor";
+ }
+
+ value = Rect2i(args[0], args[1], args[2], args[3]);
+ return OK;
} else if (id == "Vector3") {
Vector<float> args;
@@ -551,6 +597,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Vector3(args[0], args[1], args[2]);
return OK;
+ } else if (id == "Vector3i") {
+
+ Vector<int32_t> args;
+ Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
+ if (err)
+ return err;
+
+ if (args.size() != 3) {
+ r_err_str = "Expected 3 arguments for constructor";
+ }
+
+ value = Vector3i(args[0], args[1], args[2]);
+ return OK;
} else if (id == "Transform2D" || id == "Matrix32") { //compatibility
Vector<float> args;
@@ -1051,6 +1110,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = token.value;
return OK;
+ } else if (token.type == TK_STRING_NAME) {
+
+ value = token.value;
+ return OK;
} else if (token.type == TK_COLOR) {
value = token.value;
@@ -1411,17 +1474,33 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
Vector2 v = p_variant;
p_store_string_func(p_store_string_ud, "Vector2( " + rtosfix(v.x) + ", " + rtosfix(v.y) + " )");
} break;
+ case Variant::VECTOR2I: {
+
+ Vector2i v = p_variant;
+ p_store_string_func(p_store_string_ud, "Vector2i( " + itos(v.x) + ", " + itos(v.y) + " )");
+ } break;
case Variant::RECT2: {
Rect2 aabb = p_variant;
p_store_string_func(p_store_string_ud, "Rect2( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + " )");
} break;
+ case Variant::RECT2I: {
+
+ Rect2i aabb = p_variant;
+ p_store_string_func(p_store_string_ud, "Rect2i( " + itos(aabb.position.x) + ", " + itos(aabb.position.y) + ", " + itos(aabb.size.x) + ", " + itos(aabb.size.y) + " )");
+
+ } break;
case Variant::VECTOR3: {
Vector3 v = p_variant;
p_store_string_func(p_store_string_ud, "Vector3( " + rtosfix(v.x) + ", " + rtosfix(v.y) + ", " + rtosfix(v.z) + " )");
} break;
+ case Variant::VECTOR3I: {
+
+ Vector3i v = p_variant;
+ p_store_string_func(p_store_string_ud, "Vector3i( " + itos(v.x) + ", " + itos(v.y) + ", " + itos(v.z) + " )");
+ } break;
case Variant::PLANE: {
Plane p = p_variant;
@@ -1498,6 +1577,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, "Color( " + rtosfix(c.r) + ", " + rtosfix(c.g) + ", " + rtosfix(c.b) + ", " + rtosfix(c.a) + " )");
} break;
+ case Variant::STRING_NAME: {
+
+ String str = p_variant;
+
+ str = "@\"" + str.c_escape() + "\"";
+ p_store_string_func(p_store_string_ud, str);
+
+ } break;
case Variant::NODE_PATH: {
String str = p_variant;
diff --git a/core/variant_parser.h b/core/variant_parser.h
index 89db3ada0d..ad0a4d6682 100644
--- a/core/variant_parser.h
+++ b/core/variant_parser.h
@@ -92,6 +92,7 @@ public:
TK_PARENTHESIS_CLOSE,
TK_IDENTIFIER,
TK_STRING,
+ TK_STRING_NAME,
TK_NUMBER,
TK_COLOR,
TK_COLON,