diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 2fd783102cc..7e5d85e1a8f 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2748,9 +2748,8 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) { if (menu->get_item_count() == 0) { menu->add_submenu_item(TTR("Sub-Resources"), "Sub-Resources"); } - int index = menu_subresources->get_item_count(); menu_subresources->add_icon_item(icon, E.name.capitalize(), EDIT_SUBRESOURCE_BASE + subresources.size()); - menu_subresources->set_item_indent(index, p_depth); + menu_subresources->set_item_indent(-1, p_depth); subresources.push_back(obj->get_instance_id()); _add_children_to_popup(obj, p_depth + 1); @@ -2973,6 +2972,13 @@ void SceneTreeDock::_update_tree_menu() { tree_menu->add_separator(); tree_menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND); tree_menu->set_item_checked(tree_menu->get_item_index(TOOL_AUTO_EXPAND), EDITOR_GET("docks/scene_tree/auto_expand_to_selected")); + + PopupMenu *resource_list = memnew(PopupMenu); + resource_list->set_name("AllResources"); + resource_list->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_list_all_subresources).bind(resource_list)); + resource_list->connect("index_pressed", callable_mp(this, &SceneTreeDock::_edit_subresource).bind(resource_list)); + tree_menu->add_child(resource_list); + tree_menu->add_submenu_item(TTR("All Scene Sub-Resources"), "AllResources"); } void SceneTreeDock::_update_filter_menu() { @@ -3481,6 +3487,88 @@ void SceneTreeDock::_create_remap_for_resource(Ref p_resource, HashMap } } +void SceneTreeDock::_list_all_subresources(PopupMenu *p_menu) { + p_menu->clear(); + + List, Node *>> all_resources; + if (edited_scene) { + _gather_resources(edited_scene, all_resources); + } + + HashMap, Node *>>> resources_by_type; + HashMap, int> unique_resources; + + for (const Pair, Node *> &pair : all_resources) { + if (!unique_resources.has(pair.first)) { + resources_by_type[pair.first->get_class()].push_back(pair); + } + unique_resources[pair.first]++; + } + + for (KeyValue, Node *>>> kv : resources_by_type) { + p_menu->add_icon_item(EditorNode::get_singleton()->get_class_icon(kv.key), kv.key); + p_menu->set_item_as_separator(-1, true); + + for (const Pair, Node *> &pair : kv.value) { + String display_text; + if (pair.first->get_name().is_empty()) { + display_text = vformat(TTR(" at %s"), pair.second->get_name()); + } else { + display_text = pair.first->get_name(); + } + + if (unique_resources[pair.first] > 1) { + display_text += " " + vformat(TTR("(used %d times)"), unique_resources[pair.first]); + } + + p_menu->add_item(display_text); + p_menu->set_item_metadata(-1, pair.first->get_instance_id()); + } + } +} + +void SceneTreeDock::_gather_resources(Node *p_node, List, Node *>> &r_resources) { + if (p_node != edited_scene && p_node->get_owner() != edited_scene) { + return; + } + + List pinfo; + p_node->get_property_list(&pinfo); + for (const PropertyInfo &E : pinfo) { + if (!(E.usage & PROPERTY_USAGE_EDITOR)) { + continue; + } + if (E.hint != PROPERTY_HINT_RESOURCE_TYPE) { + continue; + } + + Variant value = p_node->get(E.name); + if (value.get_type() != Variant::OBJECT) { + continue; + } + Ref res = value; + if (res.is_null()) { + continue; + } + + const Pair, Node *> pair(res, p_node); + r_resources.push_back(pair); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _gather_resources(p_node->get_child(i), r_resources); + } +} + +void SceneTreeDock::_edit_subresource(int p_idx, const PopupMenu *p_from_menu) { + const ObjectID &id = p_from_menu->get_item_metadata(p_idx); + + Object *obj = ObjectDB::get_instance(id); + ERR_FAIL_COND(!obj); + + _push_item(obj); +} + void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_owners"), &SceneTreeDock::_set_owners); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 961ae06da56..52a7d6d6c1c 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -77,7 +77,6 @@ class SceneTreeDock : public VBoxContainer { TOOL_MULTI_EDIT, TOOL_ERASE, TOOL_COPY_NODE_PATH, - TOOL_BUTTON_MAX, TOOL_OPEN_DOCUMENTATION, TOOL_AUTO_EXPAND, TOOL_SCENE_EDITABLE_CHILDREN, @@ -267,6 +266,10 @@ class SceneTreeDock : public VBoxContainer { void _create_remap_for_node(Node *p_node, HashMap, Ref> &r_remap); void _create_remap_for_resource(Ref p_resource, HashMap, Ref> &r_remap); + void _list_all_subresources(PopupMenu *p_menu); + void _gather_resources(Node *p_node, List, Node *>> &r_resources); + void _edit_subresource(int p_idx, const PopupMenu *p_from_menu); + bool profile_allow_editing = true; bool profile_allow_script_editing = true;