Add a list of all sub-resources used in the scene

This commit is contained in:
kobewi 2023-04-04 15:59:50 +02:00
parent ef025711a6
commit 5a99304251
2 changed files with 94 additions and 3 deletions

View File

@ -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<Resource> p_resource, HashMap
}
}
void SceneTreeDock::_list_all_subresources(PopupMenu *p_menu) {
p_menu->clear();
List<Pair<Ref<Resource>, Node *>> all_resources;
if (edited_scene) {
_gather_resources(edited_scene, all_resources);
}
HashMap<String, List<Pair<Ref<Resource>, Node *>>> resources_by_type;
HashMap<Ref<Resource>, int> unique_resources;
for (const Pair<Ref<Resource>, 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<String, List<Pair<Ref<Resource>, 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<Ref<Resource>, Node *> &pair : kv.value) {
String display_text;
if (pair.first->get_name().is_empty()) {
display_text = vformat(TTR("<Unnamed> 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<Pair<Ref<Resource>, Node *>> &r_resources) {
if (p_node != edited_scene && p_node->get_owner() != edited_scene) {
return;
}
List<PropertyInfo> 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<Resource> res = value;
if (res.is_null()) {
continue;
}
const Pair<Ref<Resource>, 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);

View File

@ -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<Resource>, Ref<Resource>> &r_remap);
void _create_remap_for_resource(Ref<Resource> p_resource, HashMap<Ref<Resource>, Ref<Resource>> &r_remap);
void _list_all_subresources(PopupMenu *p_menu);
void _gather_resources(Node *p_node, List<Pair<Ref<Resource>, 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;