Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Structs to core.
Browse files Browse the repository at this point in the history
nlupugla committed Oct 1, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent e3213aa commit f7f01b1
Showing 29 changed files with 2,343 additions and 438 deletions.
2 changes: 2 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
@@ -856,6 +856,8 @@ if env.msvc and not methods.using_clang(env): # MSVC
]
)

env.Append(CCFLAGS=["/permissive-"])

if env["werror"]:
env.Append(CCFLAGS=["/WX"])
env.Append(LINKFLAGS=["/WX"])
77 changes: 77 additions & 0 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@
#include "core/math/geometry_3d.h"
#include "core/os/keyboard.h"
#include "core/os/thread_safe.h"
#include "core/variant/struct.h"
#include "core/variant/typed_array.h"

namespace core_bind {
@@ -1442,6 +1443,15 @@ Dictionary ClassDB::class_get_signal(const StringName &p_class, const StringName
}
}

//Struct<MethodInfo> ClassDB::class_get_signal_as_struct(const StringName &p_class, const StringName &p_signal) const {
// MethodInfo signal;
// if (::ClassDB::get_signal(p_class, p_signal, &signal)) {
// return Struct<MethodInfo>(signal);
// } else {
// return Struct<MethodInfo>();
// }
//}

TypedArray<Dictionary> ClassDB::class_get_signal_list(const StringName &p_class, bool p_no_inheritance) const {
List<MethodInfo> signals;
::ClassDB::get_signal_list(p_class, &signals, p_no_inheritance);
@@ -1454,6 +1464,12 @@ TypedArray<Dictionary> ClassDB::class_get_signal_list(const StringName &p_class,
return ret;
}

//TypedArray<Struct<MethodInfo>> ClassDB::class_get_signal_list_as_structs(const StringName &p_class, bool p_no_inheritance) const {
// List<MethodInfo> signals;
// ::ClassDB::get_signal_list(p_class, &signals, p_no_inheritance);
// return TypedArray<Struct<MethodInfo>>(&signals);
//}

TypedArray<Dictionary> ClassDB::class_get_property_list(const StringName &p_class, bool p_no_inheritance) const {
List<PropertyInfo> plist;
::ClassDB::get_property_list(p_class, &plist, p_no_inheritance);
@@ -1465,6 +1481,12 @@ TypedArray<Dictionary> ClassDB::class_get_property_list(const StringName &p_clas
return ret;
}

//TypedArray<Struct<PropertyInfo>> ClassDB::class_get_property_list_as_structs(const StringName &p_class, bool p_no_inheritance) const {
// List<PropertyInfo> plist;
// ::ClassDB::get_property_list(p_class, &plist, p_no_inheritance);
// return TypedArray<Struct<PropertyInfo>>(&plist);
//}

StringName ClassDB::class_get_property_getter(const StringName &p_class, const StringName &p_property) {
return ::ClassDB::get_property_getter(p_class, p_property);
}
@@ -1525,6 +1547,12 @@ TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class,
return ret;
}

//TypedArray<Struct<MethodInfo>> ClassDB::class_get_method_list_as_structs(const StringName &p_class, bool p_no_inheritance) const {
// List<MethodInfo> methods;
// ::ClassDB::get_method_list(p_class, &methods, p_no_inheritance);
// return TypedArray<Struct<MethodInfo>>(&methods);
//}

Variant ClassDB::class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) {
if (p_argcount < 2) {
r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
@@ -1609,6 +1637,47 @@ bool ClassDB::is_class_enum_bitfield(const StringName &p_class, const StringName
return ::ClassDB::is_enum_bitfield(p_class, p_enum, p_no_inheritance);
}

bool ClassDB::class_has_struct(const StringName &p_class, const StringName &p_struct, bool p_no_inheritance) const {
return ::ClassDB::get_struct_info(p_class, p_struct, p_no_inheritance) != nullptr;
}

TypedArray<Dictionary> ClassDB::class_get_struct_list(const StringName &p_class, bool p_no_inheritance) const {
List<StructInfo> structs;
TypedArray<Dictionary> ret;
::ClassDB::get_struct_list(p_class, &structs, p_no_inheritance);
for (const StructInfo &struct_info : structs) {
Dictionary struct_dict;
for (int i = 0; i < struct_info.count; i++) {
Dictionary member_dict;
member_dict[SNAME("name")] = struct_info.names[i];
member_dict[SNAME("type")] = struct_info.types[i];
member_dict[SNAME("class_name")] = struct_info.class_names[i];
member_dict[SNAME("default_value")] = struct_info.default_values[i];
struct_dict[struct_info.name] = member_dict;
}
ret.push_back(struct_dict);
}
return ret;
}

TypedArray<Dictionary> ClassDB::class_get_struct_members(const StringName &p_class, const StringName &p_struct) const {
// TODO: this should return an array of structs if possible without circular reference
TypedArray<Dictionary> ret;
const StructInfo *struct_info = ::ClassDB::get_struct_info(p_class, p_struct);
if (!struct_info) {
return ret; // TODO: should this be an error?
}
for (int i = 0; i < struct_info->count; i++) {
Dictionary dict;
dict[SNAME("name")] = struct_info->names[i];
dict[SNAME("type")] = struct_info->types[i];
dict[SNAME("class_name")] = struct_info->class_names[i];
dict[SNAME("default_value")] = struct_info->default_values[i];
ret.push_back(dict);
}
return ret;
}

bool ClassDB::is_class_enabled(const StringName &p_class) const {
return ::ClassDB::is_class_enabled(p_class);
}
@@ -1650,9 +1719,12 @@ void ClassDB::_bind_methods() {

::ClassDB::bind_method(D_METHOD("class_has_signal", "class", "signal"), &ClassDB::class_has_signal);
::ClassDB::bind_method(D_METHOD("class_get_signal", "class", "signal"), &ClassDB::class_get_signal);
//::ClassDB::bind_method(D_METHOD("class_get_signal_as_struct", "class", "signal"), &ClassDB::class_get_signal_as_struct);
::ClassDB::bind_method(D_METHOD("class_get_signal_list", "class", "no_inheritance"), &ClassDB::class_get_signal_list, DEFVAL(false));
//::ClassDB::bind_method(D_METHOD("class_get_signal_list_as_structs", "class", "no_inheritance"), &ClassDB::class_get_signal_list_as_structs, DEFVAL(false));

::ClassDB::bind_method(D_METHOD("class_get_property_list", "class", "no_inheritance"), &ClassDB::class_get_property_list, DEFVAL(false));
//::ClassDB::bind_method(D_METHOD("class_get_property_list_as_structs", "class", "no_inheritance"), &ClassDB::class_get_property_list_as_structs, DEFVAL(false));
::ClassDB::bind_method(D_METHOD("class_get_property_getter", "class", "property"), &ClassDB::class_get_property_getter);
::ClassDB::bind_method(D_METHOD("class_get_property_setter", "class", "property"), &ClassDB::class_get_property_setter);
::ClassDB::bind_method(D_METHOD("class_get_property", "object", "property"), &ClassDB::class_get_property);
@@ -1665,6 +1737,7 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("class_get_method_argument_count", "class", "method", "no_inheritance"), &ClassDB::class_get_method_argument_count, DEFVAL(false));

::ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &ClassDB::class_get_method_list, DEFVAL(false));
//::ClassDB::bind_method(D_METHOD("class_get_method_list_as_structs", "class", "no_inheritance"), &ClassDB::class_get_method_list_as_structs, DEFVAL(false));

::ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "class_call_static_method", &ClassDB::class_call_static_method, MethodInfo("class_call_static_method", PropertyInfo(Variant::STRING_NAME, "class"), PropertyInfo(Variant::STRING_NAME, "method")));

