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.cpp522
1 files changed, 369 insertions, 153 deletions
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 5dd5c050e0..33c6ce9622 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,16 +37,21 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/templates/list.h"
-#include "editor_feature_profile.h"
-#include "editor_node.h"
-#include "editor_resource_preview.h"
-#include "editor_scale.h"
-#include "editor_settings.h"
-#include "import_dock.h"
+#include "editor/editor_feature_profile.h"
+#include "editor/editor_node.h"
+#include "editor/editor_resource_preview.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "editor/import_dock.h"
+#include "editor/scene_tree_dock.h"
+#include "editor/shader_create_dialog.h"
+#include "scene/gui/label.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
#include "servers/display_server.h"
+FileSystemDock *FileSystemDock::singleton = nullptr;
+
Ref<Texture2D> FileSystemDock::_get_tree_item_icon(bool p_is_valid, String p_file_type) {
Ref<Texture2D> file_icon;
if (!p_is_valid) {
@@ -63,12 +68,12 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
// Create a tree item for the subdirectory.
TreeItem *subdirectory_item = tree->create_item(p_parent);
String dname = p_dir->get_name();
- if (dname == "") {
+ if (dname.is_empty()) {
dname = "res://";
}
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);
@@ -106,7 +111,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
List<FileInfo> file_list;
for (int i = 0; i < p_dir->get_file_count(); i++) {
String file_type = p_dir->get_file_type(i);
- if (_is_file_type_disabled_by_feature_profile(file_type)) {
+ if (file_type != "TextFile" && _is_file_type_disabled_by_feature_profile(file_type)) {
// If type is disabled, file won't be displayed.
continue;
}
@@ -138,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);
@@ -197,7 +202,7 @@ Vector<String> FileSystemDock::_compute_uncollapsed_paths() {
child = child->get_next();
}
}
- needs_check.remove(0);
+ needs_check.remove_at(0);
}
}
}
@@ -219,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://")) {
@@ -335,30 +354,28 @@ void FileSystemDock::_notification(int p_what) {
EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &FileSystemDock::_fs_changed));
EditorResourcePreview::get_singleton()->connect("preview_invalidated", callable_mp(this, &FileSystemDock::_preview_invalidated));
- String ei = "EditorIcons";
-
- button_reload->set_icon(get_theme_icon(SNAME("Reload"), ei));
- button_toggle_display_mode->set_icon(get_theme_icon(SNAME("Panels2"), ei));
+ button_reload->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
+ button_toggle_display_mode->set_icon(get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons")));
button_file_list_display_mode->connect("pressed", callable_mp(this, &FileSystemDock::_toggle_file_display));
files->connect("item_activated", callable_mp(this, &FileSystemDock::_file_list_activate_file));
button_hist_next->connect("pressed", callable_mp(this, &FileSystemDock::_fw_history));
button_hist_prev->connect("pressed", callable_mp(this, &FileSystemDock::_bw_history));
- tree_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
+ tree_search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
tree_search_box->set_clear_button_enabled(true);
- tree_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
+ tree_button_sort->set_icon(get_theme_icon(SNAME("Sort"), SNAME("EditorIcons")));
- file_list_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
+ file_list_search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
file_list_search_box->set_clear_button_enabled(true);
- file_list_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
+ file_list_button_sort->set_icon(get_theme_icon(SNAME("Sort"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
- button_hist_next->set_icon(get_theme_icon(SNAME("Back"), ei));
- button_hist_prev->set_icon(get_theme_icon(SNAME("Forward"), ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
} else {
- button_hist_next->set_icon(get_theme_icon(SNAME("Forward"), ei));
- button_hist_prev->set_icon(get_theme_icon(SNAME("Back"), ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
}
file_list_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_list_rmb_option));
tree_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_tree_rmb_option));
@@ -393,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: {
@@ -409,15 +439,14 @@ void FileSystemDock::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
// Update icons.
- String ei = "EditorIcons";
- button_reload->set_icon(get_theme_icon(SNAME("Reload"), ei));
- button_toggle_display_mode->set_icon(get_theme_icon(SNAME("Panels2"), ei));
+ button_reload->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
+ button_toggle_display_mode->set_icon(get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
- button_hist_next->set_icon(get_theme_icon(SNAME("Back"), ei));
- button_hist_prev->set_icon(get_theme_icon(SNAME("Forward"), ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
} else {
- button_hist_next->set_icon(get_theme_icon(SNAME("Forward"), ei));
- button_hist_prev->set_icon(get_theme_icon(SNAME("Back"), ei));
+ button_hist_next->set_icon(get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
+ button_hist_prev->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
}
if (file_list_display_mode == FILE_LIST_DISPLAY_LIST) {
button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
@@ -425,13 +454,13 @@ void FileSystemDock::_notification(int p_what) {
button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
}
- tree_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
+ tree_search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
tree_search_box->set_clear_button_enabled(true);
- tree_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
+ tree_button_sort->set_icon(get_theme_icon(SNAME("Sort"), SNAME("EditorIcons")));
- file_list_search_box->set_right_icon(get_theme_icon(SNAME("Search"), ei));
+ file_list_search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
file_list_search_box->set_clear_button_enabled(true);
- file_list_button_sort->set_icon(get_theme_icon(SNAME("Sort"), ei));
+ file_list_button_sort->set_icon(get_theme_icon(SNAME("Sort"), SNAME("EditorIcons")));
// Update always show folders.
bool new_always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
@@ -510,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);
@@ -528,7 +555,7 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
_update_tree(_compute_uncollapsed_paths(), false, p_select_in_favorites, true);
if (display_mode == DISPLAY_MODE_SPLIT) {
_update_file_list(false);
- files->get_v_scroll()->set_value(0);
+ files->get_v_scroll_bar()->set_value(0);
}
String file_name = p_path.get_file();
@@ -626,7 +653,7 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
for (int i = 0; i < p_path->get_file_count(); i++) {
String file = p_path->get_file(i);
- if (file.to_lower().find(searched_string) != -1) {
+ if (file.to_lower().contains(searched_string)) {
FileInfo fi;
fi.name = file;
fi.type = p_path->get_file_type(i);
@@ -688,9 +715,11 @@ void FileSystemDock::_sort_file_info_list(List<FileSystemDock::FileInfo> &r_file
r_file_list.reverse();
break;
case FILE_SORT_NAME_REVERSE:
+ r_file_list.sort();
r_file_list.reverse();
break;
default: // FILE_SORT_NAME
+ r_file_list.sort();
break;
}
}
@@ -713,7 +742,6 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
String directory = path;
String file = "";
- String ei = "EditorIcons";
int thumbnail_size = EditorSettings::get_singleton()->get("docks/filesystem/thumbnail_size");
thumbnail_size *= EDSCALE;
Ref<Texture2D> folder_thumbnail;
@@ -731,13 +759,13 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
if (thumbnail_size < 64) {
- folder_thumbnail = get_theme_icon(SNAME("FolderMediumThumb"), ei);
- file_thumbnail = get_theme_icon(SNAME("FileMediumThumb"), ei);
- file_thumbnail_broken = get_theme_icon(SNAME("FileDeadMediumThumb"), ei);
+ folder_thumbnail = get_theme_icon(SNAME("FolderMediumThumb"), SNAME("EditorIcons"));
+ file_thumbnail = get_theme_icon(SNAME("FileMediumThumb"), SNAME("EditorIcons"));
+ file_thumbnail_broken = get_theme_icon(SNAME("FileDeadMediumThumb"), SNAME("EditorIcons"));
} else {
- folder_thumbnail = get_theme_icon(SNAME("FolderBigThumb"), ei);
- file_thumbnail = get_theme_icon(SNAME("FileBigThumb"), ei);
- file_thumbnail_broken = get_theme_icon(SNAME("FileDeadBigThumb"), ei);
+ folder_thumbnail = get_theme_icon(SNAME("FolderBigThumb"), SNAME("EditorIcons"));
+ file_thumbnail = get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons"));
+ file_thumbnail_broken = get_theme_icon(SNAME("FileDeadBigThumb"), SNAME("EditorIcons"));
}
} else {
// No thumbnails.
@@ -765,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;
@@ -826,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;
@@ -838,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);
@@ -866,7 +894,6 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
// Fills the ItemList control node from the FileInfos.
String main_scene = ProjectSettings::get_singleton()->get("application/run/main_scene");
- String oi = "Object";
for (FileInfo &E : file_list) {
FileInfo *finfo = &(E);
String fname = finfo->name;
@@ -880,10 +907,10 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
// Select the icons.
if (!finfo->import_broken) {
- type_icon = (has_theme_icon(ftype, ei)) ? get_theme_icon(ftype, ei) : get_theme_icon(oi, ei);
+ type_icon = (has_theme_icon(ftype, SNAME("EditorIcons"))) ? get_theme_icon(ftype, SNAME("EditorIcons")) : get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
big_icon = file_thumbnail;
} else {
- type_icon = get_theme_icon(SNAME("ImportFail"), ei);
+ type_icon = get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"));
big_icon = file_thumbnail_broken;
tooltip += "\n" + TTR("Status: Import of file failed. Please fix file and reimport manually.");
}
@@ -920,7 +947,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->select(item_index, false);
}
- if (!p_keep_selection && file != "" && fname == file) {
+ if (!p_keep_selection && !file.is_empty() && fname == file) {
files->select(item_index, true);
files->ensure_current_is_visible();
}
@@ -962,7 +989,7 @@ 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) {
@@ -973,12 +1000,32 @@ 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_scene_singleton()->show_advanced_options(fpath);
} else {
- editor->open_request(fpath);
+ 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) {
+ is_imported = true;
+ break;
+ }
+ }
+ }
+
+ if (is_imported) {
+ ResourceImporterScene::get_animation_singleton()->show_advanced_options(fpath);
+ } else {
+ EditorNode::get_singleton()->open_request(fpath);
}
} else {
- editor->load_resource(fpath);
+ EditorNode::get_singleton()->load_resource(fpath);
}
}
_navigate_to_path(fpath, p_select_in_favorites);
@@ -1091,7 +1138,7 @@ void FileSystemDock::_push_to_history() {
history_pos++;
if (history.size() > history_max_size) {
- history.remove(0);
+ history.remove_at(0);
history_pos = history_max_size - 1;
}
}
@@ -1156,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) {
@@ -1171,12 +1218,12 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
// Update scene if it is open.
for (int i = 0; i < file_changed_paths.size(); ++i) {
String new_item_path = p_item.is_file ? new_path : file_changed_paths[i].replace_first(old_path, new_path);
- if (ResourceLoader::get_resource_type(new_item_path) == "PackedScene" && editor->is_scene_open(file_changed_paths[i])) {
- EditorData *ed = &editor->get_editor_data();
+ if (ResourceLoader::get_resource_type(new_item_path) == "PackedScene" && EditorNode::get_singleton()->is_scene_open(file_changed_paths[i])) {
+ EditorData *ed = &EditorNode::get_singleton()->get_editor_data();
for (int j = 0; j < ed->get_edited_scene_count(); j++) {
if (ed->get_scene_path(j) == file_changed_paths[i]) {
- ed->get_edited_scene_root(j)->set_filename(new_item_path);
- editor->save_layout();
+ ed->get_edited_scene_root(j)->set_scene_file_path(new_item_path);
+ EditorNode::get_singleton()->save_layout();
break;
}
}
@@ -1196,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 {
@@ -1215,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) {
@@ -1225,11 +1271,34 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
if (err != OK) {
EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ".import\n");
}
+
+ // Remove uid from .import file to avoid conflict.
+ Ref<ConfigFile> cfg;
+ cfg.instantiate();
+ cfg->load(new_path + ".import");
+ cfg->erase_section_key("remap", "uid");
+ 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.
+ 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];
+
+ if (line.contains("uid")) {
+ line = line.substr(0, line.find(" uid")) + "]";
+ lines.write[0] = line;
+
+ Ref<FileAccess> file2 = FileAccess::open(new_path, FileAccess::WRITE, &err);
+ if (err == OK) {
+ file2->store_string(String("\n").join(lines));
+ }
+ }
+ }
}
} 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 {
@@ -1260,7 +1329,7 @@ void FileSystemDock::_update_resource_paths_after_move(const Map<String, String>
continue;
}
- path = get_tree()->get_edited_scene_root()->get_filename();
+ path = get_tree()->get_edited_scene_root()->get_scene_file_path();
} else {
path = EditorNode::get_editor_data().get_scene_path(i);
}
@@ -1270,7 +1339,7 @@ void FileSystemDock::_update_resource_paths_after_move(const Map<String, String>
}
if (i == EditorNode::get_editor_data().get_edited_scene()) {
- get_tree()->get_edited_scene_root()->set_filename(path);
+ get_tree()->get_edited_scene_root()->set_scene_file_path(path);
} else {
EditorNode::get_editor_data().set_scene_path(i, path);
}
@@ -1290,7 +1359,7 @@ void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &
Error err = ResourceLoader::rename_dependencies(file, p_renames);
if (err == OK) {
if (ResourceLoader::get_resource_type(file) == "PackedScene") {
- editor->reload_scene(file);
+ EditorNode::get_singleton()->reload_scene(file);
}
} else {
EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies:") + "\n" + remaps[i] + "\n");
@@ -1301,11 +1370,11 @@ void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &
void FileSystemDock::_update_project_settings_after_move(const Map<String, String> &p_renames) const {
// Find all project settings of type FILE and replace them if needed.
const Map<StringName, PropertyInfo> prop_info = ProjectSettings::get_singleton()->get_custom_property_info();
- for (const Map<StringName, PropertyInfo>::Element *E = prop_info.front(); E; E = E->next()) {
- if (E->get().hint == PROPERTY_HINT_FILE) {
- String old_path = GLOBAL_GET(E->key());
+ for (const KeyValue<StringName, PropertyInfo> &E : prop_info) {
+ if (E.value.hint == PROPERTY_HINT_FILE) {
+ String old_path = GLOBAL_GET(E.key);
if (p_renames.has(old_path)) {
- ProjectSettings::get_singleton()->set_setting(E->key(), p_renames[old_path]);
+ ProjectSettings::get_singleton()->set_setting(E.key, p_renames[old_path]);
}
};
}
@@ -1359,7 +1428,7 @@ void FileSystemDock::_save_scenes_after_move(const Map<String, String> &p_rename
}
}
- editor->save_scene_list(new_filenames);
+ EditorNode::get_singleton()->save_scene_list(new_filenames);
}
void FileSystemDock::_make_dir_confirm() {
@@ -1368,8 +1437,8 @@ void FileSystemDock::_make_dir_confirm() {
if (dir_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
return;
- } else if (dir_name.find("/") != -1 || dir_name.find("\\") != -1 || dir_name.find(":") != -1 || dir_name.find("*") != -1 ||
- dir_name.find("|") != -1 || dir_name.find(">") != -1 || dir_name.ends_with(".") || dir_name.ends_with(" ")) {
+ } else if (dir_name.contains("/") || dir_name.contains("\\") || dir_name.contains(":") || dir_name.contains("*") ||
+ dir_name.contains("|") || dir_name.contains(">") || dir_name.ends_with(".") || dir_name.ends_with(" ")) {
EditorNode::get_singleton()->show_warning(TTR("Provided name contains invalid characters."));
return;
}
@@ -1378,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.");
@@ -1425,16 +1499,14 @@ 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 = editor->new_scene();
- editor->get_editor_data().set_scene_path(idx, scene_name);
+ int idx = EditorNode::get_singleton()->new_scene();
+ EditorNode::get_singleton()->get_editor_data().set_scene_path(idx, scene_name);
}
void FileSystemDock::_file_removed(String p_file) {
@@ -1442,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();
}
@@ -1455,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();
}
@@ -1469,12 +1541,18 @@ void FileSystemDock::_folder_removed(String p_folder) {
void FileSystemDock::_rename_operation_confirm() {
String new_name = rename_dialog_text->get_text().strip_edges();
+ String old_name = tree->get_selected()->get_text(0);
if (new_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
return;
- } else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
+ } else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) {
EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
return;
+ } else if (to_rename.is_file && old_name.get_extension() != new_name.get_extension()) {
+ if (!EditorFileSystem::get_singleton()->get_valid_extensions().find(new_name.get_extension())) {
+ EditorNode::get_singleton()->show_warning(TTR("This file extension is not recognized by the editor.\nIf you want to rename it anyway, use your operating system's file manager.\nAfter renaming to an unknown extension, the file won't be shown in the editor anymore."));
+ return;
+ }
}
String old_path = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1) : to_rename.path;
@@ -1488,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()) {
@@ -1496,23 +1574,21 @@ 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;
_try_move_item(to_rename, new_path, file_renames, folder_renames);
- int current_tab = editor->get_current_tab();
+ int current_tab = EditorNode::get_singleton()->get_current_tab();
_save_scenes_after_move(file_renames); // save scenes before updating
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
_update_favorites_list_after_move(file_renames, folder_renames);
- editor->set_current_tab(current_tab);
+ EditorNode::get_singleton()->set_current_tab(current_tab);
print_verbose("FileSystem: calling rescan.");
_rescan();
@@ -1529,7 +1605,7 @@ void FileSystemDock::_duplicate_operation_confirm() {
if (new_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
return;
- } else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
+ } else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) {
EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
return;
}
@@ -1543,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);
@@ -1616,14 +1690,14 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove
}
if (is_moved) {
- int current_tab = editor->get_current_tab();
+ int current_tab = EditorNode::get_singleton()->get_current_tab();
_save_scenes_after_move(file_renames); // Save scenes before updating.
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
_update_favorites_list_after_move(file_renames, folder_renames);
- editor->set_current_tab(current_tab);
+ EditorNode::get_singleton()->set_current_tab(current_tab);
print_verbose("FileSystem: calling rescan.");
_rescan();
@@ -1667,8 +1741,8 @@ Vector<String> FileSystemDock::_remove_self_included_paths(Vector<String> select
selected_strings.sort_custom<NaturalNoCaseComparator>();
String last_path = "";
for (int i = 0; i < selected_strings.size(); i++) {
- if (last_path != "" && selected_strings[i].begins_with(last_path)) {
- selected_strings.remove(i);
+ if (!last_path.is_empty() && selected_strings[i].begins_with(last_path)) {
+ selected_strings.remove_at(i);
i--;
}
if (selected_strings[i].ends_with("/")) {
@@ -1702,7 +1776,7 @@ void FileSystemDock::_tree_rmb_option(int p_option) {
child = child->get_next();
}
- needs_check.remove(0);
+ needs_check.remove_at(0);
}
}
} break;
@@ -1790,7 +1864,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
// Add the files from favorites.
Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
for (int i = 0; i < p_selected.size(); i++) {
- if (favorites.find(p_selected[i]) == -1) {
+ if (!favorites.has(p_selected[i])) {
favorites.push_back(p_selected[i]);
}
}
@@ -1954,10 +2028,33 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
case FILE_NEW_RESOURCE: {
new_resource_dialog->popup_create(true);
} break;
+ case FILE_NEW_TEXTFILE: {
+ String fpath = path;
+ if (!fpath.ends_with("/")) {
+ fpath = fpath.get_base_dir();
+ }
+ ScriptEditor::get_singleton()->open_text_file_create_dialog(fpath);
+ } break;
}
}
void FileSystemDock::_resource_created() {
+ String fpath = path;
+ if (!fpath.ends_with("/")) {
+ fpath = fpath.get_base_dir();
+ }
+
+ String type_name = new_resource_dialog->get_selected_type();
+ if (type_name == "Shader") {
+ make_shader_dialog->config(fpath.plus_file("new_shader"), false, false, 0);
+ make_shader_dialog->popup_centered();
+ return;
+ } else if (type_name == "VisualShader") {
+ make_shader_dialog->config(fpath.plus_file("new_shader"), false, false, 1);
+ make_shader_dialog->popup_centered();
+ return;
+ }
+
Variant c = new_resource_dialog->instance_selected();
ERR_FAIL_COND(!c);
@@ -1972,14 +2069,8 @@ void FileSystemDock::_resource_created() {
memdelete(node);
}
- editor->push_item(r);
-
- String fpath = path;
- if (!fpath.ends_with("/")) {
- fpath = fpath.get_base_dir();
- }
-
- editor->save_resource_as(RES(r), fpath);
+ EditorNode::get_singleton()->push_item(r);
+ EditorNode::get_singleton()->save_resource_as(RES(r), fpath);
}
void FileSystemDock::_search_changed(const String &p_text, const Control *p_from) {
@@ -1996,7 +2087,7 @@ void FileSystemDock::_search_changed(const String &p_text, const Control *p_from
tree_search_box->set_text(searched_string);
}
- bool unfold_path = (p_text == String() && path != String());
+ bool unfold_path = (p_text.is_empty() && !path.is_empty());
switch (display_mode) {
case DISPLAY_MODE_TREE_ONLY: {
_update_tree(searched_string.length() == 0 ? uncollapsed_paths_before_search : Vector<String>(), false, false, unfold_path);
@@ -2036,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;
@@ -2220,7 +2315,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
drop_position -= offset;
to_remove.sort();
for (int i = 0; i < to_remove.size(); i++) {
- dirs.remove(to_remove[i] - i);
+ dirs.remove_at(to_remove[i] - i);
}
// Re-add them at the right position.
@@ -2264,7 +2359,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
}
if (!to_move.is_empty()) {
- if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
+ if (Input::get_singleton()->is_key_pressed(Key::CTRL)) {
for (int i = 0; i < to_move.size(); i++) {
String new_path;
String new_path_base;
@@ -2279,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);
@@ -2296,7 +2391,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
Vector<String> fnames = drag_data["files"];
Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
for (int i = 0; i < fnames.size(); i++) {
- if (favorites.find(fnames[i]) == -1) {
+ if (!favorites.has(fnames[i])) {
favorites.push_back(fnames[i]);
}
}
@@ -2309,7 +2404,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
String to_dir;
bool favorite;
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
- EditorNode::get_singleton()->get_scene_tree_dock()->save_branch_to_file(to_dir);
+ SceneTreeDock::get_singleton()->save_branch_to_file(to_dir);
}
}
@@ -2473,12 +2568,14 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
p_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE);
p_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT);
p_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE);
p_popup->add_separator();
}
String fpath = p_paths[0];
String item_text = fpath.ends_with("/") ? TTR("Open in File Manager") : TTR("Show in File Manager");
p_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), item_text, FILE_SHOW_IN_EXPLORER);
+ path = fpath;
}
}
@@ -2497,9 +2594,10 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
// Popup.
if (!paths.is_empty()) {
- tree_popup->set_size(Size2(1, 1));
+ tree_popup->reset_size();
_file_and_folders_fill_popup(tree_popup, paths);
tree_popup->set_position(tree->get_screen_position() + p_pos);
+ tree_popup->reset_size();
tree_popup->popup();
}
}
@@ -2508,12 +2606,17 @@ void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) {
// Right click is pressed in the empty space of the tree.
path = "res://";
tree_popup->clear();
- tree_popup->set_size(Size2(1, 1));
+ tree_popup->reset_size();
tree_popup->add_icon_item(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), TTR("New Folder..."), FILE_NEW_FOLDER);
tree_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE);
tree_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT);
tree_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE);
- tree_popup->set_position(tree->get_global_position() + p_pos);
+ tree_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE);
+ tree_popup->add_separator();
+ tree_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER);
+
+ tree_popup->set_position(tree->get_screen_position() + p_pos);
+ tree_popup->reset_size();
tree_popup->popup();
}
@@ -2538,9 +2641,9 @@ void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) {
// Popup.
if (!paths.is_empty()) {
file_list_popup->clear();
- file_list_popup->set_size(Size2(1, 1));
_file_and_folders_fill_popup(file_list_popup, paths, searched_string.length() == 0);
- file_list_popup->set_position(files->get_global_position() + p_pos);
+ file_list_popup->set_position(files->get_screen_position() + p_pos);
+ file_list_popup->reset_size();
file_list_popup->popup();
}
}
@@ -2551,16 +2654,20 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) {
return;
}
+ path = current_path->get_text();
+
file_list_popup->clear();
- file_list_popup->set_size(Size2(1, 1));
+ file_list_popup->reset_size();
file_list_popup->add_icon_item(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")), TTR("New Folder..."), FILE_NEW_FOLDER);
file_list_popup->add_icon_item(get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")), TTR("New Scene..."), FILE_NEW_SCENE);
file_list_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT);
file_list_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE);
+ file_list_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE);
file_list_popup->add_separator();
file_list_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER);
- file_list_popup->set_position(files->get_global_position() + p_pos);
+ file_list_popup->set_position(files->get_screen_position() + p_pos);
+ file_list_popup->reset_size();
file_list_popup->popup();
}
@@ -2586,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);
@@ -2608,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)) {
@@ -2636,10 +2851,10 @@ 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 != String()) {
+ while (!n.is_empty()) {
if (n != "." && n != ".." && !n.ends_with(".import")) {
String npath = p_path + n + (da->current_is_dir() ? "/" : "");
_get_imported_files(npath, files);
@@ -2694,7 +2909,7 @@ void FileSystemDock::_update_import_dock() {
if (cf->has_section_key("remap", "type")) {
type = cf->get_value("remap", "type");
}
- if (import_type == "") {
+ if (import_type.is_empty()) {
import_type = type;
} else if (import_type != type) {
// All should be the same type.
@@ -2705,11 +2920,11 @@ void FileSystemDock::_update_import_dock() {
}
if (imports.size() == 0) {
- EditorNode::get_singleton()->get_import_dock()->clear();
+ ImportDock::get_singleton()->clear();
} else if (imports.size() == 1) {
- EditorNode::get_singleton()->get_import_dock()->set_edit_path(imports[0]);
+ ImportDock::get_singleton()->set_edit_path(imports[0]);
} else {
- EditorNode::get_singleton()->get_import_dock()->set_edit_multiple_paths(imports);
+ ImportDock::get_singleton()->set_edit_multiple_paths(imports);
}
import_dock_needs_update = false;
@@ -2777,16 +2992,17 @@ void FileSystemDock::_bind_methods() {
ADD_SIGNAL(MethodInfo("display_mode_changed"));
}
-FileSystemDock::FileSystemDock(EditorNode *p_editor) {
+FileSystemDock::FileSystemDock() {
+ singleton = this;
set_name("FileSystem");
- editor = p_editor;
path = "res://";
- // `KEY_MASK_CMD | KEY_C` conflicts with other editor shortcuts.
- ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C);
- ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KEY_MASK_CMD | KEY_D);
- ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), KEY_DELETE);
- ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), KEY_F2);
+ // `KeyModifierMask::CMD | Key::C` conflicts with other editor shortcuts.
+ ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::C);
+ ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KeyModifierMask::CMD | Key::D);
+ ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), Key::KEY_DELETE);
+ ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), Key::F2);
+ ED_SHORTCUT_OVERRIDE("filesystem_dock/rename", "macos", Key::ENTER);
VBoxContainer *top_vbc = memnew(VBoxContainer);
add_child(top_vbc);
@@ -2810,7 +3026,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
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);
@@ -2870,6 +3086,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
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);
@@ -2909,7 +3126,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
Label *slabel = memnew(Label);
slabel->set_text(TTR("Scanning Files,\nPlease Wait..."));
- slabel->set_align(Label::ALIGN_CENTER);
+ slabel->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
scanning_vb->add_child(slabel);
scanning_progress = memnew(ProgressBar);
@@ -2918,7 +3135,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
deps_editor = memnew(DependencyEditor);
add_child(deps_editor);
- owners_editor = memnew(DependencyEditorOwners(editor));
+ owners_editor = memnew(DependencyEditorOwners());
add_child(owners_editor);
remove_dialog = memnew(DependencyRemoveDialog);
@@ -2984,6 +3201,9 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
make_script_dialog->set_title(TTR("Create Script"));
add_child(make_script_dialog);
+ make_shader_dialog = memnew(ShaderCreateDialog);
+ add_child(make_shader_dialog);
+
new_resource_dialog = memnew(CreateDialog);
add_child(new_resource_dialog);
new_resource_dialog->set_base_type("Resource");
@@ -2992,10 +3212,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
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;
@@ -3004,9 +3221,8 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
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() {
+ singleton = nullptr;
}