Merge pull request #113586 from Ivorforce/gdtype-noms-enums
Move enum registration from `ClassDB` / `ClassInfo` to `GDType`.
This commit is contained in:
10 files changed
+233
-204
No files matched your search
@@ -760,9 +760,9 @@ void Resource::_bind_methods() {
|
||||
|
||||
// For the bindings, it's much more natural to expose this enum from the Variant realm via Resource.
|
||||
// Therefore, we can't use BIND_ENUM_CONSTANT here because we need some customization.
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName("DeepDuplicateMode"), "DEEP_DUPLICATE_NONE", RESOURCE_DEEP_DUPLICATE_NONE);
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName("DeepDuplicateMode"), "DEEP_DUPLICATE_INTERNAL", RESOURCE_DEEP_DUPLICATE_INTERNAL);
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName("DeepDuplicateMode"), "DEEP_DUPLICATE_ALL", RESOURCE_DEEP_DUPLICATE_ALL);
|
||||
get_gdtype_static_mutable().bind_integer_constant(StringName("DeepDuplicateMode"), "DEEP_DUPLICATE_NONE", RESOURCE_DEEP_DUPLICATE_NONE);
|
||||
get_gdtype_static_mutable().bind_integer_constant(StringName("DeepDuplicateMode"), "DEEP_DUPLICATE_INTERNAL", RESOURCE_DEEP_DUPLICATE_INTERNAL);
|
||||
get_gdtype_static_mutable().bind_integer_constant(StringName("DeepDuplicateMode"), "DEEP_DUPLICATE_ALL", RESOURCE_DEEP_DUPLICATE_ALL);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("changed"));
|
||||
ADD_SIGNAL(MethodInfo("setup_local_to_scene_requested"));
|
||||
|
||||
+38
-131
@@ -461,7 +461,7 @@ uint32_t ClassDB::get_api_hash(APIType p_api) {
|
||||
|
||||
List<StringName> snames;
|
||||
|
||||
for (const KeyValue<StringName, int64_t> &F : t->constant_map) {
|
||||
for (const KeyValue<StringName, int64_t> &F : t->gdtype->get_integer_constant_map(true)) {
|
||||
snames.push_back(F.key);
|
||||
}
|
||||
|
||||
@@ -469,7 +469,7 @@ uint32_t ClassDB::get_api_hash(APIType p_api) {
|
||||
|
||||
for (const StringName &F : snames) {
|
||||
hash = hash_murmur3_one_64(F.hash(), hash);
|
||||
hash = hash_murmur3_one_64(uint64_t(t->constant_map[F]), hash);
|
||||
hash = hash_murmur3_one_64(uint64_t(t->gdtype->get_integer_constant_map(true)[F]), hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -883,7 +883,7 @@ use_script:
|
||||
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
|
||||
}
|
||||
|
||||
void ClassDB::_add_class(const GDType &p_class, const GDType *p_inherits) {
|
||||
void ClassDB::_add_class(GDType &p_class, const GDType *p_inherits) {
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
const StringName &name = p_class.get_name();
|
||||
@@ -1158,61 +1158,19 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
if (type->constant_map.has(p_name)) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
type->constant_map[p_name] = p_constant;
|
||||
|
||||
String enum_name = p_enum;
|
||||
if (!enum_name.is_empty()) {
|
||||
if (enum_name.contains_char('.')) {
|
||||
enum_name = enum_name.get_slicec('.', 1);
|
||||
}
|
||||
|
||||
ClassInfo::EnumInfo *constants_list = type->enum_map.getptr(enum_name);
|
||||
|
||||
if (constants_list) {
|
||||
constants_list->constants.push_back(p_name);
|
||||
constants_list->is_bitfield = p_is_bitfield;
|
||||
} else {
|
||||
ClassInfo::EnumInfo new_list;
|
||||
new_list.is_bitfield = p_is_bitfield;
|
||||
new_list.constants.push_back(p_name);
|
||||
type->enum_map[enum_name] = new_list;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
type->constant_order.push_back(p_name);
|
||||
#endif // DEBUG_ENABLED
|
||||
type->gdtype->bind_integer_constant(p_enum, p_name, p_constant, p_is_bitfield);
|
||||
}
|
||||
|
||||
void ClassDB::get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance) {
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
while (type) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
for (const StringName &E : type->constant_order) {
|
||||
p_constants->push_back(E);
|
||||
}
|
||||
#else
|
||||
|
||||
for (const KeyValue<StringName, int64_t> &E : type->constant_map) {
|
||||
p_constants->push_back(E.key);
|
||||
}
|
||||
|
||||
#endif // DEBUG_ENABLED
|
||||
if (p_no_inheritance) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
for (const KeyValue<StringName, int64_t> &E : type->gdtype->get_integer_constant_map(p_no_inheritance)) {
|
||||
p_constants->push_back(E.key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1220,23 +1178,19 @@ int64_t ClassDB::get_integer_constant(const StringName &p_class, const StringNam
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
while (type) {
|
||||
int64_t *constant = type->constant_map.getptr(p_name);
|
||||
if (type) {
|
||||
const int64_t *constant = type->gdtype->get_integer_constant_map(false).getptr(p_name);
|
||||
if (constant) {
|
||||
if (p_success) {
|
||||
*p_success = true;
|
||||
}
|
||||
return *constant;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
}
|
||||
|
||||
if (p_success) {
|
||||
*p_success = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1244,60 +1198,33 @@ bool ClassDB::has_integer_constant(const StringName &p_class, const StringName &
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL_V(type, false);
|
||||
|
||||
while (type) {
|
||||
if (type->constant_map.has(p_name)) {
|
||||
return true;
|
||||
}
|
||||
if (p_no_inheritance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
return type->gdtype->get_integer_constant_map(p_no_inheritance).has(p_name);
|
||||
}
|
||||
|
||||
StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL_V(type, StringName());
|
||||
|
||||
while (type) {
|
||||
for (KeyValue<StringName, ClassInfo::EnumInfo> &E : type->enum_map) {
|
||||
List<StringName> &constants_list = E.value.constants;
|
||||
const List<StringName>::Element *found = constants_list.find(p_name);
|
||||
if (found) {
|
||||
return E.key;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_no_inheritance) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
}
|
||||
|
||||
return StringName();
|
||||
const GDType::EnumInfo *enum_info = type->gdtype->get_integer_constant_enum(p_name, p_no_inheritance);
|
||||
return enum_info ? enum_info->name : StringName();
|
||||
}
|
||||
|
||||
void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance) {
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
if (!type) {
|
||||
// TODO This should probably error, but didn't previously.
|
||||
// Making this error leads to a few prints during unit tests.
|
||||
return;
|
||||
}
|
||||
|
||||
while (type) {
|
||||
for (KeyValue<StringName, ClassInfo::EnumInfo> &E : type->enum_map) {
|
||||
p_enums->push_back(E.key);
|
||||
}
|
||||
|
||||
if (p_no_inheritance) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
for (const KeyValue<StringName, const GDType::EnumInfo *> &E : type->gdtype->get_enum_map(p_no_inheritance)) {
|
||||
p_enums->push_back(E.key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1305,21 +1232,13 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
while (type) {
|
||||
const ClassInfo::EnumInfo *constants = type->enum_map.getptr(p_enum);
|
||||
const GDType::EnumInfo *const *enum_info = type->gdtype->get_enum_map(p_no_inheritance).getptr(p_enum);
|
||||
ERR_FAIL_NULL(enum_info);
|
||||
|
||||
if (constants) {
|
||||
for (const List<StringName>::Element *E = constants->constants.front(); E; E = E->next()) {
|
||||
p_constants->push_back(E->get());
|
||||
}
|
||||
}
|
||||
|
||||
if (p_no_inheritance) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
for (const KeyValue<StringName, int64_t> &kv : (*enum_info)->values) {
|
||||
p_constants->push_back(kv.key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1354,38 +1273,25 @@ bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL_V(type, false);
|
||||
|
||||
while (type) {
|
||||
if (type->enum_map.has(p_name)) {
|
||||
return true;
|
||||
}
|
||||
if (p_no_inheritance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
return type->gdtype->get_enum_map(p_no_inheritance).has(p_name);
|
||||
}
|
||||
|
||||
bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL_V(type, false);
|
||||
|
||||
while (type) {
|
||||
if (type->enum_map.has(p_name) && type->enum_map[p_name].is_bitfield) {
|
||||
return true;
|
||||
}
|
||||
if (p_no_inheritance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
type = type->inherits_ptr;
|
||||
const GDType::EnumInfo *const *enum_info = type->gdtype->get_enum_map(p_no_inheritance).getptr(p_name);
|
||||
// FIXME This fails unexpectedly often. Keeping legacy behavior to silently fail for now.
|
||||
//ERR_FAIL_NULL_V(enum_info, false);
|
||||
if (!enum_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return (*enum_info)->is_bitfield;
|
||||
}
|
||||
|
||||
void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
|
||||
@@ -1727,7 +1633,7 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia
|
||||
return true;
|
||||
}
|
||||
|
||||
const int64_t *c = check->constant_map.getptr(p_property); //constants count
|
||||
const int64_t *c = check->gdtype->get_integer_constant_map(true).getptr(p_property); //constants count
|
||||
if (c) {
|
||||
r_value = *c;
|
||||
return true;
|
||||
@@ -2446,8 +2352,9 @@ void ClassDB::cleanup() {
|
||||
native_structs.clear();
|
||||
|
||||
for (GDType **type : gdtype_autorelease_pool) {
|
||||
if (!type) {
|
||||
if (!*type) {
|
||||
WARN_PRINT("GDType in autorelease pool was cleaned up before being auto-released. Ignoring.");
|
||||
continue;
|
||||
}
|
||||
memdelete(*type);
|
||||
*type = nullptr;
|
||||
|
||||
+6
-13
@@ -95,6 +95,7 @@ MethodDefinition D_METHOD(const char *p_name, const VarArgs... p_args) {
|
||||
|
||||
class ClassDB {
|
||||
friend class Object;
|
||||
friend class GDType;
|
||||
|
||||
public:
|
||||
enum APIType {
|
||||
@@ -119,25 +120,18 @@ public:
|
||||
APIType api = API_NONE;
|
||||
ClassInfo *inherits_ptr = nullptr;
|
||||
void *class_ptr = nullptr;
|
||||
const GDType *gdtype = nullptr;
|
||||
GDType *gdtype = nullptr;
|
||||
|
||||
ObjectGDExtension *gdextension = nullptr;
|
||||
|
||||
HashMap<StringName, MethodBind *> method_map;
|
||||
HashMap<StringName, LocalVector<MethodBind *>> method_map_compatibility;
|
||||
AHashMap<StringName, int64_t> constant_map;
|
||||
struct EnumInfo {
|
||||
List<StringName> constants;
|
||||
bool is_bitfield = false;
|
||||
};
|
||||
|
||||
HashMap<StringName, EnumInfo> enum_map;
|
||||
AHashMap<StringName, MethodInfo> signal_map;
|
||||
List<PropertyInfo> property_list;
|
||||
HashMap<StringName, PropertyInfo> property_map;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
List<StringName> constant_order;
|
||||
List<StringName> method_order;
|
||||
HashSet<StringName> methods_in_properties;
|
||||
List<MethodInfo> virtual_methods;
|
||||
@@ -215,7 +209,7 @@ public:
|
||||
static APIType current_api;
|
||||
static HashMap<APIType, uint32_t> api_hashes_cache;
|
||||
|
||||
static void _add_class(const GDType &p_class, const GDType *p_inherits);
|
||||
static void _add_class(GDType &p_class, const GDType *p_inherits);
|
||||
|
||||
static HashMap<StringName, HashMap<StringName, Variant>> default_values;
|
||||
static HashSet<StringName> default_values_cached;
|
||||
@@ -507,7 +501,6 @@ public:
|
||||
static bool has_integer_constant(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
|
||||
|
||||
static StringName get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
|
||||
static StringName get_integer_constant_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
|
||||
static void get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance = false);
|
||||
static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false);
|
||||
static bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
|
||||
@@ -551,13 +544,13 @@ public:
|
||||
};
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
::ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant), __constant_get_enum_value_name(#m_constant), m_constant);
|
||||
get_gdtype_static_mutable().bind_integer_constant(__constant_get_enum_name(m_constant), __constant_get_enum_value_name(#m_constant), m_constant);
|
||||
|
||||
#define BIND_BITFIELD_FLAG(m_constant) \
|
||||
::ClassDB::bind_integer_constant(get_class_static(), __constant_get_bitfield_name(m_constant), __constant_get_enum_value_name(#m_constant), m_constant, true);
|
||||
get_gdtype_static_mutable().bind_integer_constant(__constant_get_bitfield_name(m_constant), __constant_get_enum_value_name(#m_constant), m_constant, true);
|
||||
|
||||
#define BIND_CONSTANT(m_constant) \
|
||||
::ClassDB::bind_integer_constant(get_class_static(), StringName(), __constant_get_enum_value_name(#m_constant), m_constant);
|
||||
get_gdtype_static_mutable().bind_integer_constant(StringName(), __constant_get_enum_value_name(#m_constant), m_constant);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
|
||||
#include "gdtype.h"
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
GDType::GDType(const GDType *p_super_type, StringName p_name) :
|
||||
super_type(p_super_type), name(std::move(p_name)) {
|
||||
name_hierarchy.push_back(name);
|
||||
@@ -40,3 +44,67 @@ GDType::GDType(const GDType *p_super_type, StringName p_name) :
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GDType::~GDType() {
|
||||
for (const KeyValue<StringName, const EnumInfo *> &kv : self_enum_map) {
|
||||
memdelete(const_cast<EnumInfo *>(kv.value));
|
||||
}
|
||||
}
|
||||
|
||||
void GDType::initialize() {
|
||||
ERR_FAIL_COND(init_state != InitState::UNINITIALIZED);
|
||||
|
||||
if (super_type) {
|
||||
// Now that a subtype is registered, the supertype cannot change anymore.
|
||||
// Otherwise, our caches would become invalid.
|
||||
// This shouldn't be a problem, since classes should register all their
|
||||
// parts in _bind_methods, which is called on registration.
|
||||
super_type->init_state = InitState::FINALIZED;
|
||||
|
||||
constant_map = super_type->constant_map;
|
||||
enum_map = super_type->enum_map;
|
||||
}
|
||||
|
||||
init_state = InitState::MUTABLE;
|
||||
}
|
||||
|
||||
void GDType::bind_integer_constant(const StringName &p_enum, const StringName &p_name, int64_t p_constant, bool p_is_bitfield) {
|
||||
ERR_FAIL_COND(!Thread::is_main_thread());
|
||||
ERR_FAIL_COND(init_state != InitState::MUTABLE);
|
||||
ERR_FAIL_COND(self_constant_map.has(p_name));
|
||||
|
||||
constant_map[p_name] = p_constant;
|
||||
self_constant_map[p_name] = p_constant;
|
||||
|
||||
String enum_name = p_enum;
|
||||
if (!enum_name.is_empty()) {
|
||||
if (enum_name.contains_char('.')) {
|
||||
enum_name = enum_name.get_slicec('.', 1);
|
||||
}
|
||||
|
||||
const EnumInfo **_enum_info = self_enum_map.getptr(enum_name);
|
||||
|
||||
if (_enum_info != nullptr) {
|
||||
EnumInfo *enum_info = const_cast<EnumInfo *>(*_enum_info);
|
||||
enum_info->values.insert(p_name, p_constant);
|
||||
enum_info->is_bitfield = p_is_bitfield;
|
||||
} else {
|
||||
EnumInfo *enum_info = memnew(EnumInfo);
|
||||
enum_info->name = enum_name;
|
||||
enum_info->is_bitfield = p_is_bitfield;
|
||||
enum_info->values.insert(p_name, p_constant);
|
||||
self_enum_map[enum_name] = enum_info;
|
||||
enum_map[enum_name] = enum_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const GDType::EnumInfo *GDType::get_integer_constant_enum(const StringName &p_name, bool p_no_inheritance) const {
|
||||
for (const KeyValue<StringName, const EnumInfo *> &kv : get_enum_map(p_no_inheritance)) {
|
||||
if (kv.value->values.has(p_name)) {
|
||||
return kv.value;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -31,20 +31,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/templates/a_hash_map.h"
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/vector.h"
|
||||
|
||||
class GDType {
|
||||
public:
|
||||
enum class InitState {
|
||||
UNINITIALIZED,
|
||||
MUTABLE,
|
||||
FINALIZED,
|
||||
};
|
||||
|
||||
struct EnumInfo {
|
||||
StringName name;
|
||||
AHashMap<StringName, int64_t> values;
|
||||
bool is_bitfield = false;
|
||||
};
|
||||
|
||||
protected:
|
||||
const GDType *super_type;
|
||||
mutable InitState init_state = InitState::UNINITIALIZED;
|
||||
|
||||
StringName name;
|
||||
/// Contains all the class names in order:
|
||||
/// `name` is the first element and `Object` is the last.
|
||||
Vector<StringName> name_hierarchy;
|
||||
|
||||
AHashMap<StringName, int64_t> constant_map;
|
||||
AHashMap<StringName, int64_t> self_constant_map;
|
||||
|
||||
AHashMap<StringName, const EnumInfo *> enum_map;
|
||||
AHashMap<StringName, const EnumInfo *> self_enum_map;
|
||||
|
||||
public:
|
||||
GDType(const GDType *p_super_type, StringName p_name);
|
||||
~GDType();
|
||||
|
||||
InitState get_init_state() const { return init_state; }
|
||||
void initialize();
|
||||
|
||||
const GDType *get_super_type() const { return super_type; }
|
||||
const StringName &get_name() const { return name; }
|
||||
const Vector<StringName> &get_name_hierarchy() const { return name_hierarchy; }
|
||||
|
||||
void bind_integer_constant(const StringName &p_enum, const StringName &p_name, int64_t p_constant, bool p_is_bitfield = false);
|
||||
const AHashMap<StringName, int64_t> &get_integer_constant_map(bool p_no_inheritance = false) const { return p_no_inheritance ? self_constant_map : constant_map; }
|
||||
const AHashMap<StringName, const EnumInfo *> &get_enum_map(bool p_no_inheritance = false) const { return p_no_inheritance ? self_enum_map : enum_map; }
|
||||
const EnumInfo *get_integer_constant_enum(const StringName &p_name, bool p_no_inheritance = false) const;
|
||||
};
|
||||
+16
-17
@@ -235,6 +235,7 @@ void ObjectGDExtension::create_gdtype() {
|
||||
ERR_FAIL_COND(gdtype);
|
||||
|
||||
gdtype = memnew(GDType(ClassDB::get_gdtype(parent_class_name), class_name));
|
||||
gdtype->initialize();
|
||||
}
|
||||
|
||||
void ObjectGDExtension::destroy_gdtype() {
|
||||
@@ -1441,6 +1442,10 @@ void Object::_reset_gdtype() const {
|
||||
}
|
||||
}
|
||||
|
||||
void Object::autorelease_gdtype(GDType **r_type) {
|
||||
ClassDB::gdtype_autorelease_pool.push_back(r_type);
|
||||
}
|
||||
|
||||
void Object::_add_user_signal(const String &p_name, const Array &p_args) {
|
||||
// this version of add_user_signal is meant to be used from scripts or external apis
|
||||
// without access to ADD_SIGNAL in bind_methods
|
||||
@@ -1793,10 +1798,18 @@ Variant Object::_get_indexed_bind(const NodePath &p_name) const {
|
||||
|
||||
void Object::initialize_class() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
if (likely(initialized)) {
|
||||
return;
|
||||
}
|
||||
_add_class_to_classdb(get_gdtype_static(), nullptr);
|
||||
|
||||
static BinaryMutex __init_mutex;
|
||||
MutexLock lock(__init_mutex);
|
||||
if (initialized) {
|
||||
// Initialized on another thread while we were waiting.
|
||||
return;
|
||||
}
|
||||
_add_class_to_classdb(get_gdtype_static_mutable(), nullptr);
|
||||
get_gdtype_static_mutable().initialize();
|
||||
_bind_methods();
|
||||
_bind_compatibility_methods();
|
||||
initialized = true;
|
||||
@@ -1872,7 +1885,7 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
|
||||
}
|
||||
}
|
||||
|
||||
void Object::_add_class_to_classdb(const GDType &p_type, const GDType *p_inherits) {
|
||||
void Object::_add_class_to_classdb(GDType &p_type, const GDType *p_inherits) {
|
||||
ClassDB::_add_class(p_type, p_inherits);
|
||||
}
|
||||
|
||||
@@ -2407,20 +2420,6 @@ void Object::detach_from_objectdb() {
|
||||
}
|
||||
}
|
||||
|
||||
void Object::assign_type_static(GDType **type_ptr, const char *p_name, const GDType *super_type) {
|
||||
static BinaryMutex _mutex;
|
||||
MutexLock lock(_mutex);
|
||||
GDType *type = *type_ptr;
|
||||
if (type) {
|
||||
// Assigned while we were waiting.
|
||||
return;
|
||||
}
|
||||
type = memnew(GDType(super_type, StringName(p_name)));
|
||||
*type_ptr = type;
|
||||
|
||||
ClassDB::gdtype_autorelease_pool.push_back(type_ptr);
|
||||
}
|
||||
|
||||
Object::~Object() {
|
||||
if (_emitting) {
|
||||
//@todo this may need to actually reach the debugger prioritarily somehow because it may crash before
|
||||
|
||||
+50
-17
@@ -372,7 +372,7 @@ struct ObjectGDExtension {
|
||||
|
||||
/// A type for this Object extension.
|
||||
/// This is not exposed through the GDExtension API (yet) so it is inferred from above parameters.
|
||||
const GDType *gdtype;
|
||||
GDType *gdtype;
|
||||
void create_gdtype();
|
||||
void destroy_gdtype();
|
||||
|
||||
@@ -491,17 +491,31 @@ private:
|
||||
private: \
|
||||
void operator=(const m_class &p_rval) {} \
|
||||
friend class ::ClassDB; \
|
||||
\
|
||||
static GDType &get_gdtype_static_mutable() { \
|
||||
static GDType *gdtype = nullptr; \
|
||||
static bool initialized = false; \
|
||||
if (likely(initialized)) { \
|
||||
return *gdtype; \
|
||||
} \
|
||||
\
|
||||
static BinaryMutex __init_mutex; \
|
||||
MutexLock lock(__init_mutex); \
|
||||
if (initialized) { \
|
||||
return *gdtype; \
|
||||
} \
|
||||
gdtype = memnew(GDType(&super_type::get_gdtype_static(), StringName(#m_class))); \
|
||||
m_class::autorelease_gdtype(&gdtype); \
|
||||
initialized = true; \
|
||||
return *gdtype; \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
virtual const GDType &_get_typev() const override { \
|
||||
return get_gdtype_static(); \
|
||||
} \
|
||||
static const GDType &get_gdtype_static() { \
|
||||
static GDType *_class_static; \
|
||||
if (unlikely(!_class_static)) { \
|
||||
assign_type_static(&_class_static, #m_class, &super_type::get_gdtype_static()); \
|
||||
} \
|
||||
return *_class_static; \
|
||||
return get_gdtype_static_mutable(); \
|
||||
} \
|
||||
static const StringName &get_class_static() { \
|
||||
return get_gdtype_static().get_name(); \
|
||||
@@ -518,11 +532,18 @@ protected: \
|
||||
public: \
|
||||
static void initialize_class() { \
|
||||
static bool initialized = false; \
|
||||
if (likely(initialized)) { \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
static BinaryMutex __init_mutex; \
|
||||
MutexLock lock(__init_mutex); \
|
||||
if (initialized) { \
|
||||
return; \
|
||||
} \
|
||||
m_inherits::initialize_class(); \
|
||||
_add_class_to_classdb(get_gdtype_static(), &super_type::get_gdtype_static()); \
|
||||
_add_class_to_classdb(get_gdtype_static_mutable(), &super_type::get_gdtype_static()); \
|
||||
get_gdtype_static_mutable().initialize(); \
|
||||
if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \
|
||||
_bind_methods(); \
|
||||
} \
|
||||
@@ -672,6 +693,24 @@ private:
|
||||
mutable const GDType *_gdtype_ptr = nullptr;
|
||||
void _reset_gdtype() const;
|
||||
|
||||
static GDType &get_gdtype_static_mutable() {
|
||||
static GDType *gdtype = nullptr;
|
||||
static bool initialized = false;
|
||||
if (likely(initialized)) {
|
||||
return *gdtype;
|
||||
}
|
||||
|
||||
static BinaryMutex __init_mutex;
|
||||
MutexLock lock(__init_mutex);
|
||||
if (initialized) {
|
||||
return *gdtype;
|
||||
}
|
||||
gdtype = memnew(GDType(nullptr, StringName("Object")));
|
||||
autorelease_gdtype(&gdtype);
|
||||
initialized = true;
|
||||
return *gdtype;
|
||||
}
|
||||
|
||||
void _add_user_signal(const String &p_name, const Array &p_args = Array());
|
||||
bool _has_user_signal(const StringName &p_name) const;
|
||||
void _remove_user_signal(const StringName &p_name);
|
||||
@@ -780,6 +819,8 @@ protected:
|
||||
Variant _call_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||
Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||
|
||||
static void autorelease_gdtype(GDType **r_type);
|
||||
|
||||
virtual const GDType &_get_typev() const { return get_gdtype_static(); }
|
||||
|
||||
TypedArray<StringName> _get_meta_list_bind() const;
|
||||
@@ -791,7 +832,7 @@ protected:
|
||||
friend class ::ClassDB;
|
||||
friend class PlaceholderExtensionInstance;
|
||||
|
||||
static void _add_class_to_classdb(const GDType &p_class, const GDType *p_inherits);
|
||||
static void _add_class_to_classdb(GDType &p_class, const GDType *p_inherits);
|
||||
static void _get_property_list_from_classdb(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator);
|
||||
|
||||
bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);
|
||||
@@ -860,15 +901,7 @@ public:
|
||||
};
|
||||
|
||||
/* TYPE API */
|
||||
static void assign_type_static(GDType **type_ptr, const char *p_name, const GDType *super_type);
|
||||
|
||||
static const GDType &get_gdtype_static() {
|
||||
static GDType *_class_static;
|
||||
if (unlikely(!_class_static)) {
|
||||
assign_type_static(&_class_static, "Object", nullptr);
|
||||
}
|
||||
return *_class_static;
|
||||
}
|
||||
static const GDType &get_gdtype_static() { return get_gdtype_static_mutable(); }
|
||||
|
||||
const GDType &get_gdtype() const;
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
|
||||
|
||||
List<StringName> snames;
|
||||
|
||||
for (const KeyValue<StringName, int64_t> &F : t->constant_map) {
|
||||
for (const KeyValue<StringName, int64_t> &F : t->gdtype->get_integer_constant_map(true)) {
|
||||
snames.push_back(F.key);
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
|
||||
constants.push_back(constant_dict);
|
||||
|
||||
constant_dict["name"] = F;
|
||||
constant_dict["value"] = t->constant_map[F];
|
||||
constant_dict["value"] = t->gdtype->get_integer_constant_map(true)[F];
|
||||
}
|
||||
|
||||
if (!constants.is_empty()) {
|
||||
|
||||
@@ -4352,10 +4352,10 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
|
||||
List<String> constants;
|
||||
ClassDB::get_integer_constant_list(type_cname, &constants, true);
|
||||
|
||||
const HashMap<StringName, ClassDB::ClassInfo::EnumInfo> &enum_map = class_info->enum_map;
|
||||
const AHashMap<StringName, const GDType::EnumInfo *> &enum_map = class_info->gdtype->get_enum_map(true);
|
||||
|
||||
for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &E : enum_map) {
|
||||
StringName enum_proxy_cname = E.key;
|
||||
for (const KeyValue<StringName, const GDType::EnumInfo *> &kv : enum_map) {
|
||||
StringName enum_proxy_cname = kv.key;
|
||||
String enum_proxy_name = pascal_to_pascal_case(enum_proxy_cname.operator String());
|
||||
if (itype.find_property_by_proxy_name(enum_proxy_name) || itype.find_method_by_proxy_name(enum_proxy_name) || itype.find_signal_by_proxy_name(enum_proxy_name)) {
|
||||
// In case the enum name conflicts with other PascalCase members,
|
||||
@@ -4364,15 +4364,12 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
|
||||
enum_proxy_name += "Enum";
|
||||
enum_proxy_cname = StringName(enum_proxy_name);
|
||||
}
|
||||
EnumInterface ienum(enum_proxy_cname, enum_proxy_name, E.value.is_bitfield);
|
||||
const List<StringName> &enum_constants = E.value.constants;
|
||||
for (const StringName &constant_cname : enum_constants) {
|
||||
String constant_name = constant_cname.operator String();
|
||||
int64_t *value = class_info->constant_map.getptr(constant_cname);
|
||||
ERR_FAIL_NULL_V(value, false);
|
||||
constants.erase(constant_name);
|
||||
EnumInterface ienum(enum_proxy_cname, enum_proxy_name, kv.value->is_bitfield);
|
||||
for (const KeyValue<StringName, int64_t> &kv_case : kv.value->values) {
|
||||
String constant_name = kv_case.key.operator String();
|
||||
constants.erase(kv_case.key);
|
||||
|
||||
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
|
||||
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), kv_case.value);
|
||||
|
||||
iconstant.const_doc = nullptr;
|
||||
for (int i = 0; i < itype.class_doc->constants.size(); i++) {
|
||||
@@ -4405,7 +4402,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
|
||||
|
||||
TypeInterface enum_itype;
|
||||
enum_itype.is_enum = true;
|
||||
enum_itype.name = itype.name + "." + String(E.key);
|
||||
enum_itype.name = itype.name + "." + String(kv.key);
|
||||
enum_itype.cname = StringName(enum_itype.name);
|
||||
enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name;
|
||||
TypeInterface::postsetup_enum_type(enum_itype);
|
||||
@@ -4413,7 +4410,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
|
||||
}
|
||||
|
||||
for (const String &constant_name : constants) {
|
||||
int64_t *value = class_info->constant_map.getptr(StringName(constant_name));
|
||||
const int64_t *value = class_info->gdtype->get_integer_constant_map(true).getptr(StringName(constant_name));
|
||||
ERR_FAIL_NULL_V(value, false);
|
||||
|
||||
String constant_proxy_name = snake_to_pascal_case(constant_name, true);
|
||||
|
||||
@@ -764,18 +764,18 @@ void add_exposed_classes(Context &r_context) {
|
||||
List<String> constants;
|
||||
ClassDB::get_integer_constant_list(class_name, &constants, true);
|
||||
|
||||
const HashMap<StringName, ClassDB::ClassInfo::EnumInfo> &enum_map = class_info->enum_map;
|
||||
const AHashMap<StringName, const GDType::EnumInfo *> &enum_map = class_info->gdtype->get_enum_map(true);
|
||||
|
||||
for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &K : enum_map) {
|
||||
for (const KeyValue<StringName, const GDType::EnumInfo *> &kv_enum : enum_map) {
|
||||
EnumData enum_;
|
||||
enum_.name = K.key;
|
||||
enum_.name = kv_enum.key;
|
||||
|
||||
for (const StringName &E : K.value.constants) {
|
||||
const StringName &constant_name = E;
|
||||
for (const KeyValue<StringName, int64_t> &kv_case : kv_enum.value->values) {
|
||||
const StringName &constant_name = kv_case.key;
|
||||
TEST_FAIL_COND(String(constant_name).contains("::"),
|
||||
"Enum constant contains '::', check bindings to remove the scope: '",
|
||||
String(class_name), ".", String(enum_.name), ".", String(constant_name), "'.");
|
||||
int64_t *value = class_info->constant_map.getptr(constant_name);
|
||||
const int64_t *value = class_info->gdtype->get_integer_constant_map(false).getptr(constant_name);
|
||||
TEST_FAIL_COND(!value, "Missing enum constant value: '",
|
||||
String(class_name), ".", String(enum_.name), ".", String(constant_name), "'.");
|
||||
constants.erase(constant_name);
|
||||
@@ -789,7 +789,7 @@ void add_exposed_classes(Context &r_context) {
|
||||
|
||||
exposed_class.enums.push_back(enum_);
|
||||
|
||||
r_context.enum_types.push_back(String(class_name) + "." + String(K.key));
|
||||
r_context.enum_types.push_back(String(class_name) + "." + String(kv_enum.key));
|
||||
}
|
||||
|
||||
for (const String &E : constants) {
|
||||
@@ -797,7 +797,7 @@ void add_exposed_classes(Context &r_context) {
|
||||
TEST_FAIL_COND(constant_name.contains("::"),
|
||||
"Constant contains '::', check bindings to remove the scope: '",
|
||||
String(class_name), ".", constant_name, "'.");
|
||||
int64_t *value = class_info->constant_map.getptr(StringName(E));
|
||||
const int64_t *value = class_info->gdtype->get_integer_constant_map(false).getptr(StringName(E));
|
||||
TEST_FAIL_COND(!value, "Missing constant value: '", String(class_name), ".", String(constant_name), "'.");
|
||||
|
||||
ConstantData constant;
|
||||
|
||||
Reference in new issue
Block a user