Browse Source

Optimize hotspots with `Object::derives_from`

lawnjelly 1 month ago
parent
commit
aec5bf47dd

+ 1 - 1
core/io/resource_loader.cpp

@@ -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();

+ 1 - 1
core/io/resource_saver.cpp

@@ -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();

+ 1 - 1
core/object.cpp

@@ -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()) {

+ 9 - 8
core/object.h

@@ -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);

+ 1 - 1
core/variant.cpp

@@ -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 {

+ 1 - 1
drivers/png/resource_saver_png.cpp

@@ -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 {

+ 8 - 8
editor/editor_node.cpp

@@ -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;
 	}
 

+ 1 - 1
editor/script_editor_debugger.cpp

@@ -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;

+ 1 - 1
main/main.cpp

@@ -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

+ 1 - 1
scene/3d/collision_shape.cpp

@@ -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";
 			}

+ 2 - 2
scene/resources/visual_shader.cpp

@@ -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;
 				}
 			}