@@ -1680,6 +1753,10 @@ void ClassDB::_bind_methods() {

::ClassDB::bind_method(D_METHOD("is_class_enum_bitfield", "class", "enum", "no_inheritance"), &ClassDB::is_class_enum_bitfield, DEFVAL(false));

// ::ClassDB::bind_method(D_METHOD("class_has_struct", "class", "struct", "no_inheritance"), &ClassDB::class_has_struct, DEFVAL(false));
// ::ClassDB::bind_method(D_METHOD("class_get_struct_list", "class", "no_inheritance"), &ClassDB::class_get_struct_list, DEFVAL(false));
// ::ClassDB::bind_method(D_METHOD("class_get_struct_members", "class", "struct"), &ClassDB::class_get_struct_members);

::ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &ClassDB::is_class_enabled);

BIND_ENUM_CONSTANT(API_CORE);
8 changes: 8 additions & 0 deletions core/core_bind.h
Original file line number Diff line number Diff line change
@@ -468,9 +468,12 @@ class ClassDB : public Object {
APIType class_get_api_type(const StringName &p_class) const;
bool class_has_signal(const StringName &p_class, const StringName &p_signal) const;
Dictionary class_get_signal(const StringName &p_class, const StringName &p_signal) const;
//Struct<MethodInfo> class_get_signal_as_struct(const StringName &p_class, const StringName &p_signal) const;
TypedArray<Dictionary> class_get_signal_list(const StringName &p_class, bool p_no_inheritance = false) const;
//TypedArray<Struct<MethodInfo>> class_get_signal_list_as_structs(const StringName &p_class, bool p_no_inheritance = false) const;

TypedArray<Dictionary> class_get_property_list(const StringName &p_class, bool p_no_inheritance = false) const;
//TypedArray<Struct<PropertyInfo>> class_get_property_list_as_structs(const StringName &p_class, bool p_no_inheritance = false) const;
StringName class_get_property_getter(const StringName &p_class, const StringName &p_property);
StringName class_get_property_setter(const StringName &p_class, const StringName &p_property);
Variant class_get_property(Object *p_object, const StringName &p_property) const;
@@ -483,6 +486,7 @@ class ClassDB : public Object {
int class_get_method_argument_count(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const;

TypedArray<Dictionary> class_get_method_list(const StringName &p_class, bool p_no_inheritance = false) const;
//TypedArray<Struct<MethodInfo>> class_get_method_list_as_structs(const StringName &p_class, bool p_no_inheritance = false) const;
Variant class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error);

PackedStringArray class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
@@ -498,6 +502,10 @@ class ClassDB : public Object {

bool is_class_enabled(const StringName &p_class) const;

bool class_has_struct(const StringName &p_class, const StringName &p_struct, bool p_no_inheritance = false) const;
TypedArray<Dictionary> class_get_struct_list(const StringName &p_class, bool p_no_inheritance = false) const;
TypedArray<Dictionary> class_get_struct_members(const StringName &p_class, const StringName &p_struct) const;

#ifdef TOOLS_ENABLED
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
#endif
73 changes: 73 additions & 0 deletions core/object/class_db.cpp
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
#include "core/io/resource_loader.h"
#include "core/object/script_language.h"
#include "core/os/mutex.h"
#include "core/variant/struct.h"
#include "core/version.h"

#define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
@@ -505,6 +506,8 @@ uint32_t ClassDB::get_api_hash(APIType p_api) {
hash = hash_murmur3_one_64(F.hint_string.hash(), hash);
hash = hash_murmur3_one_64(F.usage, hash);
}

// TODO: do I need to incorporate the structs into the hash?
}

hash = hash_fmix32(hash);
@@ -1317,6 +1320,67 @@ bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_na
return false;
}

void ClassDB::bind_struct(const StringName &p_class_name, const StructInfo &p_struct_info) {
OBJTYPE_WLOCK;

ClassInfo *type = classes.getptr(p_class_name);

ERR_FAIL_NULL(type);

if (type->struct_map.has(p_struct_info.name)) {
ERR_FAIL();
}

String struct_name = p_struct_info.name;
if (struct_name.contains(".")) {
struct_name = struct_name.get_slicec('.', 1);
}

type->struct_map.insert(struct_name, p_struct_info);
}

void ClassDB::get_struct_list(const StringName &p_class, List<StructInfo> *r_structs, bool p_no_inheritance) {
OBJTYPE_RLOCK;

ClassInfo *type = classes.getptr(p_class);

while (type) {
for (const KeyValue<StringName, StructInfo> &E : type->struct_map) {
r_structs->push_back(E.value);
}

if (p_no_inheritance) {
break;
}

type = type->inherits_ptr;
}
}

const StructInfo *ClassDB::get_struct_info(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
OBJTYPE_RLOCK;

ClassInfo *type = classes.getptr(p_class);
while (type) {
if (const StructInfo *info = type->struct_map.getptr(p_name)) {
return info;
}
if (p_no_inheritance) {
return nullptr;
}
type = type->inherits_ptr;
}
return nullptr;
}

const StructInfo *ClassDB::get_struct_info(const String &p_qualified_name, bool p_no_inheritance) {
Vector<String> names = String(p_qualified_name).split("."); // TODO: what about cases other than size == 2?
if (names.size() == 2) {
return ClassDB::get_struct_info(names[0], names[1]);
}
return nullptr;
}

void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
OBJTYPE_WLOCK;

@@ -1429,6 +1493,15 @@ void ClassDB::add_property_array(const StringName &p_class, const StringName &p_
type->property_list.push_back(PropertyInfo(Variant::NIL, p_path, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, p_array_element_prefix));
}

// TODO: This probably isn't right, I just copied the function above.
void ClassDB::add_property_struct(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix) {
OBJTYPE_WLOCK; // TODO: I'm not sure what this does but it's in the one above so I figure I need it
ClassInfo *type = classes.getptr(p_class);
ERR_FAIL_NULL(type);

type->property_list.push_back(PropertyInfo(Variant::NIL, p_path, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, p_array_element_prefix));
}

// NOTE: For implementation simplicity reasons, this method doesn't allow setters to have optional arguments at the end.
void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
lock.read_lock();
10 changes: 10 additions & 0 deletions core/object/class_db.h
Original file line number Diff line number Diff line change
@@ -114,6 +114,7 @@ class ClassDB {
};

HashMap<StringName, EnumInfo> enum_map;
HashMap<StringName, StructInfo> struct_map;
HashMap<StringName, MethodInfo> signal_map;
List<PropertyInfo> property_list;
HashMap<StringName, PropertyInfo> property_map;
@@ -426,6 +427,7 @@ class ClassDB {
static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = "", int p_indent_depth = 0);
static void add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage = PROPERTY_USAGE_DEFAULT);
static void add_property_array(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix);
static void add_property_struct(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix);
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static void set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default);
static void add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property);
@@ -467,6 +469,11 @@ class ClassDB {
static bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
static bool is_enum_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);

static void bind_struct(const StringName &p_class, const StructInfo &p_struct_info);
static void get_struct_list(const StringName &p_class, List<StructInfo> *r_structs, bool p_no_inheritance = false);
static const StructInfo *get_struct_info(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
static const StructInfo *get_struct_info(const String &p_qualified_name, bool p_no_inheritance = false);

static void set_method_error_return_values(const StringName &p_class, const StringName &p_method, const Vector<Error> &p_values);
static Vector<Error> get_method_error_return_values(const StringName &p_class, const StringName &p_method);
static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid = nullptr);
@@ -506,6 +513,9 @@ class ClassDB {
#define BIND_CONSTANT(m_constant) \
::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::Layout::get_struct_info());

#ifdef DEBUG_METHODS_ENABLED

_FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr) {
Loading

0 comments on commit f7f01b1

Please sign in to comment.