diff options
Diffstat (limited to 'editor/scene_tree_dock.cpp')
| -rw-r--r-- | editor/scene_tree_dock.cpp | 144 |
1 files changed, 128 insertions, 16 deletions
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index d8f1d92e44..7e5d85e1a8 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -482,6 +482,20 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { ERR_CONTINUE(!dup); + // Preserve ownership relations ready for pasting. + List<Node *> owned; + node->get_owned_by(node->get_owner(), &owned); + + for (Node *F : owned) { + if (!duplimap.has(F) || F == node) { + continue; + } + Node *d = duplimap[F]; + // Only use this as a marker that ownership needs to be assigned when pasting. + // The actual owner doesn't matter. + d->set_owner(dup); + } + node_clipboard.push_back(dup); } @@ -1264,13 +1278,6 @@ void SceneTreeDock::_notification(int p_what) { spatial_editor_plugin->get_spatial_editor()->connect("item_lock_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false)); spatial_editor_plugin->get_spatial_editor()->connect("item_group_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false)); - button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - button_instance->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); - button_create_script->set_icon(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons"))); - button_detach_script->set_icon(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons"))); - button_tree_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); - - filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); filter->set_clear_button_enabled(true); // create_root_dialog @@ -1352,19 +1359,35 @@ void SceneTreeDock::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { scene_tree->set_auto_expand_selected(EDITOR_GET("docks/scene_tree/auto_expand_to_selected"), false); + } break; + + case NOTIFICATION_THEME_CHANGED: { button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); button_instance->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); button_create_script->set_icon(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons"))); button_detach_script->set_icon(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons"))); button_tree_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); - button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons"))); - button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons"))); - button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons"))); - button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - button_clipboard->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons"))); filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - filter->set_clear_button_enabled(true); + + // These buttons are created on READY, because reasons... + if (button_2d) { + button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons"))); + } + if (button_3d) { + button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons"))); + } + if (button_ui) { + button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons"))); + } + if (button_custom) { + button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + } + if (button_clipboard) { + button_clipboard->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons"))); + } + + menu_subresources->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), SNAME("Editor"))); } break; case NOTIFICATION_PROCESS: { @@ -2725,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); @@ -2950,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() { @@ -3239,7 +3268,8 @@ List<Node *> SceneTreeDock::paste_nodes() { for (KeyValue<const Node *, Node *> &E2 : duplimap) { Node *d = E2.value; - if (d != dup) { + // When copying, all nodes that should have an owner assigned here were given node as an owner. + if (d != dup && E2.key->get_owner() == node) { ur->add_do_method(d, "set_owner", owner); } } @@ -3457,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); |
