diff options
Diffstat (limited to 'editor/scene_tree_dock.cpp')
-rw-r--r-- | editor/scene_tree_dock.cpp | 245 |
1 files changed, 150 insertions, 95 deletions
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 7e72777da1..cece787bf3 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -361,8 +361,12 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { tree->edit_selected(); } } break; - case TOOL_NEW: - case TOOL_REPARENT_TO_NEW_NODE: { + case TOOL_REPARENT_TO_NEW_NODE: + if (!_validate_no_foreign()) { + break; + } + [[fallthrough]]; + case TOOL_NEW: { if (!profile_allow_editing) { break; } @@ -441,8 +445,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } + bool was_empty = false; if (!node_clipboard.is_empty()) { _clear_clipboard(); + } else { + was_empty = true; } clipboard_source_scene = editor->get_edited_scene()->get_scene_file_path(); @@ -460,81 +467,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (p_tool == TOOL_CUT) { _delete_confirm(true); } - } break; - case TOOL_PASTE: { - if (node_clipboard.is_empty() || !edited_scene) { - break; - } - - bool has_cycle = false; - if (!edited_scene->get_scene_file_path().is_empty()) { - for (Node *E : node_clipboard) { - if (edited_scene->get_scene_file_path() == E->get_scene_file_path()) { - has_cycle = true; - break; - } - } - } - - if (has_cycle) { - current_option = -1; - accept->set_text(TTR("Can't paste root node into the same scene.")); - accept->popup_centered(); - break; - } - - Node *paste_parent = edited_scene; - List<Node *> selection = editor_selection->get_selected_node_list(); - if (selection.size() > 0) { - paste_parent = selection.back()->get(); - } - - Node *owner = paste_parent->get_owner(); - if (!owner) { - owner = paste_parent; - } - - editor_data->get_undo_redo().create_action(TTR("Paste Node(s)")); - editor_data->get_undo_redo().add_do_method(editor_selection, "clear"); - - Map<RES, RES> resource_remap; - String target_scene = editor->get_edited_scene()->get_scene_file_path(); - if (target_scene != clipboard_source_scene) { - if (!clipboard_resource_remap.has(target_scene)) { - Map<RES, RES> remap; - for (Node *E : node_clipboard) { - _create_remap_for_node(E, remap); - } - clipboard_resource_remap[target_scene] = remap; - } - resource_remap = clipboard_resource_remap[target_scene]; - } - - for (Node *node : node_clipboard) { - Map<const Node *, Node *> duplimap; - - Node *dup = node->duplicate_from_editor(duplimap, resource_remap); - ERR_CONTINUE(!dup); - - editor_data->get_undo_redo().add_do_method(paste_parent, "add_child", dup, true); - - for (KeyValue<const Node *, Node *> &E2 : duplimap) { - Node *d = E2.value; - editor_data->get_undo_redo().add_do_method(d, "set_owner", owner); - } - - editor_data->get_undo_redo().add_do_method(dup, "set_owner", owner); - editor_data->get_undo_redo().add_do_method(editor_selection, "add_node", dup); - editor_data->get_undo_redo().add_undo_method(paste_parent, "remove_child", dup); - editor_data->get_undo_redo().add_do_reference(dup); - - if (node_clipboard.size() == 1) { - editor_data->get_undo_redo().add_do_method(editor, "push_item", dup); - } + if (was_empty) { + _update_create_root_dialog(); } - - editor_data->get_undo_redo().commit_action(); + } break; + case TOOL_PASTE: { + paste_nodes(); } break; case TOOL_REPLACE: { if (!profile_allow_editing) { @@ -1104,7 +1043,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (node) { node->set_scene_inherited_state(Ref<SceneState>()); scene_tree->update_tree(); - EditorNode::get_singleton()->get_inspector()->update_tree(); + InspectorDock::get_inspector_singleton()->update_tree(); } } } break; @@ -1302,6 +1241,12 @@ void SceneTreeDock::_notification(int p_what) { button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); button_custom->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_NEW, false)); + button_clipboard = memnew(Button); + node_shortcuts->add_child(button_clipboard); + button_clipboard->set_text(TTR("Paste From Clipboard")); + button_clipboard->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons"))); + button_clipboard->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_PASTE, false)); + node_shortcuts->add_spacer(); create_root_dialog->add_child(node_shortcuts); _update_create_root_dialog(); @@ -1326,6 +1271,7 @@ void SceneTreeDock::_notification(int p_what) { 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); @@ -2121,7 +2067,7 @@ void SceneTreeDock::_delete_confirm(bool p_cut) { // Fixes the EditorHistory from still offering deleted notes EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); editor_history->cleanup_history(); - EditorNode::get_singleton()->get_inspector_dock()->call("_prepare_history"); + InspectorDock::get_singleton()->call("_prepare_history"); } void SceneTreeDock::_update_script_button() { @@ -2621,6 +2567,10 @@ void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) { } void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) { + if (!_validate_no_foreign()) { + return; + } + List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.is_empty()) { @@ -2721,6 +2671,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->add_icon_shortcut(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW); menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE); } + menu->add_icon_shortcut(get_theme_icon(SNAME("Collapse"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE); menu->add_separator(); existing_script = selected->get_script(); @@ -2731,10 +2682,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } if (profile_allow_editing) { - menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/cut_node"), TOOL_CUT); - menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/copy_node"), TOOL_COPY); + menu->add_icon_shortcut(get_theme_icon(SNAME("ActionCut"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/cut_node"), TOOL_CUT); + menu->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/copy_node"), TOOL_COPY); if (selection.size() == 1 && !node_clipboard.is_empty()) { - menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/paste_node"), TOOL_PASTE); + menu->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/paste_node"), TOOL_PASTE); } menu->add_separator(); } @@ -2858,16 +2809,9 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->popup(); } -void SceneTreeDock::_open_tree_menu() { - menu->clear(); - - menu->add_icon_shortcut(get_theme_icon(SNAME("Collapse"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE); - menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND); - menu->set_item_checked(menu->get_item_idx_from_text(TTR("Auto Expand to Selected")), EditorSettings::get_singleton()->get("docks/scene_tree/auto_expand_to_selected")); - - menu->reset_size(); - menu->set_position(get_screen_position() + get_local_mouse_position()); - menu->popup(); +void SceneTreeDock::_update_tree_menu() { + PopupMenu *tree_menu = button_tree_menu->get_popup(); + tree_menu->set_item_checked(tree_menu->get_item_idx_from_text(TTR("Auto Expand to Selected")), EditorSettings::get_singleton()->get("docks/scene_tree/auto_expand_to_selected")); } void SceneTreeDock::_filter_changed(const String &p_filter) { @@ -3014,6 +2958,112 @@ void SceneTreeDock::open_instance_child_dialog() { _tool_selected(TOOL_INSTANTIATE, true); } +List<Node *> SceneTreeDock::paste_nodes() { + List<Node *> pasted_nodes; + + if (node_clipboard.is_empty()) { + return pasted_nodes; + } + + bool has_cycle = false; + if (edited_scene && !edited_scene->get_scene_file_path().is_empty()) { + for (Node *E : node_clipboard) { + if (edited_scene->get_scene_file_path() == E->get_scene_file_path()) { + has_cycle = true; + break; + } + } + } + + if (has_cycle) { + current_option = -1; + accept->set_text(TTR("Can't paste root node into the same scene.")); + accept->popup_centered(); + return pasted_nodes; + } + + Node *paste_parent = edited_scene; + List<Node *> selection = editor_selection->get_selected_node_list(); + if (selection.size() > 0) { + paste_parent = selection.back()->get(); + } + + Node *owner = nullptr; + if (paste_parent) { + owner = paste_parent->get_owner(); + } + if (!owner) { + owner = paste_parent; + } + + UndoRedo &ur = editor_data->get_undo_redo(); + ur.create_action(TTR("Paste Node(s)")); + ur.add_do_method(editor_selection, "clear"); + + Map<RES, RES> resource_remap; + String target_scene; + if (edited_scene) { + target_scene = edited_scene->get_scene_file_path(); + } + if (target_scene != clipboard_source_scene) { + if (!clipboard_resource_remap.has(target_scene)) { + Map<RES, RES> remap; + for (Node *E : node_clipboard) { + _create_remap_for_node(E, remap); + } + clipboard_resource_remap[target_scene] = remap; + } + resource_remap = clipboard_resource_remap[target_scene]; + } + + for (Node *node : node_clipboard) { + Map<const Node *, Node *> duplimap; + + Node *dup = node->duplicate_from_editor(duplimap, resource_remap); + ERR_CONTINUE(!dup); + + pasted_nodes.push_back(dup); + + if (!paste_parent) { + paste_parent = dup; + owner = dup; + ur.add_do_method(editor, "set_edited_scene", dup); + } else { + ur.add_do_method(paste_parent, "add_child", dup, true); + } + + for (KeyValue<const Node *, Node *> &E2 : duplimap) { + Node *d = E2.value; + if (d != dup) { + ur.add_do_method(d, "set_owner", owner); + } + } + + if (dup != owner) { + ur.add_do_method(dup, "set_owner", owner); + } + ur.add_do_method(editor_selection, "add_node", dup); + + if (dup == paste_parent) { + ur.add_undo_method(editor, "set_edited_scene", (Object *)nullptr); + } else { + ur.add_undo_method(paste_parent, "remove_child", dup); + } + ur.add_do_reference(dup); + + if (node_clipboard.size() == 1) { + ur.add_do_method(editor, "push_item", dup); + } + } + + ur.commit_action(); + return pasted_nodes; +} + +List<Node *> SceneTreeDock::get_node_clipboard() const { + return node_clipboard; +} + void SceneTreeDock::add_remote_tree_editor(Control *p_remote) { ERR_FAIL_COND(remote_tree != nullptr); add_child(p_remote); @@ -3113,6 +3163,7 @@ void SceneTreeDock::_update_create_root_dialog() { beginner_nodes->show(); favorite_nodes->hide(); } + button_clipboard->set_visible(!node_clipboard.is_empty()); } } @@ -3167,7 +3218,7 @@ void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap) } Variant v = p_node->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (!states_stack_ready) { @@ -3205,7 +3256,7 @@ void SceneTreeDock::_create_remap_for_resource(RES p_resource, Map<RES, RES> &r_ } Variant v = p_resource->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (res->is_built_in() && !r_remap.has(res)) { @@ -3260,7 +3311,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KeyModifierMask::CMD | Key::A); ED_SHORTCUT("scene_tree/instance_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::A); - ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse All")); + ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse Branch")); ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KeyModifierMask::CMD | Key::X); ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KeyModifierMask::CMD | Key::C); ED_SHORTCUT("scene_tree/paste_node", TTR("Paste"), KeyModifierMask::CMD | Key::V); @@ -3317,11 +3368,15 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel filter_hbc->add_child(button_detach_script); button_detach_script->hide(); - button_tree_menu = memnew(Button); + button_tree_menu = memnew(MenuButton); button_tree_menu->set_flat(true); - button_tree_menu->connect("pressed", callable_mp(this, &SceneTreeDock::_open_tree_menu)); + button_tree_menu->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_update_tree_menu)); filter_hbc->add_child(button_tree_menu); + PopupMenu *tree_menu = button_tree_menu->get_popup(); + tree_menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND); + tree_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); + button_hb = memnew(HBoxContainer); vbc->add_child(button_hb); |