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); Ref<Resource> res = ResourceLoader::load(script_path);
ERR_FAIL_COND_V(res.is_null(), false); 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; Ref<Script> s = res;
StringName ibt = s->get_instance_base_type(); 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); Ref<Resource> res = ResourceLoader::load(script_path);
ERR_FAIL_COND_V(res.is_null(), false); 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; Ref<Script> s = res;
StringName ibt = s->get_instance_base_type(); 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); _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)); p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
} }
if (!metadata.empty()) { 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 _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; } 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++ public: //should be protected, but bug in clang++
static void initialize_class(); static void initialize_class();
_FORCE_INLINE_ static void register_custom_data_to_otdb(){}; _FORCE_INLINE_ static void register_custom_data_to_otdb(){};
@ -643,12 +646,12 @@ public:
template <class T> template <class T>
static T *cast_to(Object *p_object) { 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> template <class T>
static const T *cast_to(const Object *p_object) { 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 { enum {
@ -670,10 +673,8 @@ public:
virtual bool is_class(const String &p_class) const { return (p_class == "Object"); } 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; } 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> template <typename T>
bool _is_class() const; bool derives_from() const;
_FORCE_INLINE_ const StringName &get_class_name() const { _FORCE_INLINE_ const StringName &get_class_name() const {
if (!_class_ptr) { if (!_class_ptr) {
@ -788,20 +789,20 @@ public:
}; };
template <typename T> 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_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"); 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 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) { 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 { } else {
return is_class_ptr(T::get_class_ptr_static()); return is_class_ptr(T::get_class_ptr_static());
} }
} }
template <> 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); bool predelete_handler(Object *p_object);
void postinitialize_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); 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); *reinterpret_cast<Ref<Reference> *>(_get_obj().ref.get_data()) = Ref<Reference>((Reference *)obj);
_get_obj().rc = nullptr; _get_obj().rc = nullptr;
} else { } 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 { 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 { 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) { 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; return;
} }
if (p_node->is_class("CanvasItem")) { if (p_node->derives_from<CanvasItem>()) {
count_2d++; count_2d++;
} else if (p_node->is_class("Spatial")) { } else if (p_node->derives_from<Spatial>()) {
count_3d++; count_3d++;
} }
@ -2051,8 +2051,8 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
Object *prev_inspected_object = get_inspector()->get_edited_object(); Object *prev_inspected_object = get_inspector()->get_edited_object();
bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding")); bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding"));
bool is_resource = current_obj->is_class("Resource"); bool is_resource = current_obj->derives_from<Resource>();
bool is_node = current_obj->is_class("Node"); 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 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; bool skip_main_plugin = false;
@ -2113,7 +2113,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) { 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."); 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; disable_folding = true;
} else if (current_obj->is_class("MultiNodeEdit")) { } else if (current_obj->derives_from<MultiNodeEdit>()) {
Node *scene = get_edited_scene(); Node *scene = get_edited_scene();
if (scene) { if (scene) {
MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(current_obj); 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()); ERR_FAIL_COND_V(!p_object, StringName());
Ref<Script> script = p_object->get_script(); 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; 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); ERR_FAIL_COND_V(!p_object || !gui_base, nullptr);
Ref<Script> script = p_object->get_script(); 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; 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) { } 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(); var = Object::cast_to<EncodedObjectAsID>(var)->get_object_id();
pinfo.type = var.get_type(); pinfo.type = var.get_type();
pinfo.hint = PROPERTY_HINT_OBJECT_ID; 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); SceneTree *sml = Object::cast_to<SceneTree>(main_loop);
#ifdef DEBUG_ENABLED #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."); warning += TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it.");
} else { } else {
if (shape->is_class("PlaneShape")) { if (shape->derives_from<PlaneShape>()) {
if (warning != String()) { if (warning != String()) {
warning += "\n\n"; warning += "\n\n";
} }

View file

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