diff options
author | RĂ©mi Verschelde <remi@verschelde.fr> | 2022-03-06 23:25:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-06 23:25:39 +0100 |
commit | 1fbd498307103d0f80f0c780bbb647214dfed4b0 (patch) | |
tree | 1a3971f7b11cb320bcefde6a0252b829ff24f094 | |
parent | 78ad01cae7d68c34cd187b9c3a94583e95ff306f (diff) | |
parent | 2ed334f95fa67b5ef9451a44ff7820b1164e6b9c (diff) |
Merge pull request #58842 from IgorKordiukiewicz/save-as-scene-visual-feedback
Added visual feedback when drag and dropping from scene tree to filesystem
-rw-r--r-- | editor/filesystem_dock.cpp | 122 | ||||
-rw-r--r-- | editor/filesystem_dock.h | 7 |
2 files changed, 129 insertions, 0 deletions
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index e5cd7b8974..e8a2a46dd2 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -396,12 +396,25 @@ void FileSystemDock::_notification(int p_what) { } } else if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) { tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM | Tree::DROP_MODE_INBETWEEN); + } else if ((String(dd["type"]) == "nodes")) { + holding_branch = true; + TreeItem *item = tree->get_next_selected(tree->get_root()); + while (item) { + tree_items_selected_on_drag_begin.push_back(item); + item = tree->get_next_selected(item); + } + list_items_selected_on_drag_begin = files->get_selected_items(); } } } break; case NOTIFICATION_DRAG_END: { tree->set_drop_mode_flags(0); + + if (holding_branch) { + holding_branch = false; + _reselect_items_selected_on_drag_begin(true); + } } break; case NOTIFICATION_THEME_CHANGED: { @@ -2647,8 +2660,79 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) { call_deferred(SNAME("_update_import_dock")); } +void FileSystemDock::_tree_mouse_exited() { + if (holding_branch) { + _reselect_items_selected_on_drag_begin(); + } +} + +void FileSystemDock::_reselect_items_selected_on_drag_begin(bool reset) { + TreeItem *selected_item = tree->get_next_selected(tree->get_root()); + if (selected_item) { + selected_item->deselect(0); + } + if (!tree_items_selected_on_drag_begin.is_empty()) { + bool reselected = false; + for (TreeItem *item : tree_items_selected_on_drag_begin) { + if (item->get_tree()) { + item->select(0); + reselected = true; + } + } + + if (reset) { + tree_items_selected_on_drag_begin.clear(); + } + + if (!reselected) { + // If couldn't reselect the items selected on drag begin, select the "res://" item. + tree->get_root()->get_child(1)->select(0); + } + } + + files->deselect_all(); + if (!list_items_selected_on_drag_begin.is_empty()) { + for (const int idx : list_items_selected_on_drag_begin) { + files->select(idx, false); + } + + if (reset) { + list_items_selected_on_drag_begin.clear(); + } + } +} + void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> key = p_event; + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + TreeItem *item = tree->get_item_at_position(mm->get_position()); + if (item && holding_branch) { + String fpath = item->get_metadata(0); + while (!fpath.ends_with("/") && fpath != "res://" && item->get_parent()) { // Find the parent folder tree item. + item = item->get_parent(); + fpath = item->get_metadata(0); + } + + TreeItem *deselect_item = tree->get_next_selected(tree->get_root()); + while (deselect_item) { + deselect_item->deselect(0); + deselect_item = tree->get_next_selected(deselect_item); + } + item->select(0); + + if (display_mode == DisplayMode::DISPLAY_MODE_SPLIT) { + files->deselect_all(); + // Try to select the corresponding file list item. + const int files_item_idx = files->find_metadata(fpath); + if (files_item_idx != -1) { + files->select(files_item_idx); + } + } + } + } + if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { _tree_rmb_option(FILE_DUPLICATE); @@ -2669,6 +2753,43 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { } void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) { + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && holding_branch) { + const int item_idx = files->get_item_at_position(mm->get_position()); + if (item_idx != -1) { + files->deselect_all(); + String fpath = files->get_item_metadata(item_idx); + if (fpath.ends_with("/") || fpath == "res://") { + files->select(item_idx); + } + + TreeItem *deselect_item = tree->get_next_selected(tree->get_root()); + while (deselect_item) { + deselect_item->deselect(0); + deselect_item = tree->get_next_selected(deselect_item); + } + + // Try to select the corresponding tree item. + TreeItem *tree_item = tree->get_item_with_text(files->get_item_text(item_idx)); + if (tree_item) { + tree_item->select(0); + } else { + // Find parent folder. + fpath = fpath.substr(0, fpath.rfind("/") + 1); + if (fpath.size() > String("res://").size()) { + fpath = fpath.left(fpath.size() - 2); // Remove last '/'. + const int slash_idx = fpath.rfind("/"); + fpath = fpath.substr(slash_idx + 1, fpath.size() - slash_idx - 1); + } + + tree_item = tree->get_item_with_text(fpath); + if (tree_item) { + tree_item->select(0); + } + } + } + } + Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { @@ -2932,6 +3053,7 @@ FileSystemDock::FileSystemDock() { tree->connect("empty_rmb", callable_mp(this, &FileSystemDock::_tree_rmb_empty)); tree->connect("nothing_selected", callable_mp(this, &FileSystemDock::_tree_empty_selected)); tree->connect("gui_input", callable_mp(this, &FileSystemDock::_tree_gui_input)); + tree->connect("mouse_exited", callable_mp(this, &FileSystemDock::_tree_mouse_exited)); file_list_vb = memnew(VBoxContainer); file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 21c50beeb2..d457c6acd4 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -185,6 +185,13 @@ private: ItemList *files; bool import_dock_needs_update; + bool holding_branch = false; + Vector<TreeItem *> tree_items_selected_on_drag_begin; + PackedInt32Array list_items_selected_on_drag_begin; + + void _tree_mouse_exited(); + void _reselect_items_selected_on_drag_begin(bool reset = false); + Ref<Texture2D> _get_tree_item_icon(bool p_is_valid, String p_file_type); bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path = false); Vector<String> _compute_uncollapsed_paths(); |