diff options
Diffstat (limited to 'core')
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, |