Optimize hotspots with Object::derives_from

This commit is contained in:
lawnjelly 2025-06-23 08:10:43 +01:00
parent 3aaabb6148
commit aec5bf47dd
11 changed files with 27 additions and 26 deletions

View file

@ -909,7 +909,7 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) {
Ref<Resource> res = ResourceLoader::load(script_path);
ERR_FAIL_COND_V(res.is_null(), false);
ERR_FAIL_COND_V(!res->is_class("Script"), false);
ERR_FAIL_COND_V(!res->derives_from<Script>(), false);
Ref<Script> s = res;
StringName ibt = s->get_instance_base_type();

View file

@ -203,7 +203,7 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) {
Ref<Resource> res = ResourceLoader::load(script_path);
ERR_FAIL_COND_V(res.is_null(), false);
ERR_FAIL_COND_V(!res->is_class("Script"), false);
ERR_FAIL_COND_V(!res->derives_from<Script>(), false);
Ref<Script> s = res;
StringName ibt = s->get_instance_base_type();

View file

@ -648,7 +648,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
if (!is_class("Script")) { // can still be set, but this is for userfriendlyness
if (!derives_from<Script>()) { // can still be set, but this is for userfriendlyness
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
if (!metadata.empty()) {

View file

@ -611,6 +611,9 @@ protected:
void _disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, bool p_force = false);
void _define_ancestry(AncestralClass p_class) { _ancestry |= (uint32_t)p_class; }
// Internally used, exposed via `Object::cast_to` and `Object::derives_from`.
bool _has_ancestry(AncestralClass p_class) const { return _ancestry & (uint32_t)p_class; }
public: //should be protected, but bug in clang++
static void initialize_class();
_FORCE_INLINE_ static void register_custom_data_to_otdb(){};
@ -643,12 +646,12 @@ public:
template <class T>
static T *cast_to(Object *p_object) {
return p_object && p_object->_is_class<T>() ? static_cast<T *>(p_object) : nullptr;
return p_object && p_object->derives_from<T>() ? static_cast<T *>(p_object) : nullptr;
}
template <class T>
static const T *cast_to(const Object *p_object) {
return p_object && p_object->_is_class<T>() ? static_cast<const T *>(p_object) : nullptr;
return p_object && p_object->derives_from<T>() ? static_cast<const T *>(p_object) : nullptr;
}
enum {
@ -670,10 +673,8 @@ public:
virtual bool is_class(const String &p_class) const { return (p_class == "Object"); }
virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
bool has_ancestry(AncestralClass p_class) const { return _ancestry & (uint32_t)p_class; }
template <typename T>
bool _is_class() const;
bool derives_from() const;
_FORCE_INLINE_ const StringName &get_class_name() const {
if (!_class_ptr) {
@ -788,20 +789,20 @@ public:
};
template <typename T>
bool Object::_is_class() const {
bool Object::derives_from() const {
static_assert(std::is_base_of<Object, T>::value, "T must be derived from Object");
static_assert(std::is_same<std::decay_t<T>, typename T::self_type>::value, "T must use GDCLASS or GDSOFTCLASS");
// If there is an explicitly set ancestral class on the type, we can use that.
if (T::static_ancestral_class != T::super_type::static_ancestral_class) {
return has_ancestry(T::static_ancestral_class);
return _has_ancestry(T::static_ancestral_class);
} else {
return is_class_ptr(T::get_class_ptr_static());
}
}
template <>
inline bool Object::_is_class<Object>() const { return true; }
inline bool Object::derives_from<Object>() const { return true; }
bool predelete_handler(Object *p_object);
void postinitialize_handler(Object *p_object);

View file

@ -2161,7 +2161,7 @@ Variant::Variant(const Object *p_object) {
memnew_placement(_data._mem, ObjData);
if (obj && obj->has_ancestry(Object::AncestralClass::REFERENCE)) {
if (Object::cast_to<Reference>(obj)) {
*reinterpret_cast<Ref<Reference> *>(_get_obj().ref.get_data()) = Ref<Reference>((Reference *)obj);
_get_obj().rc = nullptr;
} else {

View file

@ -77,7 +77,7 @@ PoolVector<uint8_t> ResourceSaverPNG::save_image_to_buffer(const Ref<Image> &p_i
}
bool ResourceSaverPNG::recognize(const RES &p_resource) const {
return (p_resource.is_valid() && p_resource->is_class("ImageTexture"));
return (p_resource.is_valid() && p_resource->derives_from<ImageTexture>());
}
void ResourceSaverPNG::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {

View file

@ -1330,13 +1330,13 @@ void EditorNode::_save_edited_subresources(Node *scene, Map<RES, bool> &processe
}
void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) {
if (p_node->is_class("Viewport") || (p_node != editor_data.get_edited_scene_root() && p_node->get_owner() != editor_data.get_edited_scene_root())) {
if (p_node->derives_from<Viewport>() || (p_node != editor_data.get_edited_scene_root() && p_node->get_owner() != editor_data.get_edited_scene_root())) {
return;
}
if (p_node->is_class("CanvasItem")) {
if (p_node->derives_from<CanvasItem>()) {
count_2d++;
} else if (p_node->is_class("Spatial")) {
} else if (p_node->derives_from<Spatial>()) {
count_3d++;
}
@ -2051,8 +2051,8 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
Object *prev_inspected_object = get_inspector()->get_edited_object();
bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding"));
bool is_resource = current_obj->is_class("Resource");
bool is_node = current_obj->is_class("Node");
bool is_resource = current_obj->derives_from<Resource>();
bool is_node = current_obj->derives_from<Node>();
bool stay_in_script_editor_on_node_selected = bool(EDITOR_GET("text_editor/navigation/stay_in_script_editor_on_node_selected"));
bool skip_main_plugin = false;
@ -2113,7 +2113,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) {
editable_warning = TTR("This is a remote object, so changes to it won't be kept.\nPlease read the documentation relevant to debugging to better understand this workflow.");
disable_folding = true;
} else if (current_obj->is_class("MultiNodeEdit")) {
} else if (current_obj->derives_from<MultiNodeEdit>()) {
Node *scene = get_edited_scene();
if (scene) {
MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(current_obj);
@ -4037,7 +4037,7 @@ StringName EditorNode::get_object_custom_type_name(const Object *p_object) const
ERR_FAIL_COND_V(!p_object, StringName());
Ref<Script> script = p_object->get_script();
if (script.is_null() && p_object->is_class("Script")) {
if (script.is_null() && p_object->derives_from<Script>()) {
script = p_object;
}
@ -4103,7 +4103,7 @@ Ref<Texture> EditorNode::get_object_icon(const Object *p_object, const String &p
ERR_FAIL_COND_V(!p_object || !gui_base, nullptr);
Ref<Script> script = p_object->get_script();
if (script.is_null() && p_object->is_class("Script")) {
if (script.is_null() && p_object->derives_from<Script>()) {
script = p_object;
}

View file

@ -656,7 +656,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
}
}
} else if (var.get_type() == Variant::OBJECT) {
if (((Object *)var)->is_class("EncodedObjectAsID")) {
if (((Object *)var)->derives_from<EncodedObjectAsID>()) {
var = Object::cast_to<EncodedObjectAsID>(var)->get_object_id();
pinfo.type = var.get_type();
pinfo.hint = PROPERTY_HINT_OBJECT_ID;

View file

@ -1944,7 +1944,7 @@ bool Main::start() {
}
}
if (main_loop->is_class("SceneTree")) {
if (main_loop->derives_from<SceneTree>()) {
SceneTree *sml = Object::cast_to<SceneTree>(main_loop);
#ifdef DEBUG_ENABLED

View file

@ -121,7 +121,7 @@ String CollisionShape::get_configuration_warning() const {
}
warning += TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it.");
} else {
if (shape->is_class("PlaneShape")) {
if (shape->derives_from<PlaneShape>()) {
if (warning != String()) {
warning += "\n\n";
}

View file

@ -671,7 +671,7 @@ void VisualShader::set_mode(Mode p_mode) {
keep = false;
} else {
Ref<VisualShaderNode> from_node = graph[i].nodes[from].node;
if (from_node->is_class("VisualShaderNodeOutput") || from_node->is_class("VisualShaderNodeInput")) {
if (from_node->derives_from<VisualShaderNodeOutput>() || from_node->derives_from<VisualShaderNodeInput>()) {
keep = false;
}
}
@ -680,7 +680,7 @@ void VisualShader::set_mode(Mode p_mode) {
keep = false;
} else {
Ref<VisualShaderNode> to_node = graph[i].nodes[to].node;
if (to_node->is_class("VisualShaderNodeOutput") || to_node->is_class("VisualShaderNodeInput")) {
if (to_node->derives_from<VisualShaderNodeOutput>() || to_node->derives_from<VisualShaderNodeInput>()) {
keep = false;
}
}