diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 6b5e9b4f4287..43f2ba3cd6b9 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -399,12 +399,14 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { hash = hash_murmur3_one_64(t->gdtype->get_name().hash(), hash); hash = hash_murmur3_one_64(t->gdtype->get_super_type_name().hash(), hash); - { //methods - - List snames; + LocalVector methods; + LocalVector constants; + LocalVector signals; + LocalVector setgets; - for (const KeyValue &F : t->gdtype->get_method_map(true)) { - String name = F.key.string(); + for (const KeyValue &kv : t->gdtype->get_property_map(true)) { + if (kv.value.type == GDType::Property::Type::METHOD) { + String name = kv.key.string(); ERR_CONTINUE(name.is_empty()); @@ -412,13 +414,21 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { continue; // Ignore non-virtual methods that start with an underscore } - snames.push_back(F.key); + methods.push_back(kv.key); + } else if (kv.value.type == GDType::Property::Type::INTEGER_CONSTANT) { + constants.push_back(kv.key); + } else if (kv.value.type == GDType::Property::Type::SIGNAL) { + signals.push_back(kv.key); + } else if (kv.value.type == GDType::Property::Type::SETGET) { + setgets.push_back(kv.key); } + } - snames.sort_custom(); + { //methods + methods.sort_custom(); - for (const StringName &F : snames) { - const MethodBind *mb = t->gdtype->get_method_map(true)[F]; + for (const StringName &F : methods) { + const MethodBind *mb = t->gdtype->get_property_map(true)[F].payload.method; hash = hash_murmur3_one_64(mb->get_name().hash(), hash); hash = hash_murmur3_one_64(mb->get_argument_count(), hash); hash = hash_murmur3_one_64(mb->get_argument_type(-1), hash); //return @@ -445,33 +455,19 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { } { //constants + constants.sort_custom(); - List snames; - - for (const KeyValue &F : t->gdtype->get_integer_constant_map(true)) { - snames.push_back(F.key); - } - - snames.sort_custom(); - - for (const StringName &F : snames) { + for (const StringName &F : constants) { hash = hash_murmur3_one_64(F.hash(), hash); - hash = hash_murmur3_one_64(uint64_t(t->gdtype->get_integer_constant_map(true)[F]), hash); + hash = hash_murmur3_one_64(uint64_t(t->gdtype->get_property_map(true)[F].payload.integer_constant.value), hash); } } { //signals + signals.sort_custom(); - List snames; - - for (const KeyValue &F : t->gdtype->get_signal_map(true)) { - snames.push_back(F.key); - } - - snames.sort_custom(); - - for (const StringName &F : snames) { - const MethodInfo &mi = *t->gdtype->get_signal_map(true)[F]; + for (const StringName &F : signals) { + const MethodInfo &mi = *t->gdtype->get_property_map(true)[F].payload.signal; hash = hash_murmur3_one_64(F.hash(), hash); for (const PropertyInfo &pi : mi.arguments) { hash = hash_murmur3_one_64(pi.type, hash); @@ -480,18 +476,9 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { } { - //properties - - LocalVector snames; - - for (const KeyValue &kv : t->gdtype->get_property_map(true)) { - if (kv.value.type == GDType::Property::Type::SETGET) { - snames.push_back(kv.key); - } - } - snames.sort_custom(); + setgets.sort_custom(); - for (const StringName &F : snames) { + for (const StringName &F : setgets) { const GDType::Property &property = t->gdtype->get_property_map(true)[F]; const GDType::Property::SetGet &psg = property.payload.setget; @@ -979,13 +966,21 @@ void ClassDB::get_method_list(const StringName &p_class, List *p_met Locker::Lock lock(Locker::STATE_READ); ClassInfo *type = classes.getptr(p_class); - for (const KeyValue &kv : type->gdtype->get_method_map(p_no_inheritance)) { + ERR_FAIL_NULL(type); + + do { if (type->disabled) { + type = type->inherits_ptr; continue; } - p_methods->push_back(info_from_bind(kv.value)); - } + for (const KeyValue &kv : type->gdtype->get_property_map(true)) { + if (kv.value.type == GDType::Property::Type::METHOD) { + p_methods->push_back(info_from_bind(kv.value.payload.method)); + } + } + type = type->inherits_ptr; + } while (type && !p_no_inheritance); #ifdef DEBUG_ENABLED ClassDB::get_virtual_methods(p_class, p_methods, p_no_inheritance); @@ -996,13 +991,7 @@ void ClassDB::get_method_list_with_compatibility(const StringName &p_class, List Locker::Lock lock(Locker::STATE_READ); ClassInfo *type = classes.getptr(p_class); - for (const KeyValue &kv : type->gdtype->get_method_map(p_no_inheritance)) { - if (type->disabled) { - continue; - } - - p_methods->push_back(Pair(info_from_bind(kv.value), kv.value->get_hash())); - } + ERR_FAIL_NULL(type); while (type) { if (type->disabled) { @@ -1013,6 +1002,11 @@ void ClassDB::get_method_list_with_compatibility(const StringName &p_class, List type = type->inherits_ptr; continue; } + for (const KeyValue &kv : type->gdtype->get_property_map(true)) { + if (kv.value.type == GDType::Property::Type::METHOD) { + p_methods->push_back(Pair(info_from_bind(kv.value.payload.method), kv.value.payload.method->get_hash())); + } + } #ifdef DEBUG_ENABLED for (const MethodInfo &E : type->virtual_methods) { Pair pair(E, E.get_compatibility_hash()); @@ -1052,11 +1046,10 @@ bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_met } #ifdef DEBUG_ENABLED - const MethodBind *const *method = type->gdtype->get_method_map(true).getptr(p_method); - if (method) { + const GDType::Property *property = type->gdtype->get_property_map(true).getptr(p_method); + if (property && property->type == GDType::Property::Type::METHOD) { if (r_info != nullptr) { - MethodInfo minfo = info_from_bind(*method); - *r_info = minfo; + *r_info = info_from_bind(property->payload.method); } return true; } else if (type->virtual_methods_map.has(p_method)) { @@ -1066,11 +1059,10 @@ bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_met return true; } #else - if (type->gdtype->get_method_map(true).has(p_method)) { + const GDType::Property *property = type->gdtype->get_property_map(true).getptr(p_method); + if (property && property->type == GDType::Property::Type::METHOD) { if (r_info) { - const MethodBind *m = type->gdtype->get_method_map(true)[p_method]; - MethodInfo minfo = info_from_bind(m); - *r_info = minfo; + *r_info = info_from_bind(property->payload.method); } return true; } @@ -1094,8 +1086,8 @@ const MethodBind *ClassDB::get_method(const StringName &p_class, const StringNam return nullptr; } - const MethodBind *const *method = type->gdtype->get_method_map(false).getptr(p_name); - return method ? *method : nullptr; + const GDType::Property *property = type->gdtype->get_property_map().getptr(p_name); + return property && property->type == GDType::Property::Type::METHOD ? property->payload.method : nullptr; } Vector ClassDB::get_method_compatibility_hashes(const StringName &p_class, const StringName &p_name) { @@ -1123,13 +1115,13 @@ const MethodBind *ClassDB::get_method_with_compatibility(const StringName &p_cla ClassInfo *type = classes.getptr(p_class); while (type) { - const MethodBind *const *method = type->gdtype->get_method_map(true).getptr(p_name); - if (method) { + const GDType::Property *property = type->gdtype->get_property_map(true).getptr(p_name); + if (property && property->type == GDType::Property::Type::METHOD) { if (r_method_exists) { *r_method_exists = true; } - if ((*method)->get_hash() == p_hash) { - return *method; + if (property->payload.method->get_hash() == p_hash) { + return property->payload.method; } } @@ -1167,8 +1159,10 @@ void ClassDB::get_integer_constant_list(const StringName &p_class, List ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NO_CLASS(type, p_class); - for (const KeyValue &E : type->gdtype->get_integer_constant_map(p_no_inheritance)) { - p_constants->push_back(E.key); + for (const KeyValue &kv : type->gdtype->get_property_map(p_no_inheritance)) { + if (kv.value.type == GDType::Property::Type::INTEGER_CONSTANT) { + p_constants->push_back(kv.key); + } } } @@ -1177,12 +1171,12 @@ int64_t ClassDB::get_integer_constant(const StringName &p_class, const StringNam ClassInfo *type = classes.getptr(p_class); if (type) { - const int64_t *constant = type->gdtype->get_integer_constant_map(false).getptr(p_name); - if (constant) { + const GDType::Property *property = type->gdtype->get_property_map().getptr(p_name); + if (property && property->type == GDType::Property::Type::INTEGER_CONSTANT) { if (p_success) { *p_success = true; } - return *constant; + return property->payload.integer_constant.value; } } @@ -1198,7 +1192,8 @@ bool ClassDB::has_integer_constant(const StringName &p_class, const StringName & ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NULL_V(type, false); - return type->gdtype->get_integer_constant_map(p_no_inheritance).has(p_name); + const GDType::Property *property = type->gdtype->get_property_map(p_no_inheritance).getptr(p_name); + return property && property->type == GDType::Property::Type::INTEGER_CONSTANT; } StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) { @@ -1221,8 +1216,10 @@ void ClassDB::get_enum_list(const StringName &p_class, List *p_enums return; } - for (const KeyValue &E : type->gdtype->get_enum_map(p_no_inheritance)) { - p_enums->push_back(E.key); + for (const KeyValue &kv : type->gdtype->get_property_map(p_no_inheritance)) { + if (kv.value.type == GDType::Property::Type::ENUM) { + p_enums->push_back(kv.key); + } } } @@ -1232,10 +1229,11 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_ ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NO_CLASS(type, p_class); - const GDType::EnumInfo *const *enum_info = type->gdtype->get_enum_map(p_no_inheritance).getptr(p_enum); - ERR_FAIL_NULL(enum_info); + const GDType::Property *property = type->gdtype->get_property_map(p_no_inheritance).getptr(p_enum); + ERR_FAIL_NULL(property); + ERR_FAIL_COND(property->type != GDType::Property::Type::ENUM); - for (const KeyValue &kv : (*enum_info)->values) { + for (const KeyValue &kv : property->payload.enum_info->values) { p_constants->push_back(kv.key); } } @@ -1273,7 +1271,8 @@ bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NULL_V(type, false); - return type->gdtype->get_enum_map(p_no_inheritance).has(p_name); + const GDType::Property *property = type->gdtype->get_property_map(p_no_inheritance).getptr(p_name); + return property && property->type == GDType::Property::Type::ENUM; } bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) { @@ -1282,14 +1281,13 @@ bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_na ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NULL_V(type, false); - const GDType::EnumInfo *const *enum_info = type->gdtype->get_enum_map(p_no_inheritance).getptr(p_name); + const GDType::Property *property = type->gdtype->get_property_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) { + if (!property || property->type != GDType::Property::Type::ENUM) { return false; } - return (*enum_info)->is_bitfield; + return property->payload.enum_info->is_bitfield; } void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) { @@ -1307,8 +1305,10 @@ void ClassDB::get_signal_list(const StringName &p_class, List *p_sig ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NO_CLASS(type, p_class); - for (const KeyValue &kv : type->gdtype->get_signal_map(p_no_inheritance)) { - p_signals->push_back(*kv.value); + for (const KeyValue &kv : type->gdtype->get_property_map(p_no_inheritance)) { + if (kv.value.type == GDType::Property::Type::SIGNAL) { + p_signals->push_back(*kv.value.payload.signal); + } } } @@ -1318,7 +1318,8 @@ bool ClassDB::has_signal(const StringName &p_class, const StringName &p_signal, if (!type) { return false; } - return type->gdtype->get_signal_map(p_no_inheritance).has(p_signal); + const GDType::Property *property = type->gdtype->get_property_map(p_no_inheritance).getptr(p_signal); + return property && property->type == GDType::Property::Type::SIGNAL; } bool ClassDB::get_signal(const StringName &p_class, const StringName &p_signal, MethodInfo *r_signal) { @@ -1327,12 +1328,12 @@ bool ClassDB::get_signal(const StringName &p_class, const StringName &p_signal, if (!type) { return false; } - const MethodInfo *const *method_info = type->gdtype->get_signal_map(false).getptr(p_signal); - if (method_info) { - *r_signal = **method_info; - return true; + const GDType::Property *property = type->gdtype->get_property_map().getptr(p_signal); + if (!property || property->type != GDType::Property::Type::SIGNAL) { + return false; } - return false; + *r_signal = *property->payload.signal; + return true; } void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix, int p_indent_depth) { @@ -1570,7 +1571,8 @@ bool ClassDB::has_method(const StringName &p_class, const StringName &p_method, if (!type) { return false; } - return type->gdtype->get_method_map(p_no_inheritance).has(p_method); + const GDType::Property *property = type->gdtype->get_property_map(p_no_inheritance).getptr(p_method); + return property && property->type == GDType::Property::Type::METHOD; } int ClassDB::get_method_argument_count(const StringName &p_class, const StringName &p_method, bool *r_is_valid, bool p_no_inheritance) { @@ -1578,12 +1580,12 @@ int ClassDB::get_method_argument_count(const StringName &p_class, const StringNa ClassInfo *type = classes.getptr(p_class); if (type) { - const MethodBind *const *method = type->gdtype->get_method_map(p_no_inheritance).getptr(p_method); - if (method) { + const GDType::Property *property = type->gdtype->get_property_map(p_no_inheritance).getptr(p_method); + if (property && property->type == GDType::Property::Type::METHOD) { if (r_is_valid) { *r_is_valid = true; } - return (*method)->get_argument_count(); + return property->payload.method->get_argument_count(); } } diff --git a/core/object/gdtype.cpp b/core/object/gdtype.cpp index ecec9cb4feec..16257fe20c45 100644 --- a/core/object/gdtype.cpp +++ b/core/object/gdtype.cpp @@ -46,11 +46,12 @@ GDType::GDType(const GDType *p_super_type, StringName p_name) : } GDType::~GDType() { - for (const KeyValue &kv : self_enum_map) { - memdelete(const_cast(kv.value)); - } - for (const KeyValue &kv : self_signal_map) { - memdelete(const_cast(kv.value)); + for (const KeyValue &kv : self_property_map) { + if (kv.value.type == Property::Type::ENUM) { + memdelete(const_cast(kv.value.payload.enum_info)); + } else if (kv.value.type == Property::Type::SIGNAL) { + memdelete(const_cast(kv.value.payload.signal)); + } } for (MethodBind *bind : owned_method_map) { memdelete(bind); @@ -70,10 +71,6 @@ void GDType::initialize() { // 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; - signal_map = super_type->signal_map; - method_map = super_type->method_map; property_map = super_type->property_map; } @@ -83,13 +80,9 @@ void GDType::initialize() { 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_MSG(self_constant_map.has(p_name), vformat("Class '%s' already has constant '%s'.", String(name), String(p_name))); ERR_FAIL_COND_MSG(property_map.has(p_name), vformat("Object '%s' already has property '%s'.", get_name(), p_name)); - constant_map[p_name] = p_constant; - self_constant_map[p_name] = p_constant; - property_map.insert(p_name, Property(Property::Type::INTEGER_CONSTANT, p_constant)); - self_property_map.insert(p_name, Property(Property::Type::INTEGER_CONSTANT, p_constant)); + EnumInfo *enum_info = nullptr; String enum_name = p_enum; if (!enum_name.is_empty()) { @@ -97,31 +90,35 @@ void GDType::bind_integer_constant(const StringName &p_enum, const StringName &p enum_name = enum_name.get_slicec('.', 1); } - const EnumInfo **_enum_info = self_enum_map.getptr(enum_name); + const Property *enum_property = self_property_map.getptr(enum_name); + ERR_FAIL_COND_MSG(!enum_property && property_map.has(enum_name), vformat("Cannot bind integer constant '%s' to enum '%s' from class '%s' because the enum belongs to a parent class.", p_name, enum_name, get_name())); + ERR_FAIL_COND_MSG(enum_property && enum_property->type != Property::Type::ENUM, vformat("Object '%s' already has property '%s'.", get_name(), enum_name)); - if (_enum_info != nullptr) { - EnumInfo *enum_info = const_cast(*_enum_info); + if (enum_property) { + enum_info = const_cast(enum_property->payload.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 = 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; + self_property_map.insert(enum_name, Property::create_enum(enum_info)); + property_map.insert(enum_name, Property::create_enum(enum_info)); } } + + Property::IntegerConstant entry{ p_constant, enum_info }; + property_map.insert(p_name, Property::create_integer_constant(entry)); + self_property_map.insert(p_name, Property::create_integer_constant(entry)); } const GDType::EnumInfo *GDType::get_integer_constant_enum(const StringName &p_name, bool p_no_inheritance) const { - for (const KeyValue &kv : get_enum_map(p_no_inheritance)) { - if (kv.value->values.has(p_name)) { - return kv.value; - } + const Property *property = get_property_map(p_no_inheritance).getptr(p_name); + if (!property || property->type != Property::Type::INTEGER_CONSTANT) { + return nullptr; } - - return nullptr; + return property->payload.integer_constant.enum_info; } void GDType::add_signal(MethodInfo p_signal) { @@ -129,15 +126,12 @@ void GDType::add_signal(MethodInfo p_signal) { ERR_FAIL_COND(init_state != InitState::MUTABLE); const StringName signal_name(p_signal.name); - ERR_FAIL_COND_MSG(signal_map.has(signal_name), vformat("Class '%s' already has signal '%s'.", String(name), String(signal_name))); ERR_FAIL_COND_MSG(property_map.has(signal_name), vformat("Object '%s' already has property '%s'.", get_name(), signal_name)); const MethodInfo *ptr = memnew(MethodInfo(std::move(p_signal))); - signal_map[signal_name] = ptr; - self_signal_map[signal_name] = ptr; - property_map.insert(ptr->name, Property(Property::Type::SIGNAL)); - self_property_map.insert(ptr->name, Property(Property::Type::SIGNAL)); + property_map.insert(ptr->name, Property::create_signal(ptr)); + self_property_map.insert(ptr->name, Property::create_signal(ptr)); } bool GDType::bind_method(MethodBind *p_method, bool p_take_ownership) { @@ -151,13 +145,11 @@ bool GDType::bind_method(MethodBind *p_method, bool p_take_ownership) { ERR_FAIL_V_MSG(false, vformat("Object '%s' already has property '%s'.", get_name(), p_method->get_name())); } - method_map[p_method->get_name()] = p_method; - self_method_map[p_method->get_name()] = p_method; if (p_take_ownership) { owned_method_map.push_back(p_method); } - property_map.insert(p_method->get_name(), Property(Property::Type::METHOD)); - self_property_map.insert(p_method->get_name(), Property(Property::Type::METHOD)); + property_map.insert(p_method->get_name(), Property::create_method(p_method)); + self_property_map.insert(p_method->get_name(), Property::create_method(p_method)); return true; } @@ -166,10 +158,11 @@ void GDType::set_method_flags(const StringName &p_method, int p_flags) { ERR_FAIL_COND(!Thread::is_main_thread()); ERR_FAIL_COND(init_state != InitState::MUTABLE); - const MethodBind **method = self_method_map.getptr(p_method); - ERR_FAIL_NULL(method); + const Property *property = self_property_map.getptr(p_method); + ERR_FAIL_NULL(property); + ERR_FAIL_COND(property->type != Property::Type::METHOD); - const_cast(*method)->set_hint_flags(p_flags); + const_cast(property->payload.method)->set_hint_flags(p_flags); } void GDType::add_property(const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, @@ -179,34 +172,40 @@ void GDType::add_property(const PropertyInfo &p_pinfo, const StringName &p_sette ERR_FAIL_COND_MSG(property_map.has(p_pinfo.name), vformat("Object '%s' already has property '%s'.", get_name(), p_pinfo.name)); - const MethodBind *const *mb_set = nullptr; + const MethodBind *mb_set = nullptr; if (p_setter) { - mb_set = get_method_map().getptr(p_setter); + const Property *set_prop = property_map.getptr(p_setter); + + ERR_FAIL_COND_MSG(!set_prop || set_prop->type != Property::Type::METHOD, vformat("Invalid setter '%s::%s' for property '%s'.", get_name(), p_setter, p_pinfo.name)); + + mb_set = set_prop->payload.method; - ERR_FAIL_NULL_MSG(mb_set, vformat("Invalid setter '%s::%s' for property '%s'.", get_name(), p_setter, p_pinfo.name)); int exp_args = 1 + (p_index >= 0 ? 1 : 0); - ERR_FAIL_COND_MSG((*mb_set)->get_argument_count() != exp_args, vformat("Invalid function for setter '%s::%s' for property '%s'.", get_name(), p_setter, p_pinfo.name)); + ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, vformat("Invalid function for setter '%s::%s' for property '%s'.", get_name(), p_setter, p_pinfo.name)); } - const MethodBind *const *mb_get = nullptr; + const MethodBind *mb_get = nullptr; if (p_getter) { - mb_get = get_method_map().getptr(p_getter); + const Property *get_prop = property_map.getptr(p_getter); + + ERR_FAIL_COND_MSG(!get_prop || get_prop->type != Property::Type::METHOD, vformat("Invalid getter '%s::%s' for property '%s'.", get_name(), p_getter, p_pinfo.name)); + + mb_get = get_prop->payload.method; - ERR_FAIL_NULL_MSG(mb_get, vformat("Invalid getter '%s::%s' for property '%s'.", get_name(), p_getter, p_pinfo.name)); int exp_args = 0 + (p_index >= 0 ? 1 : 0); - ERR_FAIL_COND_MSG((*mb_get)->get_argument_count() != exp_args, vformat("Invalid function for getter '%s::%s' for property '%s'.", get_name(), p_getter, p_pinfo.name)); + ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, vformat("Invalid function for getter '%s::%s' for property '%s'.", get_name(), p_getter, p_pinfo.name)); } PropertyInfo *info = memnew(PropertyInfo(p_pinfo)); Property::SetGet psg; psg.property_info = info; - psg.setter = mb_set ? *mb_set : nullptr; - psg.getter = mb_get ? *mb_get : nullptr; + psg.setter = mb_set; + psg.getter = mb_get; psg.index = p_index; - property_map.insert(p_pinfo.name, Property(Property::Type::SETGET, psg)); - self_property_map.insert(p_pinfo.name, Property(Property::Type::SETGET, psg)); + property_map.insert(p_pinfo.name, Property::create_setget(psg)); + self_property_map.insert(p_pinfo.name, Property::create_setget(psg)); ordered_self_properties.push_back(info); } diff --git a/core/object/gdtype.h b/core/object/gdtype.h index 703190b41a5b..43b8310ec043 100644 --- a/core/object/gdtype.h +++ b/core/object/gdtype.h @@ -55,6 +55,7 @@ class GDType { enum class Type { SETGET, INTEGER_CONSTANT, + ENUM, METHOD, SIGNAL }; @@ -66,24 +67,56 @@ class GDType { int index; }; + struct IntegerConstant { + int64_t value; + const EnumInfo *enum_info; + }; + union Payload { - int64_t integer = 0; SetGet setget; + IntegerConstant integer_constant; + const EnumInfo *enum_info; + const MethodBind *method; + const MethodInfo *signal; }; Type type; Payload payload; - Property &operator=(const Property &p) = default; + Property &operator=(const Property &) = default; - Property(const Property &) = default; - Property(Type p_type, const SetGet &p_pointer) : type(p_type) { - payload.setget = p_pointer; + static Property create_setget(const SetGet &p_setget) { + Payload payload; + payload.setget = p_setget; + return Property(Type::SETGET, payload); } - Property(Type p_type, int64_t p_int) : type(p_type) { - payload.integer = p_int; + + static Property create_integer_constant(IntegerConstant p_constant) { + Payload payload; + payload.integer_constant = p_constant; + return Property(Type::INTEGER_CONSTANT, payload); + } + + static Property create_enum(const EnumInfo *p_enum_info) { + Payload payload; + payload.enum_info = p_enum_info; + return Property(Type::ENUM, payload); } - Property(Type p_type) : type(p_type) {} + + static Property create_method(const MethodBind *p_method) { + Payload payload; + payload.method = p_method; + return Property(Type::METHOD, payload); + } + + static Property create_signal(const MethodInfo *p_method) { + Payload payload; + payload.signal = p_method; + return Property(Type::SIGNAL, payload); + } + + Property(const Property &) = default; + Property(Type p_type, const Payload &p_payload) : type(p_type), payload(p_payload) {} }; protected: @@ -95,19 +128,8 @@ class GDType { /// `name` is the first element and `Object` is the last (for `Object` types). Vector name_hierarchy; - AHashMap constant_map; - AHashMap self_constant_map; - - AHashMap enum_map; - AHashMap self_enum_map; - - AHashMap signal_map; - AHashMap self_signal_map; - - AHashMap method_map; - AHashMap self_method_map; - // This is deliberately not the same as self_method_map because - // bind_method supports binding non-owned methods. + /// This needs to be tracked separately because + /// bind_method supports binding non-owned methods. LocalVector owned_method_map; /// Contains all properties that can be obtained or set with `object.property`. @@ -130,20 +152,20 @@ class GDType { } const Vector &get_name_hierarchy() const { return name_hierarchy; } + // Binding void bind_integer_constant(const StringName &p_enum, const StringName &p_name, int64_t p_constant, bool p_is_bitfield = false); - const AHashMap &get_integer_constant_map(bool p_no_inheritance = false) const { return p_no_inheritance ? self_constant_map : constant_map; } - const AHashMap &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; void add_signal(MethodInfo p_signal); - const AHashMap &get_signal_map(bool p_no_inheritance = false) const { return p_no_inheritance ? self_signal_map : signal_map; } bool bind_method(MethodBind *p_method, bool p_take_ownership = true); + void set_method_flags(const StringName &p_method, int p_flags); - const AHashMap &get_method_map(bool p_no_inheritance = false) const { return p_no_inheritance ? self_method_map : method_map; } void add_property(const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index); void add_to_ordered_properties(const PropertyInfo &p_pinfo); - const AHashMap &get_property_map(bool p_no_inheritance = false) const { return p_no_inheritance ? self_property_map : property_map; } const LocalVector &get_ordered_self_properties() const { return ordered_self_properties; } + + // Access + const AHashMap &get_property_map(bool p_no_inheritance = false) const { return p_no_inheritance ? self_property_map : property_map; } + const EnumInfo *get_integer_constant_enum(const StringName &p_name, bool p_no_inheritance = false) const; }; diff --git a/core/object/object.cpp b/core/object/object.cpp index efbca035d260..700768d5e3c3 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -376,7 +376,10 @@ bool Object::set_native(const StringName &p_name, const Variant &p_value, bool * } return true; } - default: { + case GDType::Property::Type::INTEGER_CONSTANT: + case GDType::Property::Type::METHOD: + case GDType::Property::Type::ENUM: + case GDType::Property::Type::SIGNAL: { // All other properties are unsettable. if (r_valid) { *r_valid = false; @@ -426,7 +429,7 @@ bool Object::get_native(const StringName &p_name, Variant &r_value, bool *r_vali if (r_valid) { *r_valid = true; } - r_value = property->payload.integer; + r_value = property->payload.integer_constant.value; return true; } case GDType::Property::Type::METHOD: { @@ -443,6 +446,13 @@ bool Object::get_native(const StringName &p_name, Variant &r_value, bool *r_vali r_value = Signal(this, p_name); return true; } + case GDType::Property::Type::ENUM: { + if (r_valid) { + *r_valid = false; + } + r_value = Variant(); + return true; + } } } @@ -734,7 +744,8 @@ bool Object::has_method(const StringName &p_method) const { return true; } - if (get_gdtype().get_method_map(false).has(p_method)) { + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_method); + if (property != nullptr && property->type == GDType::Property::Type::METHOD) { return true; } @@ -866,11 +877,10 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_ return Variant(); } - Variant ret; OBJ_DEBUG_LOCK if (script_instance) { - ret = script_instance->callp(p_method, p_args, p_argcount, r_error); + Variant ret = script_instance->callp(p_method, p_args, p_argcount, r_error); // Force jump table. switch (r_error.error) { case Callable::CallError::CALL_OK: @@ -889,15 +899,14 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_ //extension does not need this, because all methods are registered in MethodBind - const MethodBind *const *method = get_gdtype().get_method_map(false).getptr(p_method); - - if (method) { - ret = (*method)->call(this, p_args, p_argcount, r_error); - } else { + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_method); + if (!property || property->type != GDType::Property::Type::METHOD) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); } - return ret; + const MethodBind *method = property->payload.method; + return method->call(this, p_args, p_argcount, r_error); } Variant Object::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { @@ -909,11 +918,10 @@ Variant Object::call_const(const StringName &p_method, const Variant **p_args, i return Variant(); } - Variant ret; OBJ_DEBUG_LOCK if (script_instance) { - ret = script_instance->call_const(p_method, p_args, p_argcount, r_error); + Variant ret = script_instance->call_const(p_method, p_args, p_argcount, r_error); //force jumptable switch (r_error.error) { case Callable::CallError::CALL_OK: @@ -933,19 +941,20 @@ Variant Object::call_const(const StringName &p_method, const Variant **p_args, i //extension does not need this, because all methods are registered in MethodBind - const MethodBind *const *method = get_gdtype().get_method_map(false).getptr(p_method); - - if (method) { - if (!(*method)->is_const()) { - r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST; - return ret; - } - ret = (*method)->call(this, p_args, p_argcount, r_error); - } else { + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_method); + if (!property || property->type != GDType::Property::Type::METHOD) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); } - return ret; + const MethodBind *method = property->payload.method; + + if (!method->is_const()) { + r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST; + return Variant(); + } + + return method->call(this, p_args, p_argcount, r_error); } void Object::_gdvirtual_init_method_ptr(uint32_t p_compat_hash, void *&r_fn_ptr, const StringName &p_fn_name, bool p_compat) const { @@ -1174,7 +1183,7 @@ void Object::get_meta_list(List *p_list) const { void Object::add_user_signal(const MethodInfo &p_signal) { ERR_FAIL_COND_MSG(p_signal.name.is_empty(), "Signal name cannot be empty."); - ERR_FAIL_COND_MSG(get_gdtype().get_signal_map(false).has(p_signal.name), vformat("User signal's name conflicts with a built-in signal of '%s'.", get_class_name())); + ERR_FAIL_COND_MSG(get_gdtype().get_property_map().has(p_signal.name), vformat("User signal's name conflicts with a built-in property of '%s'.", get_class_name())); ObjectSignalLock signal_lock(this); @@ -1264,7 +1273,8 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int SignalData *s = signal_map.getptr(p_name); if (!s) { #ifdef DEBUG_ENABLED - bool signal_is_valid = get_gdtype().get_signal_map(false).has(p_name); + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_name); + bool signal_is_valid = property && property->type == GDType::Property::Type::SIGNAL; //check in script ERR_FAIL_COND_V_MSG(!signal_is_valid && script_instance && !script_instance->get_script()->has_script_signal(p_name), ERR_UNAVAILABLE, vformat("Can't emit non-existing signal \"%s\".", p_name)); #endif @@ -1492,7 +1502,8 @@ bool Object::has_signal(const StringName &p_name) const { return true; } - if (get_gdtype().get_signal_map(false).has(p_name)) { + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_name); + if (property && property->type == GDType::Property::Type::SIGNAL) { return true; } @@ -1599,7 +1610,8 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui SignalData *s = signal_map.getptr(p_signal); if (!s) { - bool signal_is_valid = get_gdtype().get_signal_map(false).has(p_signal); + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_signal); + bool signal_is_valid = property && property->type == GDType::Property::Type::SIGNAL; //check in script if (!signal_is_valid && script_instance) { if (script_instance->get_script()->has_script_signal(p_signal)) { @@ -1657,8 +1669,8 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable const SignalData *s = signal_map.getptr(p_signal); if (!s) { - bool signal_is_valid = get_gdtype().get_signal_map(false).has(p_signal); - if (signal_is_valid) { + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_signal); + if (property && property->type == GDType::Property::Type::SIGNAL) { return false; } @@ -1677,8 +1689,8 @@ bool Object::has_connections(const StringName &p_signal) const { const SignalData *s = signal_map.getptr(p_signal); if (!s) { - bool signal_is_valid = get_gdtype().get_signal_map(false).has(p_signal); - if (signal_is_valid) { + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_signal); + if (property && property->type == GDType::Property::Type::SIGNAL) { return false; } @@ -1703,7 +1715,8 @@ bool Object::_disconnect(const StringName &p_signal, const Callable &p_callable, SignalData *s = signal_map.getptr(p_signal); if (!s) { - bool signal_is_valid = get_gdtype().get_signal_map(false).has(p_signal) || + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_signal); + bool signal_is_valid = (property && property->type == GDType::Property::Type::SIGNAL) || (script_instance && script_instance->get_script()->has_script_signal(p_signal)); ERR_FAIL_COND_V_MSG(signal_is_valid, false, vformat("Attempt to disconnect a nonexistent connection from '%s'. Signal: '%s', callable: '%s'.", to_string(), p_signal, p_callable)); } @@ -1726,7 +1739,8 @@ bool Object::_disconnect(const StringName &p_signal, const Callable &p_callable, s->slot_map.erase(*p_callable.get_base_comparator()); - if (s->slot_map.is_empty() && get_gdtype().get_signal_map(false).has(p_signal)) { + const GDType::Property *property = get_gdtype().get_property_map().getptr(p_signal); + if (s->slot_map.is_empty() && property && property->type == GDType::Property::Type::SIGNAL) { //not user signal, delete signal_map.erase(p_signal); } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 408cf499cd6f..e17526ec1b7f 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1222,8 +1222,7 @@ struct _VariantCall { static void add_variant_constant(int p_type, const StringName &p_constant_name, const Variant &p_constant_value) { #ifdef DEBUG_ENABLED ERR_FAIL_COND(variant_constants[p_type].has(p_constant_name)); - ERR_FAIL_COND(Variant::_get_gdtype_for_type(static_cast(p_type)).get_enum_map(true).has(p_constant_name)); - ERR_FAIL_COND(Variant::_get_gdtype_for_type(static_cast(p_type)).get_integer_constant_map(true).has(p_constant_name)); + ERR_FAIL_COND(Variant::_get_gdtype_for_type(static_cast(p_type)).get_property_map(true).has(p_constant_name)); #endif // DEBUG_ENABLED variant_constants[p_type][p_constant_name] = p_constant_value; } @@ -1655,8 +1654,11 @@ void Variant::get_method_list(List *p_list) const { void Variant::get_constants_for_type(Variant::Type p_type, List *p_constants) { ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); - for (const KeyValue &E : _get_gdtype_for_type(p_type).get_integer_constant_map(false)) { - if (_get_gdtype_for_type(p_type).get_integer_constant_enum(E.key, false) == nullptr) { + for (const KeyValue &E : _get_gdtype_for_type(p_type).get_property_map()) { + if (E.value.type != GDType::Property::Type::INTEGER_CONSTANT) { + continue; + } + if (!E.value.payload.integer_constant.enum_info) { p_constants->push_back(E.key); } } @@ -1676,9 +1678,9 @@ int Variant::get_constants_count_for_type(Variant::Type p_type) { bool Variant::has_constant(Variant::Type p_type, const StringName &p_value) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + const GDType::Property *property = _get_gdtype_for_type(p_type).get_property_map().getptr(p_value); const bool is_non_enum_integer_constant = - _get_gdtype_for_type(p_type).get_integer_constant_map(false).has(p_value) && - _get_gdtype_for_type(p_type).get_integer_constant_enum(p_value, false) == nullptr; + property && property->type == GDType::Property::Type::INTEGER_CONSTANT && !property->payload.integer_constant.enum_info; return is_non_enum_integer_constant || _VariantCall::variant_constants[p_type].has(p_value); } @@ -1689,12 +1691,12 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); - const int64_t *int_value = _get_gdtype_for_type(p_type).get_integer_constant_map(false).getptr(p_value); - if (int_value && _get_gdtype_for_type(p_type).get_integer_constant_enum(p_value, false) == nullptr) { + const GDType::Property *property = _get_gdtype_for_type(p_type).get_property_map().getptr(p_value); + if (property && property->type == GDType::Property::Type::INTEGER_CONSTANT && !property->payload.integer_constant.enum_info) { if (r_valid) { *r_valid = true; } - return *int_value; + return property->payload.integer_constant.value; } HashMap::Iterator F = _VariantCall::variant_constants[p_type].find(p_value); @@ -1710,19 +1712,21 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va void Variant::get_enums_for_type(Variant::Type p_type, List *p_enums) { ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); - for (const KeyValue &E : _get_gdtype_for_type(p_type).get_enum_map(false)) { - p_enums->push_back(E.key); + for (const KeyValue &E : _get_gdtype_for_type(p_type).get_property_map()) { + if (E.value.type == GDType::Property::Type::ENUM) { + p_enums->push_back(E.key); + } } } void Variant::get_enumerations_for_enum(Variant::Type p_type, const StringName &p_enum_name, List *p_enumerations) { ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); - const GDType::EnumInfo *const *enum_info = _get_gdtype_for_type(p_type).get_enum_map(false).getptr(p_enum_name); - if (!enum_info) { + const GDType::Property *property = _get_gdtype_for_type(p_type).get_property_map().getptr(p_enum_name); + if (!property || property->type != GDType::Property::Type::ENUM) { return; } - for (const KeyValue &V : (*enum_info)->values) { + for (const KeyValue &V : property->payload.enum_info->values) { p_enumerations->push_back(V.key); } } @@ -1733,12 +1737,12 @@ int Variant::get_enum_value(Variant::Type p_type, const StringName &p_enum_name, } ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); - const GDType::EnumInfo *const *enum_info = _get_gdtype_for_type(p_type).get_enum_map(false).getptr(p_enum_name); - if (!enum_info) { + const GDType::Property *property = _get_gdtype_for_type(p_type).get_property_map().getptr(p_enum_name); + if (!property || property->type != GDType::Property::Type::ENUM) { return -1; } - const int64_t *enum_value = (*enum_info)->values.getptr(p_enumeration); + const int64_t *enum_value = property->payload.enum_info->values.getptr(p_enumeration); if (!enum_value) { return -1; } @@ -1752,7 +1756,8 @@ int Variant::get_enum_value(Variant::Type p_type, const StringName &p_enum_name, bool Variant::has_enum(Variant::Type p_type, const StringName &p_enum_name) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); - return _get_gdtype_for_type(p_type).get_enum_map(false).has(p_enum_name); + const GDType::Property *property = _get_gdtype_for_type(p_type).get_property_map().getptr(p_enum_name); + return property && property->type == GDType::Property::Type::ENUM; } StringName Variant::get_enum_for_enumeration(Variant::Type p_type, const StringName &p_enumeration) { diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index c7670e326467..db8c1bc837ed 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -58,7 +58,10 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List snames; - for (const KeyValue &F : t->gdtype->get_method_map(true)) { + for (const KeyValue &F : t->gdtype->get_property_map(true)) { + if (F.value.type != GDType::Property::Type::METHOD) { + continue; + } String name = F.key.string(); ERR_CONTINUE(name.is_empty()); @@ -78,7 +81,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Dictionary method_dict; methods.push_back(method_dict); - const MethodBind *mb = t->gdtype->get_method_map(true)[F]; + const MethodBind *mb = t->gdtype->get_property_map(true)[F].payload.method; method_dict["name"] = mb->get_name(); method_dict["argument_count"] = mb->get_argument_count(); method_dict["return_type"] = mb->get_argument_type(-1); @@ -121,7 +124,10 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List snames; - for (const KeyValue &F : t->gdtype->get_integer_constant_map(true)) { + for (const KeyValue &F : t->gdtype->get_property_map(true)) { + if (F.value.type != GDType::Property::Type::INTEGER_CONSTANT) { + continue; + } snames.push_back(F.key); } @@ -134,7 +140,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->gdtype->get_integer_constant_map(true)[F]; + constant_dict["value"] = t->gdtype->get_property_map(true)[F].payload.integer_constant.value; } if (!constants.is_empty()) { @@ -146,7 +152,10 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List snames; - for (const KeyValue &F : t->gdtype->get_signal_map(true)) { + for (const KeyValue &F : t->gdtype->get_property_map(true)) { + if (F.value.type != GDType::Property::Type::SIGNAL) { + continue; + } snames.push_back(F.key); } @@ -158,7 +167,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Dictionary signal_dict; signals.push_back(signal_dict); - const MethodInfo &mi = *t->gdtype->get_signal_map(true)[F]; + const MethodInfo &mi = *t->gdtype->get_property_map(true)[F].payload.signal; signal_dict["name"] = F; Array arguments; diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 61fa1665aa4d..d1f52ae401d3 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -4230,12 +4230,15 @@ bool BindingsGenerator::_populate_object_type_interfaces() { // Populate signals - const AHashMap &signal_map = class_info->gdtype->get_signal_map(true); + const AHashMap &property_map = class_info->gdtype->get_property_map(true); - for (const KeyValue &E : signal_map) { + for (const KeyValue &E : property_map) { + if (E.value.type != GDType::Property::Type::SIGNAL) { + continue; + } SignalInterface isignal; - const MethodInfo &method_info = *E.value; + const MethodInfo &method_info = *E.value.payload.signal; if (method_info.name.begins_with("_")) { // Signals starting with an underscore are internal and not meant to be exposed. @@ -4326,9 +4329,10 @@ bool BindingsGenerator::_populate_object_type_interfaces() { List constants; ClassDB::get_integer_constant_list(type_cname, &constants, true); - const AHashMap &enum_map = class_info->gdtype->get_enum_map(true); - - for (const KeyValue &kv : enum_map) { + for (const KeyValue &kv : property_map) { + if (kv.value.type != GDType::Property::Type::ENUM) { + continue; + } StringName enum_proxy_cname = kv.key; String enum_proxy_name = pascal_to_pascal_case(enum_proxy_cname.string()); if (enums_with_forced_suffix.has(itype.proxy_name + "." + enum_proxy_name) || 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)) { @@ -4338,8 +4342,8 @@ 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, kv.value->is_bitfield); - for (const KeyValue &kv_case : kv.value->values) { + EnumInterface ienum(enum_proxy_cname, enum_proxy_name, kv.value.payload.enum_info->is_bitfield); + for (const KeyValue &kv_case : kv.value.payload.enum_info->values) { String constant_name = kv_case.key.string(); constants.erase(kv_case.key); @@ -4384,8 +4388,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() { } for (const String &constant_name : constants) { - const int64_t *value = class_info->gdtype->get_integer_constant_map(true).getptr(StringName(constant_name)); - ERR_FAIL_NULL_V(value, false); + const GDType::Property *property = class_info->gdtype->get_property_map(true).getptr(StringName(constant_name)); + ERR_FAIL_NULL_V(property, false); + int64_t value = property->payload.integer_constant.value; String constant_proxy_name = snake_to_pascal_case(constant_name, true); @@ -4395,7 +4400,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { constant_proxy_name += "Constant"; } - ConstantInterface iconstant(constant_name, constant_proxy_name, *value); + ConstantInterface iconstant(constant_name, constant_proxy_name, value); iconstant.const_doc = nullptr; for (int i = 0; i < itype.class_doc->constants.size(); i++) { diff --git a/tests/core/object/test_class_db.cpp b/tests/core/object/test_class_db.cpp index a247998f8fbb..8eed14b767f3 100644 --- a/tests/core/object/test_class_db.cpp +++ b/tests/core/object/test_class_db.cpp @@ -711,12 +711,15 @@ void add_exposed_classes(Context &r_context) { // Add signals - const AHashMap &signal_map = class_info->gdtype->get_signal_map(true); + const AHashMap &property_map = class_info->gdtype->get_property_map(true); - for (const KeyValue &K : signal_map) { + for (const KeyValue &K : property_map) { + if (K.value.type != GDType::Property::Type::SIGNAL) { + continue; + } SignalData signal; - const MethodInfo &method_info = *signal_map.get(K.key); + const MethodInfo &method_info = *K.value.payload.signal; signal.name = method_info.name; TEST_FAIL_COND(!String(signal.name).is_valid_ascii_identifier(), @@ -764,25 +767,26 @@ void add_exposed_classes(Context &r_context) { List constants; ClassDB::get_integer_constant_list(class_name, &constants, true); - const AHashMap &enum_map = class_info->gdtype->get_enum_map(true); - - for (const KeyValue &kv_enum : enum_map) { + for (const KeyValue &kv_enum : property_map) { + if (kv_enum.value.type != GDType::Property::Type::ENUM) { + continue; + } EnumData enum_; enum_.name = kv_enum.key; - for (const KeyValue &kv_case : kv_enum.value->values) { + for (const KeyValue &kv_case : kv_enum.value.payload.enum_info->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), "'."); - const int64_t *value = class_info->gdtype->get_integer_constant_map(false).getptr(constant_name); - TEST_FAIL_COND(!value, "Missing enum constant value: '", + const GDType::Property *constant_property = property_map.getptr(constant_name); + TEST_FAIL_COND(!constant_property, "Missing enum constant value: '", String(class_name), ".", String(enum_.name), ".", String(constant_name), "'."); constants.erase(constant_name); ConstantData constant; constant.name = constant_name; - constant.value = *value; + constant.value = constant_property->payload.integer_constant.value; enum_.constants.push_back(constant); } @@ -797,12 +801,12 @@ 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, "'."); - 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), "'."); + const GDType::Property *constant_property = property_map.getptr(constant_name); + TEST_FAIL_COND(!constant_property, "Missing constant value: '", String(class_name), ".", String(constant_name), "'."); ConstantData constant; constant.name = constant_name; - constant.value = *value; + constant.value = constant_property->payload.integer_constant.value; exposed_class.constants.push_back(constant); } diff --git a/tests/core/object/test_method_bind.cpp b/tests/core/object/test_method_bind.cpp index bb1d380962ea..5a62b9442fda 100644 --- a/tests/core/object/test_method_bind.cpp +++ b/tests/core/object/test_method_bind.cpp @@ -221,7 +221,7 @@ TEST_CASE("[MethodBind] check all method binds") { } TEST_CASE("[MethodBind] check bound enums") { - const AHashMap &enum_map = MethodBindTester::get_gdtype_static().get_enum_map(); + const AHashMap &property_map = MethodBindTester::get_gdtype_static().get_property_map(); #define BOUND_ENUM_LOOP(m_info, m_value, m_name) \ CHECK(m_info->values.has(#m_name)); \ @@ -229,8 +229,10 @@ TEST_CASE("[MethodBind] check bound enums") { CHECK(static_cast(m_value) == m_info->values[#m_name]); \ } - const GDType::EnumInfo *enum_info_test = enum_map.has("Test") ? enum_map.get("Test") : nullptr; - CHECK(enum_info_test != nullptr); + const GDType::Property *property = property_map.getptr("Test"); + CHECK(property); + CHECK(property->type == GDType::Property::Type::ENUM); + const GDType::EnumInfo *enum_info_test = property->payload.enum_info; if (enum_info_test) { BOUND_ENUM_LOOP(enum_info_test, MethodBindTester::TEST_METHOD, TEST_METHOD) BOUND_ENUM_LOOP(enum_info_test, MethodBindTester::TEST_METHOD_ARGS, TEST_METHOD_ARGS) @@ -245,8 +247,10 @@ TEST_CASE("[MethodBind] check bound enums") { BOUND_ENUM_LOOP(enum_info_test, MethodBindTester::TEST_MAX, TEST_MAX) } - const GDType::EnumInfo *enum_info_test_scoped = enum_map.has("TestScoped") ? enum_map.get("TestScoped") : nullptr; - CHECK(enum_info_test_scoped != nullptr); + const GDType::Property *property_scoped = property_map.getptr("TestScoped"); + CHECK(property_scoped); + CHECK(property_scoped->type == GDType::Property::Type::ENUM); + const GDType::EnumInfo *enum_info_test_scoped = property_scoped->payload.enum_info; if (enum_info_test_scoped) { BOUND_ENUM_LOOP(enum_info_test_scoped, MethodBindTester::TestScoped::METHOD, TEST_SCOPED_METHOD) BOUND_ENUM_LOOP(enum_info_test_scoped, MethodBindTester::TestScoped::METHOD_ARGS, TEST_SCOPED_METHOD_ARGS)