From 4680ced5faf403ab779b7f841b1f246f7a2c5fab Mon Sep 17 00:00:00 2001 From: jsjtxietian Date: Tue, 14 Nov 2023 13:00:41 +0800 Subject: [PATCH] support updating tooltip after editor description change --- doc/classes/Node.xml | 6 +++ editor/gui/scene_tree_editor.cpp | 76 +++++++++++++++++++++----------- editor/gui/scene_tree_editor.h | 5 +++ scene/main/node.cpp | 7 +-- 4 files changed, 63 insertions(+), 31 deletions(-) diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 0ace4357fa3..73d3698f1f0 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -940,6 +940,12 @@ Emitted when the list of children is changed. This happens when child nodes are added, moved or removed. + + + + Emitted when the node's editor description field changed. + + Emitted when the node is ready. Comes after [method _ready] callback and follows the same rules. diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp index 056e4f8d9d5..b4ac328eacf 100644 --- a/editor/gui/scene_tree_editor.cpp +++ b/editor/gui/scene_tree_editor.cpp @@ -361,33 +361,12 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } { - // Display the node name in all tooltips so that long node names can be previewed - // without having to rename them. - String tooltip = String(p_node->get_name()); - - if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) { - item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - tooltip += String("\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path()); - } else if (p_node != get_scene_node() && !p_node->get_scene_file_path().is_empty() && can_open_instance) { - item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - tooltip += String("\n" + TTR("Instance:") + " " + p_node->get_scene_file_path()); + _update_node_tooltip(p_node, item); + Callable delay_update_tooltip = callable_mp(this, &SceneTreeEditor::_queue_update_node_tooltip); + if (p_node->is_connected("editor_description_changed", delay_update_tooltip)) { + p_node->disconnect("editor_description_changed", delay_update_tooltip); } - - StringName custom_type = EditorNode::get_singleton()->get_object_custom_type_name(p_node); - tooltip += String("\n" + TTR("Type:") + " " + (custom_type != StringName() ? String(custom_type) : p_node->get_class())); - - if (!p_node->get_editor_description().is_empty()) { - const PackedInt32Array boundaries = TS->string_get_word_breaks(p_node->get_editor_description(), "", 80); - tooltip += "\n"; - - for (int i = 0; i < boundaries.size(); i += 2) { - const int start = boundaries[i]; - const int end = boundaries[i + 1]; - tooltip += "\n" + p_node->get_editor_description().substr(start, end - start + 1).rstrip("\n"); - } - } - - item->set_tooltip_text(0, tooltip); + p_node->connect("editor_description_changed", delay_update_tooltip.bind(item)); } if (can_open_instance && is_scene_tree_dock) { // Show buttons only when necessary (SceneTreeDock) to avoid crashes. @@ -508,6 +487,46 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } } +void SceneTreeEditor::_queue_update_node_tooltip(Node *p_node, TreeItem *p_item) { + Callable update_tooltip = callable_mp(this, &SceneTreeEditor::_update_node_tooltip); + if (update_node_tooltip_delay->is_connected("timeout", update_tooltip)) { + update_node_tooltip_delay->disconnect("timeout", update_tooltip); + } + + update_node_tooltip_delay->connect("timeout", update_tooltip.bind(p_node, p_item)); + update_node_tooltip_delay->start(); +} + +void SceneTreeEditor::_update_node_tooltip(Node *p_node, TreeItem *p_item) { + // Display the node name in all tooltips so that long node names can be previewed + // without having to rename them. + String tooltip = p_node->get_name(); + + if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) { + p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); + tooltip += String("\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path()); + } else if (p_node != get_scene_node() && !p_node->get_scene_file_path().is_empty() && can_open_instance) { + p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); + tooltip += String("\n" + TTR("Instance:") + " " + p_node->get_scene_file_path()); + } + + StringName custom_type = EditorNode::get_singleton()->get_object_custom_type_name(p_node); + tooltip += "\n" + TTR("Type:") + " " + (custom_type != StringName() ? String(custom_type) : p_node->get_class()); + + if (!p_node->get_editor_description().is_empty()) { + const PackedInt32Array boundaries = TS->string_get_word_breaks(p_node->get_editor_description(), "", 80); + tooltip += "\n"; + + for (int i = 0; i < boundaries.size(); i += 2) { + const int start = boundaries[i]; + const int end = boundaries[i + 1]; + tooltip += "\n" + p_node->get_editor_description().substr(start, end - start + 1).rstrip("\n"); + } + } + + p_item->set_tooltip_text(0, tooltip); +} + void SceneTreeEditor::_node_visibility_changed(Node *p_node) { if (!p_node || (p_node != get_scene_node() && !p_node->get_owner())) { return; @@ -1504,6 +1523,11 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope update_timer->set_wait_time(0.5); add_child(update_timer); + update_node_tooltip_delay = memnew(Timer); + update_node_tooltip_delay->set_wait_time(0.5); + update_node_tooltip_delay->set_one_shot(true); + add_child(update_node_tooltip_delay); + script_types = memnew(List); ClassDB::get_inheriters_from_class("Script", script_types); } diff --git a/editor/gui/scene_tree_editor.h b/editor/gui/scene_tree_editor.h index 0df0c3a1c32..c377efda541 100644 --- a/editor/gui/scene_tree_editor.h +++ b/editor/gui/scene_tree_editor.h @@ -37,6 +37,7 @@ class EditorSelection; class TextureRect; +class Timer; class SceneTreeEditor : public Control { GDCLASS(SceneTreeEditor, Control); @@ -108,6 +109,8 @@ class SceneTreeEditor : public Control { bool display_foreign = false; bool tree_dirty = true; bool pending_test_update = false; + Timer *update_node_tooltip_delay = nullptr; + static void _bind_methods(); void _cell_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); @@ -118,6 +121,8 @@ class SceneTreeEditor : public Control { void _node_visibility_changed(Node *p_node); void _update_visibility_color(Node *p_node, TreeItem *p_item); void _set_item_custom_color(TreeItem *p_item, Color p_color); + void _update_node_tooltip(Node *p_node, TreeItem *p_item); + void _queue_update_node_tooltip(Node *p_node, TreeItem *p_item); void _selection_changed(); Node *get_scene_node(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index e730f47607e..8978af331ca 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2298,11 +2298,7 @@ void Node::set_editor_description(const String &p_editor_description) { } data.editor_description = p_editor_description; - - if (Engine::get_singleton()->is_editor_hint() && is_inside_tree()) { - // Update tree so the tooltip in the Scene tree dock is also updated in the editor. - get_tree()->tree_changed(); - } + emit_signal(SNAME("editor_description_changed"), this); } String Node::get_editor_description() const { @@ -3500,6 +3496,7 @@ void Node::_bind_methods() { ADD_SIGNAL(MethodInfo("child_order_changed")); ADD_SIGNAL(MethodInfo("replacing_by", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node"))); + ADD_SIGNAL(MethodInfo("editor_description_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node"))); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_name", "get_name"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "unique_name_in_owner", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_unique_name_in_owner", "is_unique_name_in_owner");