From 13e1941f87a222330bdca8fe54c60d20cc5bba1b Mon Sep 17 00:00:00 2001 From: Marius Hanl Date: Fri, 18 Nov 2022 21:20:36 +0100 Subject: [PATCH] Fix Tooltips do not work properly when selecting multiple nodes (MultiNodeEdit) The editor inspector will now get the edited class name from the MultiNodeEdit when it is used. The name of the selected nodes is searched in the scene and if not found in the parent class(es). This is a mostly clean backport from Godot 4.0. --- editor/editor_inspector.cpp | 3 +++ editor/multi_node_edit.cpp | 54 +++++++++++++++++++++++++++++++++++++ editor/multi_node_edit.h | 1 + 3 files changed, 58 insertions(+) diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 6c9465876..3c4182252 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1628,7 +1628,10 @@ void EditorInspector::update_tree() { StringName classname = object->get_class_name(); if (object_class != String()) { classname = object_class; + } else if (Object::cast_to(object)) { + classname = Object::cast_to(object)->get_edited_class_name(); } + StringName propname = property_prefix + p.name; String descr; bool found = false; diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index 0a48fdba3..3814bb06f 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -202,6 +202,60 @@ NodePath MultiNodeEdit::get_node(int p_index) const { return nodes[p_index]; } +StringName MultiNodeEdit::get_edited_class_name() const { + Node *es = EditorNode::get_singleton()->get_edited_scene(); + if (!es) { + return StringName("Node"); + } + + // Get the class name of the first node. + StringName class_name; + for (const List::Element *E = nodes.front(); E; E = E->next()) { + Node *node = es->get_node_or_null(E->get()); + if (!node) { + continue; + } + + class_name = node->get_class_name(); + break; + } + + if (class_name == StringName()) { + return StringName("Node"); + } + + bool check_again = true; + while (check_again) { + check_again = false; + + if (class_name == StringName("Node") || class_name == StringName()) { + // All nodes inherit from Node, so no need to continue checking. + return StringName("Node"); + } + + // Check that all nodes inherit from class_name. + for (const List::Element *E = nodes.front(); E; E = E->next()) { + Node *node = es->get_node_or_null(E->get()); + if (!node) { + continue; + } + + const StringName node_class_name = node->get_class_name(); + if (class_name == node_class_name || ClassDB::is_parent_class(node_class_name, class_name)) { + // class_name is the same or a parent of the node's class. + continue; + } + + // class_name is not a parent of the node's class, so check again with the parent class. + class_name = ClassDB::get_parent_class(class_name); + check_again = true; + break; + } + } + + return class_name; +} + void MultiNodeEdit::set_property_field(const StringName &p_property, const Variant &p_value, const String &p_field) { _set_impl(p_property, p_value, p_field); } diff --git a/editor/multi_node_edit.h b/editor/multi_node_edit.h index 18a70934d..06df70033 100644 --- a/editor/multi_node_edit.h +++ b/editor/multi_node_edit.h @@ -58,6 +58,7 @@ public: int get_node_count() const; NodePath get_node(int p_index) const; + StringName get_edited_class_name() const; void set_property_field(const StringName &p_property, const Variant &p_value, const String &p_field);