From 05de7ce6caf441f8b64dd60d1837835f10d06520 Mon Sep 17 00:00:00 2001 From: reduz Date: Fri, 6 Nov 2020 22:29:22 -0300 Subject: [PATCH] Refactored variant setters/getters -Discern between named, indexed and keyed -Get direct access to functions for typed GDScript and GDNative bindings -Small changes to some classes in order to work with the new setget binder --- core/color.h | 14 + core/math/aabb.h | 8 + core/math/expression.cpp | 2 +- core/math/quat.h | 16 +- core/math/rect2.h | 17 + core/object.cpp | 48 +- core/packed_data_container.cpp | 3 + core/register_core_types.cpp | 4 + core/variant.h | 62 +- core/variant_op.cpp | 13 +- core/variant_setget.cpp | 3349 +++++++---------- editor/animation_track_editor.cpp | 3 +- modules/gdscript/gdscript_analyzer.cpp | 2 +- modules/gdscript/gdscript_function.cpp | 6 +- .../visual_script_expression.cpp | 2 +- .../visual_script_func_nodes.cpp | 18 +- 16 files changed, 1571 insertions(+), 1996 deletions(-) diff --git a/core/color.h b/core/color.h index 4fde353aed5f..eb9c5bfd15a2 100644 --- a/core/color.h +++ b/core/color.h @@ -193,6 +193,20 @@ struct Color { _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys operator String() const; + //for binder + _FORCE_INLINE_ void set_r8(int32_t r8) { r = (CLAMP(r8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_r8() const { return CLAMP(uint32_t(r * 255.0), 0, 255); } + _FORCE_INLINE_ void set_g8(int32_t g8) { g = (CLAMP(g8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_g8() const { return CLAMP(uint32_t(g * 255.0), 0, 255); } + _FORCE_INLINE_ void set_b8(int32_t b8) { b = (CLAMP(b8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_b8() const { return CLAMP(uint32_t(b * 255.0), 0, 255); } + _FORCE_INLINE_ void set_a8(int32_t a8) { a = (CLAMP(a8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_a8() const { return CLAMP(uint32_t(a * 255.0), 0, 255); } + + _FORCE_INLINE_ void set_h(float h) { set_hsv(h, get_s(), get_v()); } + _FORCE_INLINE_ void set_s(float s) { set_hsv(get_h(), s, get_v()); } + _FORCE_INLINE_ void set_v(float v) { set_hsv(get_h(), get_s(), v); } + _FORCE_INLINE_ Color() {} /** diff --git a/core/math/aabb.h b/core/math/aabb.h index 8c08754e1c52..45dcbc7f7f4a 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -107,6 +107,14 @@ public: Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const; Variant intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const; + _FORCE_INLINE_ void set_end(const Vector3 &p_end) { + size = p_end - position; + } + + _FORCE_INLINE_ Vector3 get_end() const { + return position + size; + } + operator String() const; _FORCE_INLINE_ AABB() {} diff --git a/core/math/expression.cpp b/core/math/expression.cpp index de7d2d2e2c29..0e72b153e405 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1980,7 +1980,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } bool valid; - r_ret = base.get_named(index->name, &valid); + r_ret = base.get_named(index->name, valid); if (!valid) { r_error_str = vformat(RTR("Invalid named index '%s' for base type %s"), String(index->name), Variant::get_type_name(base.get_type())); return true; diff --git a/core/math/quat.h b/core/math/quat.h index 617bffd908e3..1ab64a2655da 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -40,8 +40,22 @@ class Quat { public: - real_t x = 0, y = 0, z = 0, w = 1; + union { + struct { + real_t x; + real_t y; + real_t z; + real_t w; + }; + real_t components[4] = { 0, 0, 0, 1.0 }; + }; + _FORCE_INLINE_ real_t &operator[](int idx) { + return components[idx]; + } + _FORCE_INLINE_ const real_t &operator[](int idx) const { + return components[idx]; + } _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Quat &p_quat) const; real_t length() const; diff --git a/core/math/rect2.h b/core/math/rect2.h index 5a746aa732cd..b1fe865ba508 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -306,6 +306,15 @@ struct Rect2 { return false; } } + + _FORCE_INLINE_ void set_end(const Vector2 &p_end) { + size = p_end - position; + } + + _FORCE_INLINE_ Vector2 get_end() const { + return position + size; + } + operator String() const { return String(position) + ", " + String(size); } Rect2() {} @@ -475,6 +484,14 @@ struct Rect2i { return Rect2i(Point2i(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); } + _FORCE_INLINE_ void set_end(const Vector2i &p_end) { + size = p_end - position; + } + + _FORCE_INLINE_ Vector2i get_end() const { + return position + size; + } + operator String() const { return String(position) + ", " + String(size); } operator Rect2() const { return Rect2(position, size); } diff --git a/core/object.cpp b/core/object.cpp index 0d9e5c511606..3a52df9c609f 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -421,17 +421,6 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid return; } - { - bool valid; - setvar(p_name, p_value, &valid); - if (valid) { - if (r_valid) { - *r_valid = true; - } - return; - } - } - #ifdef TOOLS_ENABLED if (script_instance) { bool valid; @@ -496,18 +485,6 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { return ret; } - //if nothing else, use getvar - { - bool valid; - ret = getvar(p_name, &valid); - if (valid) { - if (r_valid) { - *r_valid = true; - } - return ret; - } - } - #ifdef TOOLS_ENABLED if (script_instance) { bool valid; @@ -555,9 +532,12 @@ void Object::set_indexed(const Vector &p_names, const Variant &p_val } for (int i = 1; i < p_names.size() - 1; i++) { - value_stack.push_back(value_stack.back()->get().get_named(p_names[i], r_valid)); + value_stack.push_back(value_stack.back()->get().get_named(p_names[i], valid)); + if (r_valid) { + *r_valid = valid; + } - if (!*r_valid) { + if (!valid) { value_stack.clear(); return; } @@ -566,10 +546,13 @@ void Object::set_indexed(const Vector &p_names, const Variant &p_val value_stack.push_back(p_value); // p_names[p_names.size() - 1] for (int i = p_names.size() - 1; i > 0; i--) { - value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), r_valid); + value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), valid); value_stack.pop_back(); - if (!*r_valid) { + if (r_valid) { + *r_valid = valid; + } + if (!valid) { value_stack.clear(); return; } @@ -592,7 +575,7 @@ Variant Object::get_indexed(const Vector &p_names, bool *r_valid) co Variant current_value = get(p_names[0], &valid); for (int i = 1; i < p_names.size(); i++) { - current_value = current_value.get_named(p_names[i], &valid); + current_value = current_value.get_named(p_names[i], valid); if (!valid) { break; @@ -698,6 +681,10 @@ Variant Object::getvar(const Variant &p_key, bool *r_valid) const { if (r_valid) { *r_valid = false; } + + if (p_key.get_type() == Variant::STRING_NAME || p_key.get_type() == Variant::STRING) { + return get(p_key, r_valid); + } return Variant(); } @@ -705,6 +692,9 @@ void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) if (r_valid) { *r_valid = false; } + if (p_key.get_type() == Variant::STRING_NAME || p_key.get_type() == Variant::STRING) { + return set(p_key, p_value, r_valid); + } } Variant Object::callv(const StringName &p_method, const Array &p_args) { @@ -1711,7 +1701,7 @@ Variant::Type Object::get_static_property_type_indexed(const Vector return Variant::NIL; } - check = check.get_named(p_path[i], &valid); + check = check.get_named(p_path[i], valid); if (!valid) { if (r_valid) { diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp index e335ec0daae2..f70482288d68 100644 --- a/core/packed_data_container.cpp +++ b/core/packed_data_container.cpp @@ -39,6 +39,9 @@ Variant PackedDataContainer::getvar(const Variant &p_key, bool *r_valid) const { if (r_valid) { *r_valid = !err; } + if (err) { + return Object::getvar(p_key, r_valid); + } return ret; } diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 2a77f51a51e8..54d3ec300f6a 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -101,6 +101,8 @@ extern void register_variant_methods(); extern void unregister_variant_methods(); extern void register_variant_operators(); extern void unregister_variant_operators(); +extern void register_variant_setters_getters(); +extern void unregister_variant_setters_getters(); void register_core_types() { //consistency check @@ -115,6 +117,7 @@ void register_core_types() { register_global_constants(); register_variant_methods(); register_variant_operators(); + register_variant_setters_getters(); CoreStringNames::create(); @@ -322,6 +325,7 @@ void unregister_core_types() { ClassDB::cleanup_defaults(); ObjectDB::cleanup(); + unregister_variant_setters_getters(); unregister_variant_operators(); unregister_variant_methods(); unregister_global_constants(); diff --git a/core/variant.h b/core/variant.h index d2e3528c2d8c..3b6205a0937f 100644 --- a/core/variant.h +++ b/core/variant.h @@ -477,8 +477,66 @@ public: static Vector get_method_argument_names(Variant::Type p_type, const StringName &p_method); static bool is_method_const(Variant::Type p_type, const StringName &p_method); - void set_named(const StringName &p_index, const Variant &p_value, bool *r_valid = nullptr); - Variant get_named(const StringName &p_index, bool *r_valid = nullptr) const; + void set_named(const StringName &p_member, const Variant &p_value, bool &r_valid); + Variant get_named(const StringName &p_member, bool &r_valid) const; + + typedef void (*ValidatedSetter)(Variant *base, const Variant *value); + typedef void (*ValidatedGetter)(const Variant *base, Variant *value); + + static bool has_member(Variant::Type p_type, const StringName &p_member); + static Variant::Type get_member_type(Variant::Type p_type, const StringName &p_member); + static void get_member_list(Type p_type, List *r_members); + + static ValidatedSetter get_member_validated_setter(Variant::Type p_type, const StringName &p_member); + static ValidatedGetter get_member_validated_getter(Variant::Type p_type, const StringName &p_member); + + typedef void (*PTRSetter)(void *base, const void *value); + typedef void (*PTRGetter)(const void *base, void *value); + + static PTRSetter get_member_ptr_setter(Variant::Type p_type, const StringName &p_member); + static PTRGetter get_member_ptr_getter(Variant::Type p_type, const StringName &p_member); + + static bool has_indexing(Variant::Type p_type); + static Variant::Type get_indexed_element_type(Variant::Type p_type); + + typedef void (*ValidatedIndexedSetter)(Variant *base, int64_t index, const Variant *value, bool &oob); + typedef void (*ValidatedIndexedGetter)(const Variant *base, int64_t index, Variant *value, bool &oob); + + static ValidatedIndexedSetter get_member_validated_indexed_setter(Variant::Type p_type); + static ValidatedIndexedGetter get_member_validated_indexed_getter(Variant::Type p_type); + + typedef void (*PTRIndexedSetter)(void *base, int64_t index, const void *value); + typedef void (*PTRIndexedGetter)(const void *base, int64_t index, void *value); + + static PTRIndexedSetter get_member_ptr_indexed_setter(Variant::Type p_type); + static PTRIndexedGetter get_member_ptr_indexed_getter(Variant::Type p_type); + + void set_indexed(int64_t p_index, const Variant &p_value, bool &r_valid, bool &r_oob); + Variant get_indexed(int64_t p_index, bool &r_valid, bool &r_oob) const; + + uint64_t get_indexed_size() const; + + static bool is_keyed(Variant::Type p_type); + + typedef void (*ValidatedKeyedSetter)(Variant *base, const Variant *key, const Variant *value, bool &valid); + typedef void (*ValidatedKeyedGetter)(const Variant *base, const Variant *key, Variant *value, bool &valid); + typedef bool (*ValidatedKeyedChecker)(const Variant *base, const Variant *key, bool &valid); + + static ValidatedKeyedSetter get_member_validated_keyed_setter(Variant::Type p_type); + static ValidatedKeyedGetter get_member_validated_keyed_getter(Variant::Type p_type); + static ValidatedKeyedChecker get_member_validated_keyed_checker(Variant::Type p_type); + + typedef void (*PTRKeyedSetter)(void *base, const void *key, const void *value); + typedef void (*PTRKeyedGetter)(const void *base, const void *key, void *value); + typedef bool (*PTRKeyedChecker)(const void *base, const void *key); + + static PTRKeyedSetter get_member_ptr_keyed_setter(Variant::Type p_type); + static PTRKeyedGetter get_member_ptr_keyed_getter(Variant::Type p_type); + static PTRKeyedChecker get_member_ptr_keyed_checker(Variant::Type p_type); + + void set_keyed(const Variant &p_key, const Variant &p_value, bool &r_valid); + Variant get_keyed(const Variant &p_key, bool &r_valid) const; + bool has_key(const Variant &p_key, bool &r_valid) const; void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr); Variant get(const Variant &p_index, bool *r_valid = nullptr) const; diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 5e851323c4bd..82722ea08879 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1481,7 +1481,6 @@ void register_op(Variant::Operator p_op, Variant::Type p_type_a, Variant::Type p } void register_variant_operators() { - printf("size of OT %i\n", (int)sizeof(operator_evaluator_table)); zeromem(operator_return_type_table, sizeof(operator_return_type_table)); zeromem(operator_evaluator_table, sizeof(operator_evaluator_table)); zeromem(validated_operator_evaluator_table, sizeof(validated_operator_evaluator_table)); @@ -2122,3 +2121,15 @@ Variant::operator bool() const { bool Variant::booleanize() const { return !is_zero(); } + +bool Variant::in(const Variant &p_index, bool *r_valid) const { + bool valid; + Variant ret; + evaluate(OP_IN, p_index, *this, ret, valid); + if (r_valid) { + *r_valid = valid; + return false; + } + ERR_FAIL_COND_V(ret.type != BOOL, false); + return *VariantGetInternalPtr::get_ptr(&ret); +} diff --git a/core/variant_setget.cpp b/core/variant_setget.cpp index 4e69f71c44e9..7e7f6c998ffd 100644 --- a/core/variant_setget.cpp +++ b/core/variant_setget.cpp @@ -33,1994 +33,1439 @@ #include "core/class_db.h" #include "core/core_string_names.h" #include "core/debugger/engine_debugger.h" +#include "core/local_vector.h" +#include "core/variant_internal.h" -void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) { - bool valid = false; - switch (type) { - case VECTOR2: { - if (p_value.type == Variant::INT) { - Vector2 *v = reinterpret_cast(_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::FLOAT) { - Vector2 *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } - } +/**** NAMED SETTERS AND GETTERS ****/ - } break; - case VECTOR2I: { - if (p_value.type == Variant::INT) { - Vector2i *v = reinterpret_cast(_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::FLOAT) { - Vector2i *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } - } +#define SETGET_STRUCT(m_base_type, m_member_type, m_member) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + *member = VariantGetInternalPtr::get_ptr(base)->m_member; \ + } \ + static void validated_get(const Variant *base, Variant *member) { \ + *VariantGetInternalPtr::get_ptr(member) = VariantGetInternalPtr::get_ptr(base)->m_member; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg::encode(PtrToArg::convert(base).m_member, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo::VARIANT_TYPE) { \ + VariantGetInternalPtr::get_ptr(base)->m_member = *VariantGetInternalPtr::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr::get_ptr(base)->m_member = *VariantGetInternalPtr::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg::convert(base); \ + b.m_member = PtrToArg::convert(member); \ + PtrToArg::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo::VARIANT_TYPE; } \ + }; - } break; - case RECT2: { - if (p_value.type == Variant::VECTOR2) { - Rect2 *v = reinterpret_cast(_data._mem); - //scalar name - if (p_index == CoreStringNames::singleton->position) { - v->position = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->size) { - v->size = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->end) { - v->size = *reinterpret_cast(p_value._data._mem) - v->position; - valid = true; - } - } - } break; - case RECT2I: { - if (p_value.type == Variant::VECTOR2I) { - Rect2i *v = reinterpret_cast(_data._mem); - //scalar name - if (p_index == CoreStringNames::singleton->position) { - v->position = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->size) { - v->size = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->end) { - v->size = *reinterpret_cast(p_value._data._mem) - v->position; - valid = true; - } - } - } break; - case TRANSFORM2D: { - if (p_value.type == Variant::VECTOR2) { - Transform2D *v = _data._transform2d; - if (p_index == CoreStringNames::singleton->x) { - v->elements[0] = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->elements[1] = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->origin) { - v->elements[2] = *reinterpret_cast(p_value._data._mem); - valid = true; - } - } +#define SETGET_NUMBER_STRUCT(m_base_type, m_member_type, m_member) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + *member = VariantGetInternalPtr::get_ptr(base)->m_member; \ + } \ + static void validated_get(const Variant *base, Variant *member) { \ + *VariantGetInternalPtr::get_ptr(member) = VariantGetInternalPtr::get_ptr(base)->m_member; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg::encode(PtrToArg::convert(base).m_member, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == Variant::FLOAT) { \ + VariantGetInternalPtr::get_ptr(base)->m_member = *VariantGetInternalPtr::get_ptr(value); \ + valid = true; \ + } else if (value->get_type() == Variant::INT) { \ + VariantGetInternalPtr::get_ptr(base)->m_member = *VariantGetInternalPtr::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr::get_ptr(base)->m_member = *VariantGetInternalPtr::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg::convert(base); \ + b.m_member = PtrToArg::convert(member); \ + PtrToArg::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo::VARIANT_TYPE; } \ + }; - } break; - case VECTOR3: { - if (p_value.type == Variant::INT) { - Vector3 *v = reinterpret_cast(_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::FLOAT) { - Vector3 *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._float; - valid = true; - } - } +#define SETGET_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + *member = VariantGetInternalPtr::get_ptr(base)->m_custom; \ + } \ + static void validated_get(const Variant *base, Variant *member) { \ + *VariantGetInternalPtr::get_ptr(member) = VariantGetInternalPtr::get_ptr(base)->m_custom; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg::encode(PtrToArg::convert(base).m_custom, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo::VARIANT_TYPE) { \ + VariantGetInternalPtr::get_ptr(base)->m_custom = *VariantGetInternalPtr::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr::get_ptr(base)->m_custom = *VariantGetInternalPtr::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg::convert(base); \ + b.m_custom = PtrToArg::convert(member); \ + PtrToArg::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo::VARIANT_TYPE; } \ + }; - } break; - case VECTOR3I: { - if (p_value.type == Variant::INT) { - Vector3i *v = reinterpret_cast(_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::FLOAT) { - Vector3i *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._float; - valid = true; - } - } +#define SETGET_NUMBER_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + *member = VariantGetInternalPtr::get_ptr(base)->m_custom; \ + } \ + static void validated_get(const Variant *base, Variant *member) { \ + *VariantGetInternalPtr::get_ptr(member) = VariantGetInternalPtr::get_ptr(base)->m_custom; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg::encode(PtrToArg::convert(base).m_custom, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == Variant::FLOAT) { \ + VariantGetInternalPtr::get_ptr(base)->m_custom = *VariantGetInternalPtr::get_ptr(value); \ + valid = true; \ + } else if (value->get_type() == Variant::INT) { \ + VariantGetInternalPtr::get_ptr(base)->m_custom = *VariantGetInternalPtr::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr::get_ptr(base)->m_custom = *VariantGetInternalPtr::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg::convert(base); \ + b.m_custom = PtrToArg::convert(member); \ + PtrToArg::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo::VARIANT_TYPE; } \ + }; - } break; - case PLANE: { - if (p_value.type == Variant::INT) { - Plane *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->normal.x = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->normal.y = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->normal.z = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->d) { - v->d = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Plane *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->normal.x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->normal.y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->normal.z = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->d) { - v->d = p_value._data._float; - valid = true; - } +#define SETGET_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + *member = VariantGetInternalPtr::get_ptr(base)->m_getter(); \ + } \ + static void validated_get(const Variant *base, Variant *member) { \ + *VariantGetInternalPtr::get_ptr(member) = VariantGetInternalPtr::get_ptr(base)->m_getter(); \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg::encode(PtrToArg::convert(base).m_getter(), member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo::VARIANT_TYPE) { \ + VariantGetInternalPtr::get_ptr(base)->m_setter(*VariantGetInternalPtr::get_ptr(value)); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr::get_ptr(base)->m_setter(*VariantGetInternalPtr::get_ptr(value)); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg::convert(base); \ + b.m_setter(PtrToArg::convert(member)); \ + PtrToArg::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo::VARIANT_TYPE; } \ + }; - } else if (p_value.type == Variant::VECTOR3) { - Plane *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->normal) { - v->normal = *reinterpret_cast(p_value._data._mem); - valid = true; - } - } +#define SETGET_NUMBER_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + *member = VariantGetInternalPtr::get_ptr(base)->m_getter(); \ + } \ + static void validated_get(const Variant *base, Variant *member) { \ + *VariantGetInternalPtr::get_ptr(member) = VariantGetInternalPtr::get_ptr(base)->m_getter(); \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg::encode(PtrToArg::convert(base).m_getter(), member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == Variant::FLOAT) { \ + VariantGetInternalPtr::get_ptr(base)->m_setter(*VariantGetInternalPtr::get_ptr(value)); \ + valid = true; \ + } else if (value->get_type() == Variant::INT) { \ + VariantGetInternalPtr::get_ptr(base)->m_setter(*VariantGetInternalPtr::get_ptr(value)); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr::get_ptr(base)->m_setter(*VariantGetInternalPtr::get_ptr(value)); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg::convert(base); \ + b.m_setter(PtrToArg::convert(member)); \ + PtrToArg::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo::VARIANT_TYPE; } \ + }; - } break; - case QUAT: { - if (p_value.type == Variant::INT) { - Quat *v = reinterpret_cast(_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_index == CoreStringNames::singleton->w) { - v->w = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Quat *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->w) { - v->w = p_value._data._float; - valid = true; - } - } +#define SETGET_STRUCT_FUNC_INDEX(m_base_type, m_member_type, m_member, m_setter, m_getter, m_index) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + *member = VariantGetInternalPtr::get_ptr(base)->m_getter(m_index); \ + } \ + static void validated_get(const Variant *base, Variant *member) { \ + *VariantGetInternalPtr::get_ptr(member) = VariantGetInternalPtr::get_ptr(base)->m_getter(m_index); \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg::encode(PtrToArg::convert(base).m_getter(m_index), member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo::VARIANT_TYPE) { \ + VariantGetInternalPtr::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr::get_ptr(value)); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr::get_ptr(value)); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg::convert(base); \ + b.m_setter(m_index, PtrToArg::convert(member)); \ + PtrToArg::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo::VARIANT_TYPE; } \ + }; - } break; - case AABB: { - if (p_value.type == Variant::VECTOR3) { - ::AABB *v = _data._aabb; - //scalar name - if (p_index == CoreStringNames::singleton->position) { - v->position = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->size) { - v->size = *reinterpret_cast(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->end) { - v->size = *reinterpret_cast(p_value._data._mem) - v->position; - valid = true; - } - } - } break; - case BASIS: { - if (p_value.type == Variant::VECTOR3) { - Basis *v = _data._basis; - //scalar name - if (p_index == CoreStringNames::singleton->x) { - v->set_axis(0, *reinterpret_cast(p_value._data._mem)); - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->set_axis(1, *reinterpret_cast(p_value._data._mem)); - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->set_axis(2, *reinterpret_cast(p_value._data._mem)); - valid = true; - } - } - } break; - case TRANSFORM: { - if (p_value.type == Variant::BASIS && p_index == CoreStringNames::singleton->basis) { - _data._transform->basis = *p_value._data._basis; - valid = true; - } else if (p_value.type == Variant::VECTOR3 && p_index == CoreStringNames::singleton->origin) { - _data._transform->origin = *reinterpret_cast(p_value._data._mem); - valid = true; - } +SETGET_NUMBER_STRUCT(Vector2, double, x) +SETGET_NUMBER_STRUCT(Vector2, double, y) - } break; - case COLOR: { - if (p_value.type == Variant::INT) { - Color *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->r) { - v->r = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->g) { - v->g = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->b) { - v->b = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->a) { - v->a = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->r8) { - v->r = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->g8) { - v->g = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->b8) { - v->b = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->a8) { - v->a = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->h) { - v->set_hsv(p_value._data._int, v->get_s(), v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->s) { - v->set_hsv(v->get_h(), p_value._data._int, v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->v) { - v->set_hsv(v->get_h(), v->get_v(), p_value._data._int, v->a); - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Color *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->r) { - v->r = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->g) { - v->g = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->b) { - v->b = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->a) { - v->a = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->r8) { - v->r = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->g8) { - v->g = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->b8) { - v->b = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->a8) { - v->a = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->h) { - v->set_hsv(p_value._data._float, v->get_s(), v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->s) { - v->set_hsv(v->get_h(), p_value._data._float, v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->v) { - v->set_hsv(v->get_h(), v->get_s(), p_value._data._float, v->a); - valid = true; - } - } - } break; - case OBJECT: { -#ifdef DEBUG_ENABLED - if (!_get_obj().obj) { - break; - } else if (EngineDebugger::is_active() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - break; - } +SETGET_NUMBER_STRUCT(Vector2i, int64_t, x) +SETGET_NUMBER_STRUCT(Vector2i, int64_t, y) -#endif - _get_obj().obj->set(p_index, p_value, &valid); +SETGET_NUMBER_STRUCT(Vector3, double, x) +SETGET_NUMBER_STRUCT(Vector3, double, y) +SETGET_NUMBER_STRUCT(Vector3, double, z) - } break; - default: { - set(p_index.operator String(), p_value, &valid); - } break; - } +SETGET_NUMBER_STRUCT(Vector3i, int64_t, x) +SETGET_NUMBER_STRUCT(Vector3i, int64_t, y) +SETGET_NUMBER_STRUCT(Vector3i, int64_t, z) - if (r_valid) { - *r_valid = valid; +SETGET_STRUCT(Rect2, Vector2, position) +SETGET_STRUCT(Rect2, Vector2, size) +SETGET_STRUCT_FUNC(Rect2, Vector2, end, set_end, get_end) + +SETGET_STRUCT(Rect2i, Vector2i, position) +SETGET_STRUCT(Rect2i, Vector2i, size) +SETGET_STRUCT_FUNC(Rect2i, Vector2i, end, set_end, get_end) + +SETGET_STRUCT(AABB, Vector3, position) +SETGET_STRUCT(AABB, Vector3, size) +SETGET_STRUCT_FUNC(AABB, Vector3, end, set_end, get_end) + +SETGET_STRUCT_CUSTOM(Transform2D, Vector2, x, elements[0]) +SETGET_STRUCT_CUSTOM(Transform2D, Vector2, y, elements[1]) +SETGET_STRUCT_CUSTOM(Transform2D, Vector2, origin, elements[2]) + +SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, x, normal.x) +SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, y, normal.y) +SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, z, normal.z) +SETGET_STRUCT(Plane, Vector3, normal) +SETGET_NUMBER_STRUCT(Plane, double, d) + +SETGET_NUMBER_STRUCT(Quat, double, x) +SETGET_NUMBER_STRUCT(Quat, double, y) +SETGET_NUMBER_STRUCT(Quat, double, z) +SETGET_NUMBER_STRUCT(Quat, double, w) + +SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_axis, get_axis, 0) +SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_axis, get_axis, 1) +SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_axis, get_axis, 2) + +SETGET_STRUCT(Transform, Basis, basis) +SETGET_STRUCT(Transform, Vector3, origin) + +SETGET_NUMBER_STRUCT(Color, double, r) +SETGET_NUMBER_STRUCT(Color, double, g) +SETGET_NUMBER_STRUCT(Color, double, b) +SETGET_NUMBER_STRUCT(Color, double, a) + +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, r8, set_r8, get_r8) +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, g8, set_g8, get_g8) +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, b8, set_b8, get_b8) +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, a8, set_a8, get_a8) + +SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h) +SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s) +SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v) + +struct VariantSetterGetterInfo { + void (*setter)(Variant *base, const Variant *value, bool &valid); + void (*getter)(const Variant *base, Variant *value); + Variant::ValidatedSetter validated_setter; + Variant::ValidatedGetter validated_getter; + Variant::PTRSetter ptr_setter; + Variant::PTRGetter ptr_getter; + Variant::Type member_type; +}; + +static LocalVector variant_setters_getters[Variant::VARIANT_MAX]; +static LocalVector variant_setters_getters_names[Variant::VARIANT_MAX]; //one next to another to make it cache friendly + +template +static void register_member(Variant::Type p_type, const StringName &p_member) { + VariantSetterGetterInfo sgi; + sgi.setter = T::set; + sgi.validated_setter = T::validated_set; + sgi.ptr_setter = T::ptr_set; + + sgi.getter = T::get; + sgi.validated_getter = T::validated_get; + sgi.ptr_getter = T::ptr_get; + + sgi.member_type = T::get_type(); + + variant_setters_getters[p_type].push_back(sgi); + variant_setters_getters_names[p_type].push_back(p_member); +} + +void register_named_setters_getters() { +#define REGISTER_MEMBER(m_base_type, m_member) register_member(GetTypeInfo::VARIANT_TYPE, #m_member) + + REGISTER_MEMBER(Vector2, x); + REGISTER_MEMBER(Vector2, y); + + REGISTER_MEMBER(Vector2i, x); + REGISTER_MEMBER(Vector2i, y); + + REGISTER_MEMBER(Vector3, x); + REGISTER_MEMBER(Vector3, y); + REGISTER_MEMBER(Vector3, z); + + REGISTER_MEMBER(Vector3i, x); + REGISTER_MEMBER(Vector3i, y); + REGISTER_MEMBER(Vector3i, z); + + REGISTER_MEMBER(Rect2, position); + REGISTER_MEMBER(Rect2, size); + REGISTER_MEMBER(Rect2, end); + + REGISTER_MEMBER(Rect2i, position); + REGISTER_MEMBER(Rect2i, size); + REGISTER_MEMBER(Rect2i, end); + + REGISTER_MEMBER(AABB, position); + REGISTER_MEMBER(AABB, size); + REGISTER_MEMBER(AABB, end); + + REGISTER_MEMBER(Transform2D, x); + REGISTER_MEMBER(Transform2D, y); + REGISTER_MEMBER(Transform2D, origin); + + REGISTER_MEMBER(Plane, x); + REGISTER_MEMBER(Plane, y); + REGISTER_MEMBER(Plane, z); + REGISTER_MEMBER(Plane, d); + REGISTER_MEMBER(Plane, normal); + + REGISTER_MEMBER(Quat, x); + REGISTER_MEMBER(Quat, y); + REGISTER_MEMBER(Quat, z); + REGISTER_MEMBER(Quat, w); + + REGISTER_MEMBER(Basis, x); + REGISTER_MEMBER(Basis, y); + REGISTER_MEMBER(Basis, z); + + REGISTER_MEMBER(Transform, basis); + REGISTER_MEMBER(Transform, origin); + + REGISTER_MEMBER(Color, r); + REGISTER_MEMBER(Color, g); + REGISTER_MEMBER(Color, b); + REGISTER_MEMBER(Color, a); + + REGISTER_MEMBER(Color, r8); + REGISTER_MEMBER(Color, g8); + REGISTER_MEMBER(Color, b8); + REGISTER_MEMBER(Color, a8); + + REGISTER_MEMBER(Color, h); + REGISTER_MEMBER(Color, s); + REGISTER_MEMBER(Color, v); +} + +void unregister_named_setters_getters() { + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + variant_setters_getters[i].clear(); + variant_setters_getters_names[i].clear(); } } -Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { - if (r_valid) { - *r_valid = true; - } +bool Variant::has_member(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); - switch (type) { - case VECTOR2: { - const Vector2 *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->y; - } - - } break; - case VECTOR2I: { - const Vector2i *v = reinterpret_cast(_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(_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 RECT2I: { - const Rect2i *v = reinterpret_cast(_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; - if (p_index == CoreStringNames::singleton->x) { - return v->elements[0]; - } else if (p_index == CoreStringNames::singleton->y) { - return v->elements[1]; - } else if (p_index == CoreStringNames::singleton->origin) { - return v->elements[2]; - } - - } break; - case VECTOR3: { - const Vector3 *v = reinterpret_cast(_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 VECTOR3I: { - const Vector3i *v = reinterpret_cast(_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(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->normal.x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->normal.y; - } else if (p_index == CoreStringNames::singleton->z) { - return v->normal.z; - } else if (p_index == CoreStringNames::singleton->d) { - return v->d; - } else if (p_index == CoreStringNames::singleton->normal) { - return v->normal; - } - - } break; - case QUAT: { - const Quat *v = reinterpret_cast(_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; - } else if (p_index == CoreStringNames::singleton->w) { - return v->w; - } - - } break; - case AABB: { - const ::AABB *v = _data._aabb; - //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 BASIS: { - const Basis *v = _data._basis; - //scalar name - if (p_index == CoreStringNames::singleton->x) { - return v->get_axis(0); - } else if (p_index == CoreStringNames::singleton->y) { - return v->get_axis(1); - } else if (p_index == CoreStringNames::singleton->z) { - return v->get_axis(2); - } - - } break; - case TRANSFORM: { - if (p_index == CoreStringNames::singleton->basis) { - return _data._transform->basis; - } else if (p_index == CoreStringNames::singleton->origin) { - return _data._transform->origin; - } - - } break; - case COLOR: { - const Color *v = reinterpret_cast(_data._mem); - if (p_index == CoreStringNames::singleton->r) { - return v->r; - } else if (p_index == CoreStringNames::singleton->g) { - return v->g; - } else if (p_index == CoreStringNames::singleton->b) { - return v->b; - } else if (p_index == CoreStringNames::singleton->a) { - return v->a; - } else if (p_index == CoreStringNames::singleton->r8) { - return int(Math::round(v->r * 255.0)); - } else if (p_index == CoreStringNames::singleton->g8) { - return int(Math::round(v->g * 255.0)); - } else if (p_index == CoreStringNames::singleton->b8) { - return int(Math::round(v->b * 255.0)); - } else if (p_index == CoreStringNames::singleton->a8) { - return int(Math::round(v->a * 255.0)); - } else if (p_index == CoreStringNames::singleton->h) { - return v->get_h(); - } else if (p_index == CoreStringNames::singleton->s) { - return v->get_s(); - } else if (p_index == CoreStringNames::singleton->v) { - return v->get_v(); - } - } break; - case OBJECT: { -#ifdef DEBUG_ENABLED - if (!_get_obj().obj) { - if (r_valid) { - *r_valid = false; - } - return "Instance base is null."; - } else { - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - if (r_valid) { - *r_valid = false; - } - return "Attempted use of stray pointer object."; - } - } - -#endif - - return _get_obj().obj->get(p_index, r_valid); - - } break; - default: { - return get(p_index.operator String(), r_valid); + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return true; } } - - if (r_valid) { - *r_valid = false; - } - return Variant(); -} - -#define DEFAULT_OP_ARRAY_CMD(m_name, m_type, skip_test, cmd) \ - case m_name: { \ - skip_test; \ - \ - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ - int index = p_index; \ - m_type *arr = reinterpret_cast(_data._mem); \ - \ - if (index < 0) \ - index += arr->size(); \ - if (index >= 0 && index < arr->size()) { \ - valid = true; \ - cmd; \ - } \ - } \ - } break; - -#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::FLOAT) { \ - int index = p_index; \ - Vector *arr = PackedArrayRef::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, m_type) \ - case m_name: { \ - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ - int index = p_index; \ - const Vector *arr = &PackedArrayRef::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) { - static bool _dummy = false; - - bool &valid = r_valid ? *r_valid : _dummy; - valid = false; - - switch (type) { - case NIL: { - return; - } break; - case BOOL: { - return; - } break; - case INT: { - return; - } break; - case FLOAT: { - return; - } break; - case STRING: { - if (p_index.type != Variant::INT && p_index.type != Variant::FLOAT) { - return; - } - - int idx = p_index; - String *str = reinterpret_cast(_data._mem); - int len = str->length(); - if (idx < 0) { - idx += len; - } - if (idx < 0 || idx >= len) { - return; - } - - String chr; - if (p_value.type == Variant::INT || p_value.type == Variant::FLOAT) { - chr = String::chr(p_value); - } else if (p_value.type == Variant::STRING) { - chr = p_value; - } else { - return; - } - - *str = str->substr(0, idx) + chr + str->substr(idx + 1, len); - valid = true; - return; - - } break; - case VECTOR2: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - Vector2 *v = reinterpret_cast(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - Vector2 *v = reinterpret_cast(_data._mem); - if (*str == "x") { - valid = true; - v->x = p_value; - return; - } else if (*str == "y") { - valid = true; - v->y = p_value; - return; - } - } - - } break; - case VECTOR2I: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - Vector2i *v = reinterpret_cast(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - Vector2i *v = reinterpret_cast(_data._mem); - if (*str == "x") { - valid = true; - v->x = p_value; - return; - } else if (*str == "y") { - valid = true; - v->y = p_value; - return; - } - } - - } break; - case RECT2: { - if (p_value.type != Variant::VECTOR2) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - Rect2 *v = reinterpret_cast(_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 = Vector2(p_value) - v->position; - return; - } - } - } break; - case RECT2I: { - if (p_value.type != Variant::VECTOR2I) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - Rect2i *v = reinterpret_cast(_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) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - Transform2D *v = _data._transform2d; - - valid = true; - v->elements[index] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING && p_value.get_type() == Variant::VECTOR2) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - Transform2D *v = _data._transform2d; - if (*str == "x") { - valid = true; - v->elements[0] = p_value; - return; - } else if (*str == "y") { - valid = true; - v->elements[1] = p_value; - return; - } else if (*str == "origin") { - valid = true; - v->elements[2] = p_value; - return; - } - } - - } break; - case VECTOR3: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - Vector3 *v = reinterpret_cast(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - Vector3 *v = reinterpret_cast(_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 VECTOR3I: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - Vector3i *v = reinterpret_cast(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - Vector3i *v = reinterpret_cast(_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) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - Plane *v = reinterpret_cast(_data._mem); - if (*str == "x") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - valid = true; - v->normal.x = p_value; - return; - } else if (*str == "y") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - valid = true; - v->normal.y = p_value; - return; - } else if (*str == "z") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - valid = true; - v->normal.z = p_value; - return; - } else if (*str == "normal") { - if (p_value.type != Variant::VECTOR3) { - return; - } - - valid = true; - v->normal = p_value; - return; - } else if (*str == "d") { - valid = true; - v->d = p_value; - return; - } - } - - } break; - case QUAT: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast(p_index._data._mem); - Quat *v = reinterpret_cast(_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; - } else if (*str == "w") { - valid = true; - v->w = p_value; - return; - } - } - - } break; - case AABB: { - if (p_value.type != Variant::VECTOR3) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - ::AABB *v = _data._aabb; - 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 = Vector3(p_value) - v->position; - return; - } - } - } break; - case BASIS: { - if (p_value.type != Variant::VECTOR3) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - Basis *v = _data._basis; - - valid = true; - v->set_axis(index, p_value); - return; - } - } else if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast(p_index._data._mem); - Basis *v = _data._basis; - - if (*str == "x") { - valid = true; - v->set_axis(0, p_value); - return; - } else if (*str == "y") { - valid = true; - v->set_axis(1, p_value); - return; - } else if (*str == "z") { - valid = true; - v->set_axis(2, p_value); - return; - } - } - - } break; - case TRANSFORM: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - if (p_value.type != Variant::VECTOR3) { - return; - } - - int index = p_index; - - if (index < 0) { - index += 4; - } - if (index >= 0 && index < 4) { - Transform *v = _data._transform; - valid = true; - if (index == 3) { - v->origin = p_value; - } else { - v->basis.set_axis(index, p_value); - } - return; - } - } else if (p_index.get_type() == Variant::STRING) { - Transform *v = _data._transform; - const String *str = reinterpret_cast(p_index._data._mem); - - if (*str == "basis") { - if (p_value.type != Variant::BASIS) { - return; - } - valid = true; - v->basis = p_value; - return; - } - if (*str == "origin") { - if (p_value.type != Variant::VECTOR3) { - return; - } - valid = true; - v->origin = p_value; - return; - } - } - - } break; - case COLOR: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast(p_index._data._mem); - Color *v = reinterpret_cast(_data._mem); - if (*str == "r") { - valid = true; - v->r = p_value; - return; - } else if (*str == "g") { - valid = true; - v->g = p_value; - return; - } else if (*str == "b") { - valid = true; - v->b = p_value; - return; - } else if (*str == "a") { - valid = true; - v->a = p_value; - return; - } else if (*str == "h") { - valid = true; - v->set_hsv(p_value, v->get_s(), v->get_v(), v->a); - return; - } else if (*str == "s") { - valid = true; - v->set_hsv(v->get_h(), p_value, v->get_v(), v->a); - return; - } else if (*str == "v") { - valid = true; - v->set_hsv(v->get_h(), v->get_s(), p_value, v->a); - return; - } else if (*str == "r8") { - valid = true; - v->r = float(p_value) / 255.0; - return; - } else if (*str == "g8") { - valid = true; - v->g = float(p_value) / 255.0; - return; - } else if (*str == "b8") { - valid = true; - v->b = float(p_value) / 255.0; - return; - } else if (*str == "a8") { - valid = true; - v->a = float(p_value) / 255.0; - return; - } - } else if (p_index.get_type() == Variant::INT) { - int idx = p_index; - if (idx < 0) { - idx += 4; - } - if (idx >= 0 && idx < 4) { - Color *v = reinterpret_cast(_data._mem); - (*v)[idx] = p_value; - valid = true; - } - } - - } break; - case STRING_NAME: { - } break; - case NODE_PATH: { - } break; - case _RID: { - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - //only if debugging! - - if (obj) { -#ifdef DEBUG_ENABLED - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - WARN_PRINT("Attempted use of previously freed pointer object."); - valid = false; - return; - } -#endif - - if (p_index.get_type() != Variant::STRING_NAME && p_index.get_type() != Variant::STRING) { - obj->setvar(p_index, p_value, r_valid); - return; - } - - obj->set(p_index, p_value, r_valid); - return; - } - } break; - case DICTIONARY: { - Dictionary *dic = reinterpret_cast(_data._mem); - dic->operator[](p_index) = p_value; - valid = true; //always valid, i guess? should this really be ok? - return; - } break; - DEFAULT_OP_ARRAY_CMD(ARRAY, Array, ;, (*arr)[index] = p_value; return ) - DEFAULT_OP_DVECTOR_SET(PACKED_BYTE_ARRAY, uint8_t, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_INT32_ARRAY, int32_t, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_INT64_ARRAY, int64_t, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_FLOAT32_ARRAY, float, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_FLOAT64_ARRAY, double, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_STRING_ARRAY, String, p_value.type != Variant::STRING) - DEFAULT_OP_DVECTOR_SET(PACKED_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) - DEFAULT_OP_DVECTOR_SET(PACKED_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3) - DEFAULT_OP_DVECTOR_SET(PACKED_COLOR_ARRAY, Color, p_value.type != Variant::COLOR) - default: - return; - } -} - -Variant Variant::get(const Variant &p_index, bool *r_valid) const { - static bool _dummy = false; - - bool &valid = r_valid ? *r_valid : _dummy; - - valid = false; - - switch (type) { - case NIL: { - return Variant(); - } break; - case BOOL: { - return Variant(); - } break; - case INT: { - return Variant(); - } break; - case FLOAT: { - return Variant(); - } break; - case STRING: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //string index - - int idx = p_index; - const String *str = reinterpret_cast(_data._mem); - if (idx < 0) { - idx += str->length(); - } - if (idx >= 0 && idx < str->length()) { - valid = true; - return str->substr(idx, 1); - } - } - - } break; - case VECTOR2: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - const Vector2 *v = reinterpret_cast(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - const Vector2 *v = reinterpret_cast(_data._mem); - if (*str == "x") { - valid = true; - return v->x; - } else if (*str == "y") { - valid = true; - return v->y; - } - } - - } break; - case VECTOR2I: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - const Vector2i *v = reinterpret_cast(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - const Vector2i *v = reinterpret_cast(_data._mem); - if (*str == "x") { - valid = true; - return v->x; - } else if (*str == "y") { - valid = true; - return v->y; - } - } - - } break; - case RECT2: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - const Rect2 *v = reinterpret_cast(_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 RECT2I: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - const Rect2i *v = reinterpret_cast(_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::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - const Vector3 *v = reinterpret_cast(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - const Vector3 *v = reinterpret_cast(_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 VECTOR3I: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - const Vector3i *v = reinterpret_cast(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - const Vector3i *v = reinterpret_cast(_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::FLOAT) { - int index = p_index; - - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - const Transform2D *v = _data._transform2d; - - valid = true; - return v->elements[index]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - const Transform2D *v = _data._transform2d; - if (*str == "x") { - valid = true; - return v->elements[0]; - } else if (*str == "y") { - valid = true; - return v->elements[1]; - } else if (*str == "origin") { - valid = true; - return v->elements[2]; - } - } - - } break; - case PLANE: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast(p_index._data._mem); - const Plane *v = reinterpret_cast(_data._mem); - if (*str == "x") { - valid = true; - return v->normal.x; - } else if (*str == "y") { - valid = true; - return v->normal.y; - } else if (*str == "z") { - valid = true; - return v->normal.z; - } else if (*str == "normal") { - valid = true; - return v->normal; - } else if (*str == "d") { - valid = true; - return v->d; - } - } - - } break; - case QUAT: { - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast(p_index._data._mem); - const Quat *v = reinterpret_cast(_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; - } else if (*str == "w") { - valid = true; - return v->w; - } - } - - } break; - case AABB: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast(p_index._data._mem); - const ::AABB *v = _data._aabb; - 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 BASIS: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - const Basis *v = _data._basis; - - valid = true; - return v->get_axis(index); - } - } else if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast(p_index._data._mem); - const Basis *v = _data._basis; - - if (*str == "x") { - valid = true; - return v->get_axis(0); - } else if (*str == "y") { - valid = true; - return v->get_axis(1); - } else if (*str == "z") { - valid = true; - return v->get_axis(2); - } - } - - } break; - case TRANSFORM: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) { - index += 4; - } - if (index >= 0 && index < 4) { - const Transform *v = _data._transform; - valid = true; - return index == 3 ? v->origin : v->basis.get_axis(index); - } - } else if (p_index.get_type() == Variant::STRING) { - const Transform *v = _data._transform; - const String *str = reinterpret_cast(p_index._data._mem); - - if (*str == "basis") { - valid = true; - return v->basis; - } - if (*str == "origin") { - valid = true; - return v->origin; - } - } - - } break; - case COLOR: { - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast(p_index._data._mem); - const Color *v = reinterpret_cast(_data._mem); - if (*str == "r") { - valid = true; - return v->r; - } else if (*str == "g") { - valid = true; - return v->g; - } else if (*str == "b") { - valid = true; - return v->b; - } else if (*str == "a") { - valid = true; - return v->a; - } else if (*str == "h") { - valid = true; - return v->get_h(); - } else if (*str == "s") { - valid = true; - return v->get_s(); - } else if (*str == "v") { - valid = true; - return v->get_v(); - } else if (*str == "r8") { - valid = true; - return (int)Math::round(v->r * 255.0); - } else if (*str == "g8") { - valid = true; - return (int)Math::round(v->g * 255.0); - } else if (*str == "b8") { - valid = true; - return (int)Math::round(v->b * 255.0); - } else if (*str == "a8") { - valid = true; - return (int)Math::round(v->a * 255.0); - } - } else if (p_index.get_type() == Variant::INT) { - int idx = p_index; - if (idx < 0) { - idx += 4; - } - if (idx >= 0 && idx < 4) { - const Color *v = reinterpret_cast(_data._mem); - valid = true; - return (*v)[idx]; - } - } - - } break; - case STRING_NAME: { - } break; - case NODE_PATH: { - } break; - case _RID: { - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - if (obj) { -#ifdef DEBUG_ENABLED - - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - valid = false; - return "Attempted get on previously freed instance."; - } -#endif - - if (p_index.get_type() != Variant::STRING) { - return obj->getvar(p_index, r_valid); - } - - return obj->get(p_index, r_valid); - } - - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast(_data._mem); - const Variant *res = dic->getptr(p_index); - if (res) { - valid = true; - return *res; - } - } break; - DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, ;, return (*arr)[index]) - DEFAULT_OP_DVECTOR_GET(PACKED_BYTE_ARRAY, uint8_t) - DEFAULT_OP_DVECTOR_GET(PACKED_INT32_ARRAY, int32_t) - DEFAULT_OP_DVECTOR_GET(PACKED_INT64_ARRAY, int64_t) - DEFAULT_OP_DVECTOR_GET(PACKED_FLOAT32_ARRAY, float) - DEFAULT_OP_DVECTOR_GET(PACKED_FLOAT64_ARRAY, double) - DEFAULT_OP_DVECTOR_GET(PACKED_STRING_ARRAY, String) - DEFAULT_OP_DVECTOR_GET(PACKED_VECTOR2_ARRAY, Vector2) - DEFAULT_OP_DVECTOR_GET(PACKED_VECTOR3_ARRAY, Vector3) - DEFAULT_OP_DVECTOR_GET(PACKED_COLOR_ARRAY, Color) - default: - return Variant(); - } - - return Variant(); -} - -bool Variant::in(const Variant &p_index, bool *r_valid) const { - if (r_valid) { - *r_valid = true; - } - - switch (type) { - case STRING: { - if (p_index.get_type() == Variant::STRING) { - //string index - String idx = p_index; - const String *str = reinterpret_cast(_data._mem); - - return str->find(idx) != -1; - } - - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - if (obj) { - bool valid = false; -#ifdef DEBUG_ENABLED - - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - if (r_valid) { - *r_valid = false; - } - return true; // Attempted get on stray pointer. - } - -#endif - - if (p_index.get_type() != Variant::STRING) { - obj->getvar(p_index, &valid); - } else { - obj->get(p_index, &valid); - } - - return valid; - } else { - if (r_valid) { - *r_valid = false; - } - } - return false; - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast(_data._mem); - return dic->has(p_index); - - } break; - case ARRAY: { - const Array *arr = reinterpret_cast(_data._mem); - int l = arr->size(); - if (l) { - for (int i = 0; i < l; i++) { - if (evaluate(OP_EQUAL, (*arr)[i], p_index)) { - return true; - } - } - } - - return false; - - } break; - case PACKED_BYTE_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - int l = arr->size(); - if (l) { - const uint8_t *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_INT32_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int32_t index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - int32_t l = arr->size(); - if (l) { - const int32_t *r = arr->ptr(); - for (int32_t i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - } break; - case PACKED_INT64_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int64_t index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - int64_t l = arr->size(); - if (l) { - const int64_t *r = arr->ptr(); - for (int64_t i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - } break; - case PACKED_FLOAT32_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - real_t index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - int l = arr->size(); - if (l) { - const float *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_FLOAT64_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - real_t index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - int l = arr->size(); - if (l) { - const double *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_STRING_ARRAY: { - if (p_index.get_type() == Variant::STRING) { - String index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const String *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; //25 - case PACKED_VECTOR2_ARRAY: { - if (p_index.get_type() == Variant::VECTOR2) { - Vector2 index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const Vector2 *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_VECTOR3_ARRAY: { - if (p_index.get_type() == Variant::VECTOR3) { - Vector3 index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const Vector3 *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_COLOR_ARRAY: { - if (p_index.get_type() == Variant::COLOR) { - Color index = p_index; - const Vector *arr = &PackedArrayRef::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const Color *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - } break; - default: { - } - } - - if (r_valid) { - *r_valid = false; - } return false; } -void Variant::get_property_list(List *p_list) const { - switch (type) { - case VECTOR2: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); +Variant::Type Variant::get_member_type(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX); - } break; - case VECTOR2I: { - p_list->push_back(PropertyInfo(Variant::INT, "x")); - p_list->push_back(PropertyInfo(Variant::INT, "y")); + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].member_type; + } + } - } break; - case RECT2: { - p_list->push_back(PropertyInfo(Variant::VECTOR2, "position")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "size")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "end")); + return Variant::NIL; +} - } 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")); +void Variant::get_member_list(Variant::Type p_type, List *r_members) { + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + r_members->push_back(variant_setters_getters_names[p_type][i]); + } +} - } break; - case VECTOR3: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); +Variant::ValidatedSetter Variant::get_member_validated_setter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); - } 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")); + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].validated_setter; + } + } - } break; - case TRANSFORM2D: { - p_list->push_back(PropertyInfo(Variant::VECTOR2, "x")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "y")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "origin")); + return nullptr; +} +Variant::ValidatedGetter Variant::get_member_validated_getter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); - } break; - case PLANE: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "normal")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "d")); + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].validated_getter; + } + } - } break; - case QUAT: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "w")); + return nullptr; +} - } break; - case AABB: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "position")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "size")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "end")); - } break; - case BASIS: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "x")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "y")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "z")); +Variant::PTRSetter Variant::get_member_ptr_setter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); - } break; - case TRANSFORM: { - p_list->push_back(PropertyInfo(Variant::BASIS, "basis")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "origin")); + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].ptr_setter; + } + } - } break; - case COLOR: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "r")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "g")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "b")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "a")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "h")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "s")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "v")); - p_list->push_back(PropertyInfo(Variant::INT, "r8")); - p_list->push_back(PropertyInfo(Variant::INT, "g8")); - p_list->push_back(PropertyInfo(Variant::INT, "b8")); - p_list->push_back(PropertyInfo(Variant::INT, "a8")); + return nullptr; +} + +Variant::PTRGetter Variant::get_member_ptr_getter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].ptr_getter; + } + } + + return nullptr; +} + +void Variant::set_named(const StringName &p_member, const Variant &p_value, bool &r_valid) { + uint32_t s = variant_setters_getters[type].size(); + if (s) { + for (uint32_t i = 0; i < s; i++) { + if (variant_setters_getters_names[type][i] == p_member) { + variant_setters_getters[type][i].setter(this, &p_value, r_valid); + return; + } + } + r_valid = false; + + } else if (type == Variant::OBJECT) { + Object *obj = get_validated_object(); + if (!obj) { + r_valid = false; + } else { + obj->set(p_member, p_value, &r_valid); + return; + } + } else if (type == Variant::DICTIONARY) { + Variant *v = VariantGetInternalPtr::get_ptr(this)->getptr(p_member); + if (v) { + *v = p_value; + r_valid = true; + } else { + r_valid = false; + } + + } else { + r_valid = false; + } +} + +Variant Variant::get_named(const StringName &p_member, bool &r_valid) const { + Variant ret; + uint32_t s = variant_setters_getters[type].size(); + if (s) { + for (uint32_t i = 0; i < s; i++) { + if (variant_setters_getters_names[type][i] == p_member) { + variant_setters_getters[type][i].getter(this, &ret); + r_valid = true; + return ret; + } + } + + r_valid = false; + + } else if (type == Variant::OBJECT) { + Object *obj = get_validated_object(); + if (!obj) { + r_valid = false; + return "Instance base is null."; + } else { + return obj->get(p_member, &r_valid); + } + } else if (type == Variant::DICTIONARY) { + const Variant *v = VariantGetInternalPtr::get_ptr(this)->getptr(p_member); + if (v) { + r_valid = true; + + return *v; + } else { + r_valid = false; + } + + } else { + r_valid = false; + } + + return ret; +} + +/**** INDEXED SETTERS AND GETTERS ****/ - } break; - case STRING_NAME: { - } break; - case NODE_PATH: { - } break; - case _RID: { - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - if (obj) { #ifdef DEBUG_ENABLED - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - WARN_PRINT("Attempted get_property list on previously freed instance."); - return; - } +#define OOB_TEST(m_idx, m_v) \ + ERR_FAIL_INDEX(m_idx, m_v) + +#else + +#define OOB_TEST(m_idx, m_v) #endif - obj->get_property_list(p_list); - } +#ifdef DEBUG_ENABLED - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast(_data._mem); - List keys; - dic->get_key_list(&keys); - for (List::Element *E = keys.front(); E; E = E->next()) { - if (E->get().get_type() == Variant::STRING) { - p_list->push_back(PropertyInfo(Variant::STRING, E->get())); - } +#define NULL_TEST(m_key) \ + ERR_FAIL_COND(!m_key) + +#else + +#define NULL_TEST(m_key) + +#endif + +#define INDEXED_SETGET_STRUCT_TYPED(m_base_type, m_elem_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + *value = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void validated_get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + *VariantGetInternalPtr::get_ptr(value) = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + PtrToArg::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob) { \ + if (value->get_type() != GetTypeInfo::VARIANT_TYPE) { \ + oob = false; \ + valid = false; \ + return; \ + } \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base)).write[index] = *VariantGetInternalPtr::get_ptr(value); \ + oob = false; \ + valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base)).write[index] = *VariantGetInternalPtr::get_ptr(value); \ + oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + v.write[index] = PtrToArg::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr::get_ptr(base)->size(); } \ + }; + +#define INDEXED_SETGET_STRUCT_TYPED_NUMERIC(m_base_type, m_elem_type, m_assign_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + *value = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void validated_get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + *VariantGetInternalPtr::get_ptr(value) = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + PtrToArg::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + valid = false; \ + return; \ + } \ + m_assign_type num; \ + if (value->get_type() == Variant::INT) { \ + num = (m_assign_type)*VariantGetInternalPtr::get_ptr(value); \ + } else if (value->get_type() == Variant::FLOAT) { \ + num = (m_assign_type)*VariantGetInternalPtr::get_ptr(value); \ + } else { \ + oob = false; \ + valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base)).write[index] = num; \ + oob = false; \ + valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base)).write[index] = *VariantGetInternalPtr::get_ptr(value); \ + oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + v.write[index] = PtrToArg::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr::get_ptr(base)->size(); } \ + }; + +#define INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(m_base_type, m_elem_type, m_assign_type, m_max) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + *value = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void validated_get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + *VariantGetInternalPtr::get_ptr(value) = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast(base); \ + OOB_TEST(index, m_max); \ + PtrToArg::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + valid = false; \ + return; \ + } \ + m_assign_type num; \ + if (value->get_type() == Variant::INT) { \ + num = (m_assign_type)*VariantGetInternalPtr::get_ptr(value); \ + } else if (value->get_type() == Variant::FLOAT) { \ + num = (m_assign_type)*VariantGetInternalPtr::get_ptr(value); \ + } else { \ + oob = false; \ + valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base))[index] = num; \ + oob = false; \ + valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base))[index] = *VariantGetInternalPtr::get_ptr(value); \ + oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast(base); \ + OOB_TEST(index, m_max); \ + v[index] = PtrToArg::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return m_max; } \ + }; + +#define INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(m_base_type, m_elem_type, m_accessor, m_max) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + *value = (*VariantGetInternalPtr::get_ptr(base))m_accessor[index]; \ + oob = false; \ + } \ + static void validated_get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + *VariantGetInternalPtr::get_ptr(value) = (*VariantGetInternalPtr::get_ptr(base))m_accessor[index]; \ + oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast(base); \ + OOB_TEST(index, m_max); \ + PtrToArg::encode(v m_accessor[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob) { \ + if (value->get_type() != GetTypeInfo::VARIANT_TYPE) { \ + oob = false; \ + valid = false; \ + } \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base)) m_accessor[index] = *VariantGetInternalPtr::get_ptr(value); \ + oob = false; \ + valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base)) m_accessor[index] = *VariantGetInternalPtr::get_ptr(value); \ + oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast(base); \ + OOB_TEST(index, m_max); \ + v m_accessor[index] = PtrToArg::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return m_max; } \ + }; + +#define INDEXED_SETGET_STRUCT_BULTIN_FUNC(m_base_type, m_elem_type, m_set, m_get, m_max) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + *value = VariantGetInternalPtr::get_ptr(base)->m_get(index); \ + oob = false; \ + } \ + static void validated_get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + *VariantGetInternalPtr::get_ptr(value) = VariantGetInternalPtr::get_ptr(base)->m_get(index); \ + oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast(base); \ + OOB_TEST(index, m_max); \ + PtrToArg::encode(v.m_get(index), member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob) { \ + if (value->get_type() != GetTypeInfo::VARIANT_TYPE) { \ + oob = false; \ + valid = false; \ + } \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + valid = false; \ + return; \ + } \ + VariantGetInternalPtr::get_ptr(base)->m_set(index, *VariantGetInternalPtr::get_ptr(value)); \ + oob = false; \ + valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool &oob) { \ + if (index < 0 || index >= m_max) { \ + oob = true; \ + return; \ + } \ + VariantGetInternalPtr::get_ptr(base)->m_set(index, *VariantGetInternalPtr::get_ptr(value)); \ + oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast(base); \ + OOB_TEST(index, m_max); \ + v.m_set(index, PtrToArg::convert(member)); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return m_max; } \ + }; + +#define INDEXED_SETGET_STRUCT_VARIANT(m_base_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + *value = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void validated_get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + *value = (*VariantGetInternalPtr::get_ptr(base))[index]; \ + oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + PtrToArg::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base))[index] = *value; \ + oob = false; \ + valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool &oob) { \ + int64_t size = VariantGetInternalPtr::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr::get_ptr(base))[index] = *value; \ + oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + v[index] = PtrToArg::convert(member); \ + } \ + static Variant::Type get_index_type() { return Variant::NIL; } \ + static uint64_t get_indexed_size(const Variant *base) { return 0; } \ + }; + +#define INDEXED_SETGET_STRUCT_DICT(m_base_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + const Variant *ptr = VariantGetInternalPtr::get_ptr(base)->getptr(index); \ + if (!ptr) { \ + oob = true; \ + return; \ + } \ + *value = *ptr; \ + oob = false; \ + } \ + static void validated_get(const Variant *base, int64_t index, Variant *value, bool &oob) { \ + const Variant *ptr = VariantGetInternalPtr::get_ptr(base)->getptr(index); \ + if (!ptr) { \ + oob = true; \ + return; \ + } \ + *value = *ptr; \ + oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast(base); \ + const Variant *ptr = v.getptr(index); \ + NULL_TEST(ptr); \ + PtrToArg::encode(*ptr, member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob) { \ + (*VariantGetInternalPtr::get_ptr(base))[index] = *value; \ + oob = false; \ + valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool &oob) { \ + (*VariantGetInternalPtr::get_ptr(base))[index] = *value; \ + oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + m_base_type &v = *reinterpret_cast(base); \ + v[index] = PtrToArg::convert(member); \ + } \ + static Variant::Type get_index_type() { return Variant::NIL; } \ + static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr::get_ptr(base)->size(); } \ + }; + +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2, double, real_t, 2) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2i, int64_t, int32_t, 2) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3, double, real_t, 3) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3i, int64_t, int32_t, 3) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quat, double, real_t, 4) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Color, double, float, 4) + +INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .elements, 3) +INDEXED_SETGET_STRUCT_BULTIN_FUNC(Basis, Vector3, set_axis, get_axis, 3) + +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedByteArray, int64_t, uint8_t) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt32Array, int64_t, int32_t) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt64Array, int64_t, int64_t) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedFloat32Array, double, float) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedFloat64Array, double, double) +INDEXED_SETGET_STRUCT_TYPED(PackedVector2Array, Vector2) +INDEXED_SETGET_STRUCT_TYPED(PackedVector3Array, Vector3) +INDEXED_SETGET_STRUCT_TYPED(PackedStringArray, String) +INDEXED_SETGET_STRUCT_TYPED(PackedColorArray, Color) + +INDEXED_SETGET_STRUCT_VARIANT(Array) +INDEXED_SETGET_STRUCT_DICT(Dictionary) + +struct VariantIndexedSetterGetterInfo { + void (*setter)(Variant *base, int64_t index, const Variant *value, bool &valid, bool &oob); + void (*getter)(const Variant *base, int64_t index, Variant *value, bool &oob); + + Variant::ValidatedIndexedSetter validated_setter; + Variant::ValidatedIndexedGetter validated_getter; + + Variant::PTRIndexedSetter ptr_setter; + Variant::PTRIndexedGetter ptr_getter; + + uint64_t (*get_indexed_size)(const Variant *base); + + Variant::Type index_type; + + bool valid = false; +}; + +static VariantIndexedSetterGetterInfo variant_indexed_setters_getters[Variant::VARIANT_MAX]; + +template +static void register_indexed_member(Variant::Type p_type) { + VariantIndexedSetterGetterInfo &sgi = variant_indexed_setters_getters[p_type]; + + sgi.setter = T::set; + sgi.validated_setter = T::validated_set; + sgi.ptr_setter = T::ptr_set; + + sgi.getter = T::get; + sgi.validated_getter = T::validated_get; + sgi.ptr_getter = T::ptr_get; + + sgi.index_type = T::get_index_type(); + sgi.get_indexed_size = T::get_indexed_size; + + sgi.valid = true; +} + +void register_indexed_setters_getters() { +#define REGISTER_INDEXED_MEMBER(m_base_type) register_indexed_member(GetTypeInfo::VARIANT_TYPE) + + REGISTER_INDEXED_MEMBER(Vector2); + REGISTER_INDEXED_MEMBER(Vector2i); + REGISTER_INDEXED_MEMBER(Vector3); + REGISTER_INDEXED_MEMBER(Vector3i); + REGISTER_INDEXED_MEMBER(Quat); + REGISTER_INDEXED_MEMBER(Color); + REGISTER_INDEXED_MEMBER(Transform2D); + REGISTER_INDEXED_MEMBER(Basis); + + REGISTER_INDEXED_MEMBER(PackedByteArray); + REGISTER_INDEXED_MEMBER(PackedInt32Array); + REGISTER_INDEXED_MEMBER(PackedInt64Array); + REGISTER_INDEXED_MEMBER(PackedFloat64Array); + REGISTER_INDEXED_MEMBER(PackedVector2Array); + REGISTER_INDEXED_MEMBER(PackedVector3Array); + REGISTER_INDEXED_MEMBER(PackedStringArray); + REGISTER_INDEXED_MEMBER(PackedColorArray); + + REGISTER_INDEXED_MEMBER(Array); + REGISTER_INDEXED_MEMBER(Dictionary); +} + +static void unregister_indexed_setters_getters() { +} + +bool Variant::has_indexing(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + return variant_indexed_setters_getters[p_type].valid; +} + +Variant::Type Variant::get_indexed_element_type(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX); + return variant_indexed_setters_getters[p_type].index_type; +} + +Variant::ValidatedIndexedSetter Variant::get_member_validated_indexed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].validated_setter; +} +Variant::ValidatedIndexedGetter Variant::get_member_validated_indexed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].validated_getter; +} + +Variant::PTRIndexedSetter Variant::get_member_ptr_indexed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].ptr_setter; +} +Variant::PTRIndexedGetter Variant::get_member_ptr_indexed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].ptr_getter; +} + +void Variant::set_indexed(int64_t p_index, const Variant &p_value, bool &r_valid, bool &r_oob) { + if (likely(variant_indexed_setters_getters[type].valid)) { + variant_indexed_setters_getters[type].setter(this, p_index, &p_value, r_valid, r_oob); + } else { + r_valid = false; + r_oob = false; + } +} +Variant Variant::get_indexed(int64_t p_index, bool &r_valid, bool &r_oob) const { + if (likely(variant_indexed_setters_getters[type].valid)) { + Variant ret; + variant_indexed_setters_getters[type].getter(this, p_index, &ret, r_oob); + r_valid = !r_oob; + return ret; + } else { + r_valid = false; + r_oob = false; + return Variant(); + } +} + +uint64_t Variant::get_indexed_size() const { + if (likely(variant_indexed_setters_getters[type].valid && variant_indexed_setters_getters[type].get_indexed_size)) { + return variant_indexed_setters_getters[type].get_indexed_size(this); + } else { + return 0; + } +} + +struct VariantKeyedSetGetDictionary { + static void get(const Variant *base, const Variant *key, Variant *value, bool &r_valid) { + const Variant *ptr = VariantGetInternalPtr::get_ptr(base)->getptr(*key); + if (!ptr) { + r_valid = false; + return; + } + *value = *ptr; + r_valid = true; + } + static void ptr_get(const void *base, const void *key, void *value) { + /* avoid ptrconvert for performance*/ + const Dictionary &v = *reinterpret_cast(base); + const Variant *ptr = v.getptr(PtrToArg::convert(key)); + NULL_TEST(ptr); + PtrToArg::encode(*ptr, value); + } + static void set(Variant *base, const Variant *key, const Variant *value, bool &r_valid) { + (*VariantGetInternalPtr::get_ptr(base))[*key] = *value; + r_valid = true; + } + static void ptr_set(void *base, const void *key, const void *value) { + Dictionary &v = *reinterpret_cast(base); + v[PtrToArg::convert(key)] = PtrToArg::convert(value); + } + + static bool has(const Variant *base, const Variant *key, bool &r_valid) { + r_valid = true; + return VariantGetInternalPtr::get_ptr(base)->has(*key); + } + static bool ptr_has(const void *base, const void *key) { + /* avoid ptrconvert for performance*/ + const Dictionary &v = *reinterpret_cast(base); + return v.has(PtrToArg::convert(key)); + } +}; + +struct VariantKeyedSetGetObject { + static void get(const Variant *base, const Variant *key, Variant *value, bool &r_valid) { + Object *obj = base->get_validated_object(); + + if (!obj) { + r_valid = false; + *value = Variant(); + return; + } + *value = obj->getvar(*key, &r_valid); + } + static void ptr_get(const void *base, const void *key, void *value) { + const Object *obj = PtrToArg::convert(base); + NULL_TEST(obj); + Variant v = obj->getvar(PtrToArg::convert(key)); + PtrToArg::encode(v, value); + } + static void set(Variant *base, const Variant *key, const Variant *value, bool &r_valid) { + Object *obj = base->get_validated_object(); + + if (!obj) { + r_valid = false; + return; + } + obj->setvar(*key, *value, &r_valid); + } + static void ptr_set(void *base, const void *key, const void *value) { + Object *obj = PtrToArg::convert(base); + NULL_TEST(obj); + obj->setvar(PtrToArg::convert(key), PtrToArg::convert(value)); + } + + static bool has(const Variant *base, const Variant *key, bool &r_valid) { + Object *obj = base->get_validated_object(); + if (obj != nullptr) { + r_valid = false; + return false; + } + r_valid = true; + bool exists; + obj->getvar(*key, &exists); + return exists; + } + static bool ptr_has(const void *base, const void *key) { + const Object *obj = PtrToArg::convert(base); + ERR_FAIL_COND_V(!obj, false); + bool valid; + obj->getvar(PtrToArg::convert(key), &valid); + return valid; + } +}; + +/*typedef void (*ValidatedKeyedSetter)(Variant *base, const Variant *key, const Variant *value); +typedef void (*ValidatedKeyedGetter)(const Variant *base, const Variant *key, Variant *value, bool &valid); +typedef bool (*ValidatedKeyedChecker)(const Variant *base, const Variant *key); + +typedef void (*PTRKeyedSetter)(void *base, const void *key, const void *value); +typedef void (*PTRKeyedGetter)(const void *base, const void *key, void *value); +typedef bool (*PTRKeyedChecker)(const void *base, const void *key);*/ + +struct VariantKeyedSetterGetterInfo { + Variant::ValidatedKeyedSetter validated_setter; + Variant::ValidatedKeyedGetter validated_getter; + Variant::ValidatedKeyedChecker validated_checker; + + Variant::PTRKeyedSetter ptr_setter; + Variant::PTRKeyedGetter ptr_getter; + Variant::PTRKeyedChecker ptr_checker; + + bool valid = false; +}; + +static VariantKeyedSetterGetterInfo variant_keyed_setters_getters[Variant::VARIANT_MAX]; + +template +static void register_keyed_member(Variant::Type p_type) { + VariantKeyedSetterGetterInfo &sgi = variant_keyed_setters_getters[p_type]; + + sgi.validated_setter = T::set; + sgi.ptr_setter = T::ptr_set; + + sgi.validated_getter = T::get; + sgi.ptr_getter = T::ptr_get; + + sgi.validated_checker = T::has; + sgi.ptr_checker = T::ptr_has; + + sgi.valid = true; +} + +static void register_keyed_setters_getters() { + register_keyed_member(Variant::DICTIONARY); + register_keyed_member(Variant::OBJECT); +} +bool Variant::is_keyed(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, false); + return variant_keyed_setters_getters[p_type].valid; +} + +Variant::ValidatedKeyedSetter Variant::get_member_validated_keyed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].validated_setter; +} +Variant::ValidatedKeyedGetter Variant::get_member_validated_keyed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].validated_getter; +} +Variant::ValidatedKeyedChecker Variant::get_member_validated_keyed_checker(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].validated_checker; +} + +Variant::PTRKeyedSetter Variant::get_member_ptr_keyed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].ptr_setter; +} +Variant::PTRKeyedGetter Variant::get_member_ptr_keyed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].ptr_getter; +} +Variant::PTRKeyedChecker Variant::get_member_ptr_keyed_checker(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].ptr_checker; +} + +void Variant::set_keyed(const Variant &p_key, const Variant &p_value, bool &r_valid) { + if (likely(variant_keyed_setters_getters[type].valid)) { + variant_keyed_setters_getters[type].validated_setter(this, &p_key, &p_value, r_valid); + } else { + r_valid = false; + } +} +Variant Variant::get_keyed(const Variant &p_key, bool &r_valid) const { + if (likely(variant_keyed_setters_getters[type].valid)) { + Variant ret; + variant_keyed_setters_getters[type].validated_getter(this, &p_key, &ret, r_valid); + return ret; + } else { + r_valid = false; + return Variant(); + } +} +bool Variant::has_key(const Variant &p_key, bool &r_valid) const { + if (likely(variant_keyed_setters_getters[type].valid)) { + return variant_keyed_setters_getters[type].validated_checker(this, &p_key, r_valid); + } else { + r_valid = false; + return false; + } +} + +void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) { + if (type == DICTIONARY || type == OBJECT) { + bool valid; + set_keyed(p_index, p_value, valid); + if (r_valid) { + *r_valid = valid; + } + } else { + bool valid = false; + if (p_index.get_type() == STRING_NAME) { + set_named(*VariantGetInternalPtr::get_ptr(&p_index), p_value, valid); + } else if (p_index.get_type() == INT) { + bool obb; + set_indexed(*VariantGetInternalPtr::get_ptr(&p_index), p_value, valid, obb); + if (obb) { + valid = false; } - } break; - case ARRAY: - case PACKED_BYTE_ARRAY: - case PACKED_INT32_ARRAY: - case PACKED_INT64_ARRAY: - case PACKED_FLOAT32_ARRAY: - case PACKED_FLOAT64_ARRAY: - case PACKED_STRING_ARRAY: - case PACKED_VECTOR2_ARRAY: - case PACKED_VECTOR3_ARRAY: - case PACKED_COLOR_ARRAY: { - //nothing - } break; - default: { + } else if (p_index.get_type() == STRING) { // less efficient version of named + set_named(*VariantGetInternalPtr::get_ptr(&p_index), p_value, valid); + } else if (p_index.get_type() == FLOAT) { // less efficient version of indexed + bool obb; + set_indexed(*VariantGetInternalPtr::get_ptr(&p_index), p_value, valid, obb); + if (obb) { + valid = false; + } + } + if (r_valid) { + *r_valid = valid; + } + } +} + +Variant Variant::get(const Variant &p_index, bool *r_valid) const { + Variant ret; + if (type == DICTIONARY || type == OBJECT) { + bool valid; + ret = get_keyed(p_index, valid); + if (r_valid) { + *r_valid = valid; + } + } else { + bool valid = false; + if (p_index.get_type() == STRING_NAME) { + ret = get_named(*VariantGetInternalPtr::get_ptr(&p_index), valid); + } else if (p_index.get_type() == INT) { + bool obb; + ret = get_indexed(*VariantGetInternalPtr::get_ptr(&p_index), valid, obb); + if (obb) { + valid = false; + } + } else if (p_index.get_type() == STRING) { // less efficient version of named + ret = get_named(*VariantGetInternalPtr::get_ptr(&p_index), valid); + } else if (p_index.get_type() == FLOAT) { // less efficient version of indexed + bool obb; + ret = get_indexed(*VariantGetInternalPtr::get_ptr(&p_index), valid, obb); + if (obb) { + valid = false; + } + } + if (r_valid) { + *r_valid = valid; + } + } + + return ret; +} + +void Variant::get_property_list(List *p_list) const { + if (type == DICTIONARY) { + const Dictionary *dic = reinterpret_cast(_data._mem); + List keys; + dic->get_key_list(&keys); + for (List::Element *E = keys.front(); E; E = E->next()) { + if (E->get().get_type() == Variant::STRING) { + p_list->push_back(PropertyInfo(Variant::STRING, E->get())); + } + } + } else if (type == OBJECT) { + Object *obj = get_validated_object(); + ERR_FAIL_COND(!obj); + obj->get_property_list(p_list); + + } else { + List members; + get_member_list(type, &members); + for (List::Element *E = members.front(); E; E = E->next()) { + PropertyInfo pi; + pi.name = E->get(); + pi.type = get_member_type(type, E->get()); + p_list->push_back(pi); } } } @@ -3130,3 +2575,13 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } } } + +void register_variant_setters_getters() { + register_named_setters_getters(); + register_indexed_setters_getters(); + register_keyed_setters_getters(); +} +void unregister_variant_setters_getters() { + unregister_named_setters_getters(); + unregister_indexed_setters_getters(); +} diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 52c984cbc0e7..5471a9907bce 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3751,7 +3751,8 @@ PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_b } for (int i = 0; i < leftover_path.size() - 1; i++) { - property_info_base = property_info_base.get_named(leftover_path[i]); + bool valid; + property_info_base = property_info_base.get_named(leftover_path[i], valid); } List pinfo; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index ab4edb04b905..e152bfb1eb95 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -2438,7 +2438,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri if (p_subscript->base->is_constant) { // Just try to get it. bool valid = false; - Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, &valid); + Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid); if (!valid) { push_error(vformat(R"(Cannot get member "%s" from "%s".)", p_subscript->attribute->name, p_subscript->base->reduced_value), p_subscript->index); } else { diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 1da0e7b4c69c..30d0049d47f6 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -620,7 +620,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a const StringName *index = &_global_names_ptr[indexname]; bool valid; - dst->set_named(*index, *value, &valid); + dst->set_named(*index, *value, valid); #ifdef DEBUG_ENABLED if (!valid) { @@ -647,10 +647,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a bool valid; #ifdef DEBUG_ENABLED //allow better error message in cases where src and dst are the same stack position - Variant ret = src->get_named(*index, &valid); + Variant ret = src->get_named(*index, valid); #else - *dst = src->get_named(*index, &valid); + *dst = src->get_named(*index, valid); #endif #ifdef DEBUG_ENABLED if (!valid) { diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index 60a439b291e3..3785e81b9f12 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -1341,7 +1341,7 @@ public: } bool valid; - r_ret = base.get_named(index->name, &valid); + r_ret = base.get_named(index->name, valid); if (!valid) { r_error_str = "Invalid index '" + String(index->name) + "' for base of type " + Variant::get_type_name(base.get_type()) + "."; return true; diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 68de6862724c..cfac234f12b9 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -1449,11 +1449,11 @@ public: _FORCE_INLINE_ void _process_get(Variant &source, const Variant &p_argument, bool &valid) { if (index != StringName() && assign_op == VisualScriptPropertySet::ASSIGN_OP_NONE) { - source.set_named(index, p_argument, &valid); + source.set_named(index, p_argument, valid); } else { Variant value; if (index != StringName()) { - value = source.get_named(index, &valid); + value = source.get_named(index, valid); } else { value = source; } @@ -1497,7 +1497,7 @@ public: } if (index != StringName()) { - source.set_named(index, value, &valid); + source.set_named(index, value, valid); } else { source = value; } @@ -1562,12 +1562,12 @@ public: bool valid; if (needs_get) { - Variant value = v.get_named(property, &valid); + Variant value = v.get_named(property, valid); _process_get(value, *p_inputs[1], valid); - v.set_named(property, value, &valid); + v.set_named(property, value, valid); } else { - v.set_named(property, *p_inputs[1], &valid); + v.set_named(property, *p_inputs[1], valid); } if (!valid) { @@ -2111,7 +2111,7 @@ public: *p_outputs[0] = object->get(property, &valid); if (index != StringName()) { - *p_outputs[0] = p_outputs[0]->get_named(index); + *p_outputs[0] = p_outputs[0]->get_named(index, valid); } if (!valid) { @@ -2140,7 +2140,7 @@ public: *p_outputs[0] = another->get(property, &valid); if (index != StringName()) { - *p_outputs[0] = p_outputs[0]->get_named(index); + *p_outputs[0] = p_outputs[0]->get_named(index, valid); } if (!valid) { @@ -2156,7 +2156,7 @@ public: *p_outputs[0] = v.get(property, &valid); if (index != StringName()) { - *p_outputs[0] = p_outputs[0]->get_named(index); + *p_outputs[0] = p_outputs[0]->get_named(index, valid); } if (!valid) {