Skip to content

Commit

Permalink
Changed STRUCT_INFO macro to avoid making a bunch of *Layout structs.
Browse files Browse the repository at this point in the history
  • Loading branch information
nlupugla committed Oct 7, 2023
1 parent ddcc90e commit d4cc397
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 87 deletions.
2 changes: 1 addition & 1 deletion core/object/class_db.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ class ClassDB {
::ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);

#define BIND_STRUCT(m_struct) \
::ClassDB::bind_struct(get_class_static(), m_struct::get_name(), m_struct::get_member_count(), m_struct::get_member);
::ClassDB::bind_struct(get_class_static(), m_struct::get_struct_name(), m_struct::get_struct_member_count(), m_struct::get_struct_member);

#ifdef DEBUG_METHODS_ENABLED

Expand Down
27 changes: 14 additions & 13 deletions core/object/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,20 @@ PropertyInfo PropertyInfo::from_dict(const Dictionary &p_dict) {
return pi;
}

PropertyInfo::operator Array() const {
Struct<PropertyInfoLayout> a;
a[SNAME("name")] = name;
a[SNAME("class_name")] = class_name;
a[SNAME("type")] = type;
a[SNAME("hint")] = hint;
a[SNAME("hint_string")] = hint_string;
a[SNAME("usage")] = usage;
PropertyInfo::operator Struct<PropertyInfo>() const {
Struct<PropertyInfo> a;

a.set_named(SNAME("name"), name);
a.set_named(SNAME("class_name"), class_name);
a.set_named(SNAME("type"), type);
a.set_named(SNAME("hint"), hint);
a.set_named(SNAME("hint_string"), hint_string);
a.set_named(SNAME("usage"), usage);
return a;
}

PropertyInfo PropertyInfo::from_struct(const Array &p_struct) {
Struct<PropertyInfoLayout> a = p_struct;
PropertyInfo PropertyInfo::from_struct(const Struct<PropertyInfo> &p_struct) {
Struct<PropertyInfo> a = p_struct;
PropertyInfo pi;
pi.name = a[SNAME("name")];
pi.class_name = a[SNAME("class_name")];
Expand Down Expand Up @@ -1016,11 +1017,11 @@ TypedArray<Dictionary> Object::_get_property_list_bind() const {
// return props;
//}

Struct<PropertyInfoLayout> Object::_get_property_struct(uint32_t p_index) const {
Struct<PropertyInfo> Object::_get_property_struct(uint32_t p_index) const {
List<PropertyInfo> lpi;
get_property_list(&lpi);
PropertyInfo pi = lpi[p_index];
return Struct<PropertyInfoLayout>(pi);
return Struct<PropertyInfo>(pi);
}

TypedArray<Dictionary> Object::_get_method_list_bind() const {
Expand Down Expand Up @@ -1708,7 +1709,7 @@ void Object::_bind_methods() {
BIND_ENUM_CONSTANT(CONNECT_ONE_SHOT);
BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);

BIND_STRUCT(PropertyInfoLayout);
BIND_STRUCT(PropertyInfo);
}

void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
Expand Down
70 changes: 33 additions & 37 deletions core/object/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,32 +166,28 @@ struct StructMember {
}
};

#define STRUCT_MEMBER(m_name, m_type, m_default) StructMember(SNAME(m_name), m_type, StringName(), nullptr, m_default)
#define STRUCT_CLASS_MEMBER(m_name, m_class_name, m_default) StructMember(SNAME(m_name), Variant::OBJECT, m_class_name, nullptr, m_default)
#define STRUCT_STRUCT_MEMBER(m_name, m_struct, m_default) StructMember(SNAME(m_name), Variant::ARRAY, m_struct::get_name(), m_struct::get_members(), m_default)

#define STRUCT_LAYOUT(m_struct, m_name, ...) \
struct m_struct { \
_FORCE_INLINE_ static const StringName get_class() { \
return SNAME(#m_struct); \
} \
_FORCE_INLINE_ static const StringName get_name() { \
return SNAME(m_name); \
} \
_FORCE_INLINE_ static const StructMember *get_members() { \
static const StructMember members[] = { __VA_ARGS__ }; \
return members; \
} \
_FORCE_INLINE_ static const uint32_t get_member_count() { \
const StructMember members[] = { __VA_ARGS__ }; \
static const uint32_t member_count = sizeof(members) / sizeof(StructMember); \
return member_count; \
} \
_FORCE_INLINE_ static const StructMember &get_member(uint32_t p_index) { \
CRASH_BAD_INDEX(p_index, get_member_count()); \
return get_members()[p_index]; \
} \
};
#define STRUCT_MEMBER(m_name, m_type, m_default) StructMember(SNAME(#m_name), m_type, StringName(), nullptr, m_default)
#define STRUCT_CLASS_MEMBER(m_name, m_class_name, m_default) StructMember(SNAME(#m_name), Variant::OBJECT, #m_class_name, nullptr, m_default)
#define STRUCT_STRUCT_MEMBER(m_name, m_struct, m_default) StructMember(SNAME(#m_name), Variant::ARRAY, m_struct::get_struct_name(), m_struct::get_struct_members(), m_default)

#define STRUCT_LAYOUT(m_name, ...) \
_FORCE_INLINE_ static const StringName get_struct_name() { \
static const StringName struct_name = SNAME(#m_name); \
return struct_name; \
} \
_FORCE_INLINE_ static const StructMember *get_struct_members() { \
static const StructMember members[] = { __VA_ARGS__ }; \
return members; \
} \
_FORCE_INLINE_ static const uint32_t get_struct_member_count() { \

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Template w/ Mono (target=template_release)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Template w/ Mono (target=template_release)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Minimal template (target=template_release, everything disabled)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]

Check failure on line 182 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Minimal template (target=template_release, everything disabled)

type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
const StructMember members[] = { __VA_ARGS__ }; \
static const uint32_t member_count = sizeof(members) / sizeof(StructMember); \
return member_count; \
} \
_FORCE_INLINE_ static const StructMember &get_struct_member(uint32_t p_index) { \
CRASH_BAD_INDEX(p_index, get_struct_member_count()); \
return get_struct_members()[p_index]; \
}

struct PropertyInfo {
Variant::Type type = Variant::NIL;
Expand All @@ -203,6 +199,14 @@ struct PropertyInfo {

// If you are thinking about adding another member to this class, ask the maintainer (Juan) first.

STRUCT_LAYOUT(PropertyInfo,

Check failure on line 202 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with clang sanitizers (target=editor, tests=yes, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)

'const' type qualifier on return type has no effect [-Werror,-Wignored-qualifiers]

Check failure on line 202 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with clang sanitizers (target=editor, tests=yes, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)

'const' type qualifier on return type has no effect [-Werror,-Wignored-qualifiers]

Check failure on line 202 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with ThreadSanitizer (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)

'const' type qualifier on return type has no effect [-Werror,-Wignored-qualifiers]

Check failure on line 202 in core/object/object.h

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with ThreadSanitizer (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)

'const' type qualifier on return type has no effect [-Werror,-Wignored-qualifiers]
STRUCT_MEMBER(name, Variant::STRING, String()),
STRUCT_MEMBER(class_name, Variant::STRING_NAME, StringName()),
STRUCT_MEMBER(type, Variant::INT, Variant::NIL),
STRUCT_MEMBER(hint, Variant::INT, PROPERTY_HINT_NONE),
STRUCT_MEMBER(hint_string, Variant::STRING, String()),
STRUCT_MEMBER(usage, Variant::INT, PROPERTY_USAGE_DEFAULT));

_FORCE_INLINE_ PropertyInfo added_usage(uint32_t p_fl) const {
PropertyInfo pi = *this;
pi.usage |= p_fl;
Expand All @@ -213,9 +217,9 @@ struct PropertyInfo {

static PropertyInfo from_dict(const Dictionary &p_dict);

operator Array() const;
operator Struct<PropertyInfo>() const;

static PropertyInfo from_struct(const Array &p_struct);
static PropertyInfo from_struct(const Struct<PropertyInfo> &p_struct);

PropertyInfo() {}

Expand Down Expand Up @@ -258,14 +262,6 @@ struct PropertyInfo {
}
};

STRUCT_LAYOUT(PropertyInfoLayout, "PropertyInfo",
STRUCT_MEMBER("name", Variant::STRING, String()),
STRUCT_MEMBER("class_name", Variant::STRING_NAME, StringName()),
STRUCT_MEMBER("type", Variant::INT, Variant::NIL),
STRUCT_MEMBER("hint", Variant::INT, PROPERTY_HINT_NONE),
STRUCT_MEMBER("hint_string", Variant::STRING, String()),
STRUCT_MEMBER("usage", Variant::INT, PROPERTY_USAGE_DEFAULT));

TypedArray<Dictionary> convert_property_list(const List<PropertyInfo> *p_list);

enum MethodFlags {
Expand Down Expand Up @@ -650,7 +646,7 @@ class Object {

// TODO: These methods are for testing purposes only and will be removed before release.
// TypedArray<Struct<PropertyInfoLayout>> _get_property_list_struct() const;
Struct<PropertyInfoLayout> _get_property_struct(uint32_t p_index) const;
Struct<PropertyInfo> _get_property_struct(uint32_t p_index) const;

private:
#ifdef DEBUG_ENABLED
Expand Down
14 changes: 7 additions & 7 deletions core/variant/struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,20 @@ class Struct : public Array {
ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign a Struct from array with a different format.");
_ref(p_array);
}
_FORCE_INLINE_ Variant &operator[](const StringName &p_member) {
return get_named(p_member);
_FORCE_INLINE_ Variant &operator[](const StringName &p_struct_member) {
return get_named(p_struct_member);
}
_FORCE_INLINE_ const Variant &operator[](const StringName &p_member) const {
return get_named(p_member);
_FORCE_INLINE_ const Variant &operator[](const StringName &p_struct_member) const {
return get_named(p_struct_member);
}
_FORCE_INLINE_ Struct(const Variant &p_variant) :
Array(Array(p_variant), T::get_name(), T::get_member) {
Array(Array(p_variant), T::get_struct_name(), T::get_struct_member) {
}
_FORCE_INLINE_ Struct(const Array &p_array) :
Array(p_array, T::get_name(), T::get_member) {
Array(p_array, T::get_struct_name(), T::get_struct_member) {
}
_FORCE_INLINE_ Struct() :
Array(T::get_member_count(), T::get_name(), T::get_member) {
Array(T::get_struct_member_count(), T::get_struct_name(), T::get_struct_member) {
}
};

Expand Down
6 changes: 3 additions & 3 deletions core/variant/typed_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ class TypedArray<Struct<T>> : public Array {
_ref(p_array);
}
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
Array(Array(p_variant), Variant::ARRAY, T::get_name(), Variant()) {
Array(Array(p_variant), Variant::ARRAY, T::get_struct_name(), Variant()) {
}
_FORCE_INLINE_ TypedArray(const Array &p_array) :
Array(p_array, Variant::ARRAY, T::get_name(), Variant()) {
Array(p_array, Variant::ARRAY, T::get_struct_name(), Variant()) {
}
_FORCE_INLINE_ TypedArray() {
set_typed(Variant::ARRAY, T::get_name(), Variant());
set_typed(Variant::ARRAY, T::get_struct_name(), Variant());
}
};

Expand Down
57 changes: 31 additions & 26 deletions tests/core/variant/test_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ TEST_CASE("[Struct] PropertyInfo") {
my_node->get_property_list(&list);
PropertyInfo info = list[0];
CHECK_EQ((((Variant)(Dictionary)info)).stringify(), "{ \"name\": \"Node\", \"class_name\": &\"\", \"type\": 0, \"hint\": 0, \"hint_string\": \"Node\", \"usage\": 128 }");
CHECK_EQ((((Variant)(Array)info)).stringify(), "[name: \"Node\", class_name: &\"\", type: 0, hint: 0, hint_string: \"Node\", usage: 128]");
CHECK_EQ((((Variant)(Struct<PropertyInfo>)info)).stringify(), "[name: \"Node\", class_name: &\"\", type: 0, hint: 0, hint_string: \"Node\", usage: 128]");

Struct<PropertyInfoLayout> prop = my_node->_get_property_struct(0);
Struct<PropertyInfo> prop = my_node->_get_property_struct(0);
CHECK_EQ(((Variant)prop).stringify(), "[name: \"Node\", class_name: &\"\", type: 0, hint: 0, hint_string: \"Node\", usage: 128]");

SUBCASE("Equality") {
Expand Down Expand Up @@ -90,12 +90,13 @@ TEST_CASE("[Struct] Validation") {
struct NamedInt {
StringName name = StringName();
int value = 0;

STRUCT_LAYOUT(NamedInt,
STRUCT_MEMBER(name, Variant::STRING_NAME, StringName()),
STRUCT_MEMBER(value, Variant::INT, 0));
};
STRUCT_LAYOUT(NamedIntLayout, "NamedInt",
STRUCT_MEMBER("name", Variant::STRING_NAME, StringName()),
STRUCT_MEMBER("value", Variant::INT, 0));

Struct<NamedIntLayout> named_int;
Struct<NamedInt> named_int;
named_int["name"] = "Godot";
named_int["value"] = 4;
CHECK_EQ(((Variant)named_int).stringify(), "[name: \"Godot\", value: 4]");
Expand All @@ -104,12 +105,12 @@ TEST_CASE("[Struct] Validation") {
CHECK(named_int.is_same_typed(named_int));
Variant variant_named_int = named_int;
CHECK(named_int.is_same_typed(variant_named_int));
Struct<NamedIntLayout> same_named_int = variant_named_int;
Struct<NamedInt> same_named_int = variant_named_int;
CHECK_EQ(named_int, same_named_int);
}

SUBCASE("Assignment") {
Struct<NamedIntLayout> a_match = named_int;
Struct<NamedInt> a_match = named_int;
CHECK_EQ(named_int, a_match);
Array not_a_match;

Expand Down Expand Up @@ -147,28 +148,32 @@ TEST_CASE("[Struct] Nesting") {
struct BasicStruct {
int int_val;
float float_val;

STRUCT_LAYOUT(BasicStruct,
STRUCT_MEMBER(int_val, Variant::INT, 4),
STRUCT_MEMBER(float_val, Variant::FLOAT, 5.5));
};
struct BasicStructLookalike {
int int_val;
float float_val;

STRUCT_LAYOUT(BasicStructLookalike,
STRUCT_MEMBER(int_val, Variant::INT, 0),
STRUCT_MEMBER(float_val, Variant::FLOAT, 0.0));
};
struct NestedStruct {
Node *node;
BasicStruct value;

STRUCT_LAYOUT(NestedStruct,
STRUCT_CLASS_MEMBER(node, Node, Variant()),
STRUCT_STRUCT_MEMBER(value, BasicStruct, Struct<BasicStruct>()));
};
STRUCT_LAYOUT(BasicStructLayout, "BasicStruct",
STRUCT_MEMBER("int_val", Variant::INT, 4),
STRUCT_MEMBER("float_val", Variant::FLOAT, 5.5));
STRUCT_LAYOUT(BasicStructLookalikeLayout, "BasicStructLookalike",
STRUCT_MEMBER("int_val", Variant::INT, 0),
STRUCT_MEMBER("float_val", Variant::FLOAT, 0.0));
STRUCT_LAYOUT(NestedStructLayout, "NestedStruct",
STRUCT_CLASS_MEMBER("node", "Node", Variant()),
STRUCT_STRUCT_MEMBER("value", BasicStructLayout, Struct<BasicStructLayout>()));

Struct<BasicStructLayout> basic_struct;
Struct<BasicStructLookalikeLayout> basic_struct_lookalike;
Struct<NestedStructLayout> nested_struct;


Struct<BasicStruct> basic_struct;
Struct<BasicStructLookalike> basic_struct_lookalike;
Struct<NestedStruct> nested_struct;

SUBCASE("Defaults") {
CHECK_EQ((int)basic_struct["int_val"], 4);
Expand All @@ -191,8 +196,8 @@ TEST_CASE("[Struct] Nesting") {

CHECK_EQ(nested_struct["node"], Variant(node));
CHECK_EQ(nested_struct["value"], basic_struct);
CHECK_EQ(((Struct<BasicStructLayout>)nested_struct["value"])["int_val"], basic_struct["int_val"]);
CHECK_EQ(((Struct<BasicStructLayout>)nested_struct["value"])["float_val"], basic_struct["float_val"]);
CHECK_EQ(((Struct<BasicStruct>)nested_struct["value"])["int_val"], basic_struct["int_val"]);
CHECK_EQ(((Struct<BasicStruct>)nested_struct["value"])["float_val"], basic_struct["float_val"]);

ERR_PRINT_OFF;
nested_struct.set_named("value", basic_struct_lookalike);
Expand All @@ -201,11 +206,11 @@ TEST_CASE("[Struct] Nesting") {
}

SUBCASE("Typed Array of Struct") {
TypedArray<Struct<BasicStructLayout>> array;
Struct<BasicStructLayout> basic_struct_0;
TypedArray<Struct<BasicStruct>> array;
Struct<BasicStruct> basic_struct_0;
basic_struct_0["int_val"] = 1;
basic_struct_0["float_val"] = 3.14;
Struct<BasicStructLayout> basic_struct_1;
Struct<BasicStruct> basic_struct_1;
basic_struct_1["int_val"] = 2;
basic_struct_1["float_val"] = 2.7;
array.push_back(basic_struct_0);
Expand Down

0 comments on commit d4cc397

Please sign in to comment.