mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-04 07:31:16 +00:00 
			
		
		
		
	Added visual feedback when drag and dropping from scene tree to file system
This commit is contained in:
		
							parent
							
								
									d37e8586be
								
							
						
					
					
						commit
						2ed334f95f
					
				
					 2 changed files with 129 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue