Skip to content

Commit

Permalink
Add a list of all sub-resources used in the scene
Browse files Browse the repository at this point in the history
  • Loading branch information
KoBeWi committed Apr 5, 2023
1 parent ef02571 commit 5a99304
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 3 deletions.
92 changes: 90 additions & 2 deletions editor/scene_tree_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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);

Expand Down
5 changes: 4 additions & 1 deletion editor/scene_tree_dock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 5a99304

Please sign in to comment.