Skip to content

Commit

Permalink
Added Structs to core.
Browse files Browse the repository at this point in the history
  • Loading branch information
nlupugla committed Sep 21, 2024
1 parent e4e024a commit defe5d5
Show file tree
Hide file tree
Showing 29 changed files with 2,338 additions and 513 deletions.
2 changes: 2 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,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"])
Expand Down
77 changes: 77 additions & 0 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -1437,6 +1438,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);
Expand All @@ -1449,6 +1459,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);
Expand All @@ -1460,6 +1476,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);
}
Expand Down Expand Up @@ -1520,6 +1542,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;
Expand Down Expand Up @@ -1604,6 +1632,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);
}
Expand Down Expand Up @@ -1645,9 +1714,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);
Expand All @@ -1660,6 +1732,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")));

Expand All @@ -1675,6 +1748,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);
Expand Down
8 changes: 8 additions & 0 deletions core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,9 +466,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;
Expand All @@ -481,6 +484,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;
Expand All @@ -496,6 +500,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
Expand Down
73 changes: 73 additions & 0 deletions core/object/class_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand Down
10 changes: 10 additions & 0 deletions core/object/class_db.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit defe5d5

Please sign in to comment.