summaryrefslogtreecommitdiff
path: root/editor/filesystem_dock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/filesystem_dock.cpp')
-rw-r--r--editor/filesystem_dock.cpp240
1 files changed, 195 insertions, 45 deletions
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index b41123c0dd..33c6ce9622 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -73,7 +73,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
}
subdirectory_item->set_text(0, dname);
- subdirectory_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE);
+ subdirectory_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE);
subdirectory_item->set_icon(0, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
subdirectory_item->set_icon_modulate(0, get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")));
subdirectory_item->set_selectable(0, true);
@@ -143,7 +143,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
for (const FileInfo &fi : file_list) {
TreeItem *file_item = tree->create_item(subdirectory_item);
file_item->set_text(0, fi.name);
- file_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE);
+ file_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE);
file_item->set_icon(0, _get_tree_item_icon(!fi.import_broken, fi.type));
String file_metadata = lpath.plus_file(fi.name);
file_item->set_metadata(0, file_metadata);
@@ -224,6 +224,20 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
favorites->set_collapsed(p_uncollapsed_paths.find("Favorites") < 0);
Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorites();
+
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ bool fav_changed = false;
+ for (int i = favorite_paths.size() - 1; i >= 0; i--) {
+ if (da->dir_exists(favorite_paths[i]) || da->file_exists(favorite_paths[i])) {
+ continue;
+ }
+ favorite_paths.remove_at(i);
+ fav_changed = true;
+ }
+ if (fav_changed) {
+ EditorSettings::get_singleton()->set_favorites(favorite_paths);
+ }
+
for (int i = 0; i < favorite_paths.size(); i++) {
String fave = favorite_paths[i];
if (!fave.begins_with("res://")) {
@@ -396,12 +410,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: {
@@ -512,16 +539,14 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
if (target_path.ends_with("/")) {
target_path = target_path.substr(0, target_path.length() - 1);
}
- DirAccess *dirAccess = DirAccess::open("res://");
- if (dirAccess->file_exists(p_path)) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->file_exists(p_path)) {
path = target_path;
- } else if (dirAccess->dir_exists(p_path)) {
+ } else if (da->dir_exists(p_path)) {
path = target_path + "/";
} else {
- memdelete(dirAccess);
ERR_FAIL_MSG(vformat("Cannot navigate to '%s' as it has not been found in the file system!", p_path));
}
- memdelete(dirAccess);
}
_set_current_path_text(path);
@@ -768,14 +793,14 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
icon = folder_icon;
if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) {
files->add_item(text, icon, true);
- files->set_item_metadata(files->get_item_count() - 1, favorite);
+ files->set_item_metadata(-1, favorite);
}
} else if (favorite.ends_with("/")) {
text = favorite.substr(0, favorite.length() - 1).get_file();
icon = folder_icon;
if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) {
files->add_item(text, icon, true);
- files->set_item_metadata(files->get_item_count() - 1, favorite);
+ files->set_item_metadata(-1, favorite);
}
} else {
int index;
@@ -829,9 +854,9 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
bd += "/";
}
- files->set_item_metadata(files->get_item_count() - 1, bd);
- files->set_item_selectable(files->get_item_count() - 1, false);
- files->set_item_icon_modulate(files->get_item_count() - 1, folder_color);
+ files->set_item_metadata(-1, bd);
+ files->set_item_selectable(-1, false);
+ files->set_item_icon_modulate(-1, folder_color);
}
bool reversed = file_sort == FILE_SORT_NAME_REVERSE;
@@ -841,8 +866,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
String dname = efd->get_subdir(i)->get_name();
files->add_item(dname, folder_icon, true);
- files->set_item_metadata(files->get_item_count() - 1, directory.plus_file(dname) + "/");
- files->set_item_icon_modulate(files->get_item_count() - 1, folder_color);
+ files->set_item_metadata(-1, directory.plus_file(dname) + "/");
+ files->set_item_icon_modulate(-1, folder_color);
if (cselection.has(dname)) {
files->select(files->get_item_count() - 1, false);
@@ -964,7 +989,27 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
{
List<String> importer_exts;
- ResourceImporterScene::get_singleton()->get_recognized_extensions(&importer_exts);
+ ResourceImporterScene::get_scene_singleton()->get_recognized_extensions(&importer_exts);
+ String extension = fpath.get_extension();
+ for (const String &E : importer_exts) {
+ if (extension.nocasecmp_to(E) == 0) {
+ is_imported = true;
+ break;
+ }
+ }
+ }
+
+ if (is_imported) {
+ ResourceImporterScene::get_scene_singleton()->show_advanced_options(fpath);
+ } else {
+ EditorNode::get_singleton()->open_request(fpath);
+ }
+ } else if (ResourceLoader::get_resource_type(fpath) == "AnimationLibrary") {
+ bool is_imported = false;
+
+ {
+ List<String> importer_exts;
+ ResourceImporterScene::get_animation_singleton()->get_recognized_extensions(&importer_exts);
String extension = fpath.get_extension();
for (const String &E : importer_exts) {
if (extension.nocasecmp_to(E) == 0) {
@@ -975,7 +1020,7 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
}
if (is_imported) {
- ResourceImporterScene::get_singleton()->show_advanced_options(fpath);
+ ResourceImporterScene::get_animation_singleton()->show_advanced_options(fpath);
} else {
EditorNode::get_singleton()->open_request(fpath);
}
@@ -1158,7 +1203,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
_get_all_items_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), file_changed_paths, folder_changed_paths);
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Moving " + old_path + " -> " + new_path);
Error err = da->rename(old_path, new_path);
if (err == OK) {
@@ -1198,7 +1243,6 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
} else {
EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + "\n");
}
- memdelete(da);
}
void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const {
@@ -1217,7 +1261,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
return;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Duplicating " + old_path + " -> " + new_path);
Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path);
if (err == OK) {
@@ -1236,7 +1280,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
cfg->save(new_path + ".import");
} else if (p_item.is_file && (old_path.get_extension() == "tscn" || old_path.get_extension() == "tres")) {
// FIXME: Quick hack to fix text resources. This should be fixed properly.
- FileAccessRef file = FileAccess::open(old_path, FileAccess::READ, &err);
+ Ref<FileAccess> file = FileAccess::open(old_path, FileAccess::READ, &err);
if (err == OK) {
PackedStringArray lines = file->get_as_utf8_string().split("\n");
String line = lines[0];
@@ -1245,7 +1289,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
line = line.substr(0, line.find(" uid")) + "]";
lines.write[0] = line;
- FileAccessRef file2 = FileAccess::open(new_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> file2 = FileAccess::open(new_path, FileAccess::WRITE, &err);
if (err == OK) {
file2->store_string(String("\n").join(lines));
}
@@ -1255,7 +1299,6 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
} else {
EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + "\n");
}
- memdelete(da);
}
void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> &p_renames) const {
@@ -1404,13 +1447,18 @@ void FileSystemDock::_make_dir_confirm() {
if (!directory.ends_with("/")) {
directory = directory.get_base_dir();
}
+
print_verbose("Making folder " + dir_name + " in " + directory);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
Error err = da->change_dir(directory);
- if (err == OK) {
- err = da->make_dir(dir_name);
+ ERR_FAIL_COND_MSG(err != OK, "Cannot open directory '" + directory + "'.");
+
+ if (da->dir_exists(dir_name)) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not create folder. File with that name already exists."));
+ return;
}
- memdelete(da);
+
+ err = da->make_dir(dir_name);
if (err == OK) {
print_verbose("FileSystem: calling rescan.");
@@ -1451,13 +1499,11 @@ void FileSystemDock::_make_scene_confirm() {
scene_name = directory.plus_file(scene_name);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(scene_name)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
int idx = EditorNode::get_singleton()->new_scene();
EditorNode::get_singleton()->get_editor_data().set_scene_path(idx, scene_name);
@@ -1468,7 +1514,7 @@ void FileSystemDock::_file_removed(String p_file) {
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_file.get_base_dir();
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
while (!da->dir_exists(path)) {
path = path.get_base_dir();
}
@@ -1481,7 +1527,7 @@ void FileSystemDock::_folder_removed(String p_folder) {
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_folder.get_base_dir();
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
while (!da->dir_exists(path)) {
path = path.get_base_dir();
}
@@ -1520,7 +1566,7 @@ void FileSystemDock::_rename_operation_confirm() {
}
// Present a more user friendly warning for name conflict.
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
// Workaround case insensitivity on Windows.
if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) {
@@ -1528,10 +1574,8 @@ void FileSystemDock::_rename_operation_confirm() {
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
#endif
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
Map<String, String> file_renames;
Map<String, String> folder_renames;
@@ -1575,13 +1619,11 @@ void FileSystemDock::_duplicate_operation_confirm() {
String new_path = base_dir.plus_file(new_name);
// Present a more user friendly warning for name conflict
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
_try_duplicate_item(to_duplicate, new_path);
@@ -2085,6 +2127,10 @@ void FileSystemDock::focus_on_filter() {
}
}
+ScriptCreateDialog *FileSystemDock::get_script_create_dialog() const {
+ return make_script_dialog;
+}
+
void FileSystemDock::set_file_list_display_mode(FileListDisplayMode p_mode) {
if (p_mode == file_list_display_mode) {
return;
@@ -2328,7 +2374,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
int exist_counter = 1;
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
while (da->file_exists(new_path) || da->dir_exists(new_path)) {
exist_counter++;
new_path = vformat(new_path_base, exist_counter);
@@ -2647,8 +2693,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 +2786,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)) {
@@ -2697,7 +2851,7 @@ void FileSystemDock::_get_imported_files(const String &p_path, Vector<String> &f
return;
}
- DirAccess *da = DirAccess::open(p_path);
+ Ref<DirAccess> da = DirAccess::open(p_path);
da->list_dir_begin();
String n = da->get_next();
while (!n.is_empty()) {
@@ -2872,7 +3026,7 @@ FileSystemDock::FileSystemDock() {
toolbar_hbc->add_child(button_hist_next);
current_path = memnew(LineEdit);
- current_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ current_path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
current_path->set_h_size_flags(SIZE_EXPAND_FILL);
_set_current_path_text(path);
toolbar_hbc->add_child(current_path);
@@ -2932,6 +3086,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);
@@ -3057,10 +3212,7 @@ FileSystemDock::FileSystemDock() {
searched_string = String();
uncollapsed_paths_before_search = Vector<String>();
- updating_tree = false;
tree_update_id = 0;
- initialized = false;
- import_dock_needs_update = false;
history_pos = 0;
history_max_size = 20;
@@ -3069,8 +3221,6 @@ FileSystemDock::FileSystemDock() {
display_mode = DISPLAY_MODE_TREE_ONLY;
old_display_mode = DISPLAY_MODE_TREE_ONLY;
file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS;
-
- always_show_folders = false;
}
FileSystemDock::~FileSystemDock() {