summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/code_editor.cpp2
-rw-r--r--editor/editor_about.cpp4
-rw-r--r--editor/editor_asset_installer.cpp4
-rw-r--r--editor/editor_export.cpp2
-rw-r--r--editor/editor_file_dialog.cpp6
-rw-r--r--editor/editor_settings.cpp34
-rw-r--r--editor/editor_themes.cpp2
-rw-r--r--editor/export_template_manager.cpp2
-rw-r--r--editor/filesystem_dock.cpp341
-rw-r--r--editor/filesystem_dock.h4
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp227
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h37
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp5
-rw-r--r--editor/project_manager.cpp47
-rw-r--r--editor/scene_tree_dock.cpp1
-rw-r--r--editor/spatial_editor_gizmos.cpp24
17 files changed, 428 insertions, 316 deletions
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 33af5927b3..61adff7c9c 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -908,6 +908,8 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_hiding_enabled(EditorSettings::get_singleton()->get("text_editor/line_numbers/code_folding"));
text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/code_folding"));
text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/line_numbers/word_wrap"));
+ text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/line_numbers/draw_minimap"));
+ text_editor->set_minimap_width(EditorSettings::get_singleton()->get("text_editor/line_numbers/minimap_width"));
text_editor->set_draw_info_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_info_gutter"));
text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/open_scripts/smooth_scrolling"));
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index bea1980b09..b2567249d8 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -181,14 +181,14 @@ EditorAbout::EditorAbout() {
// Thirdparty License
VBoxContainer *license_thirdparty = memnew(VBoxContainer);
- license_thirdparty->set_name(TTR("Thirdparty License"));
+ license_thirdparty->set_name(TTR("Third-party Licenses"));
license_thirdparty->set_h_size_flags(Control::SIZE_EXPAND_FILL);
tc->add_child(license_thirdparty);
Label *tpl_label = memnew(Label);
tpl_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
tpl_label->set_autowrap(true);
- tpl_label->set_text(TTR("Godot Engine relies on a number of thirdparty free and open source libraries, all compatible with the terms of its MIT license. The following is an exhaustive list of all such thirdparty components with their respective copyright statements and license terms."));
+ tpl_label->set_text(TTR("Godot Engine relies on a number of third-party free and open source libraries, all compatible with the terms of its MIT license. The following is an exhaustive list of all such third-party components with their respective copyright statements and license terms."));
tpl_label->set_size(Size2(630, 1) * EDSCALE);
license_thirdparty->add_child(tpl_label);
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index b706f2cae6..98e670f952 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -90,7 +90,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io);
if (!pkg) {
- error->set_text(TTR("Error opening package file, not in zip format."));
+ error->set_text(TTR("Error opening package file, not in ZIP format."));
return;
}
@@ -217,7 +217,7 @@ void EditorAssetInstaller::ok_pressed() {
unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io);
if (!pkg) {
- error->set_text(TTR("Error opening package file, not in zip format."));
+ error->set_text(TTR("Error opening package file, not in ZIP format."));
return;
}
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index cb1754bb10..e2a750cf08 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -30,11 +30,11 @@
#include "editor_export.h"
+#include "core/crypto/crypto_core.h"
#include "core/io/config_file.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/zip_io.h"
-#include "core/math/crypto_core.h"
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/project_settings.h"
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 8c9aedc7b7..80aeeef868 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -257,7 +257,7 @@ void EditorFileDialog::_post_popup() {
if (is_visible_in_tree()) {
Ref<Texture> folder = get_icon("folder", "FileDialog");
- const Color folder_color = get_color("folder", "FileDialog");
+ const Color folder_color = get_color("folder_icon_modulate", "FileDialog");
recent->clear();
bool res = access == ACCESS_RESOURCES;
@@ -736,7 +736,7 @@ void EditorFileDialog::update_file_list() {
dir_access->list_dir_begin();
Ref<Texture> folder = get_icon("folder", "FileDialog");
- const Color folder_color = get_color("folder", "FileDialog");
+ const Color folder_color = get_color("folder_icon_modulate", "FileDialog");
List<String> files;
List<String> dirs;
@@ -1204,7 +1204,7 @@ void EditorFileDialog::_update_favorites() {
String current = get_current_dir();
Ref<Texture> folder_icon = get_icon("Folder", "EditorIcons");
- const Color folder_color = get_color("folder", "FileDialog");
+ const Color folder_color = get_color("folder_icon_modulate", "FileDialog");
favorites->clear();
favorite->set_pressed(false);
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 3bd333692f..61668d55be 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -448,6 +448,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/line_numbers/show_info_gutter", true);
_initial_set("text_editor/line_numbers/code_folding", true);
_initial_set("text_editor/line_numbers/word_wrap", false);
+ _initial_set("text_editor/line_numbers/draw_minimap", false);
+ _initial_set("text_editor/line_numbers/minimap_width", 80);
+ hints["text_editor/line_numbers/minimap_width"] = PropertyInfo(Variant::INT, "text_editor/line_numbers/minimap_width", PROPERTY_HINT_RANGE, "50,250,1");
_initial_set("text_editor/line_numbers/show_line_length_guideline", false);
_initial_set("text_editor/line_numbers/line_length_guideline_column", 80);
hints["text_editor/line_numbers/line_length_guideline_column"] = PropertyInfo(Variant::INT, "text_editor/line_numbers/line_length_guideline_column", PROPERTY_HINT_RANGE, "20, 160, 1");
@@ -561,6 +564,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// 2D
_initial_set("editors/2d/grid_color", Color(1.0, 1.0, 1.0, 0.07));
_initial_set("editors/2d/guides_color", Color(0.6, 0.0, 0.8));
+ _initial_set("editors/2d/smart_snapping_line_color", Color(0.9, 0.1, 0.1));
_initial_set("editors/2d/bone_width", 5);
_initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9));
_initial_set("editors/2d/bone_color2", Color(0.6, 0.6, 0.6, 0.9));
@@ -608,6 +612,18 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("run/output/always_open_output_on_play", true);
_initial_set("run/output/always_close_output_on_stop", false);
+ /* Network */
+
+ // Debug
+ _initial_set("network/debug/remote_host", "127.0.0.1"); // Hints provided in setup_network
+
+ _initial_set("network/debug/remote_port", 6007);
+ hints["network/debug/remote_port"] = PropertyInfo(Variant::INT, "network/debug/remote_port", PROPERTY_HINT_RANGE, "1,65535,1");
+
+ // SSL
+ _initial_set("network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH);
+ hints["network/ssl/editor_ssl_certificates"] = PropertyInfo(Variant::STRING, "network/ssl/editor_ssl_certificates", PROPERTY_HINT_GLOBAL_FILE, "*.crt,*.pem");
+
/* Extra config */
_initial_set("project_manager/sorting_order", 0);
@@ -993,11 +1009,11 @@ void EditorSettings::setup_network() {
List<IP_Address> local_ip;
IP::get_singleton()->get_local_addresses(&local_ip);
- String lip = "127.0.0.1";
String hint;
String current = has_setting("network/debug/remote_host") ? get("network/debug/remote_host") : "";
- int port = has_setting("network/debug/remote_port") ? (int)get("network/debug/remote_port") : 6007;
+ String selected = "127.0.0.1";
+ // Check that current remote_host is a valid interface address and populate hints.
for (List<IP_Address>::Element *E = local_ip.front(); E; E = E->next()) {
String ip = E->get();
@@ -1008,22 +1024,18 @@ void EditorSettings::setup_network() {
// Same goes for IPv4 link-local (APIPA) addresses.
if (ip.begins_with("169.254.")) // 169.254.0.0/16
continue;
+ // Select current IP (found)
if (ip == current)
- lip = current; //so it saves
+ selected = ip;
if (hint != "")
hint += ",";
hint += ip;
}
- _initial_set("network/debug/remote_host", lip);
+ // Add hints with valid IP addresses to remote_host property.
add_property_hint(PropertyInfo(Variant::STRING, "network/debug/remote_host", PROPERTY_HINT_ENUM, hint));
-
- _initial_set("network/debug/remote_port", port);
- add_property_hint(PropertyInfo(Variant::INT, "network/debug/remote_port", PROPERTY_HINT_RANGE, "1,65535,1"));
-
- // Editor SSL certificates override
- _initial_set("network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH);
- add_property_hint(PropertyInfo(Variant::STRING, "network/ssl/editor_ssl_certificates", PROPERTY_HINT_GLOBAL_FILE, "*.crt,*.pem"));
+ // Fix potentially invalid remote_host due to network change.
+ set("network/debug/remote_host", selected);
}
void EditorSettings::save() {
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index d962001b38..56eed96e31 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1068,7 +1068,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("folder", "FileDialog", theme->get_icon("Folder", "EditorIcons"));
// Use a different color for folder icons to make them easier to distinguish from files.
// On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color.
- theme->set_color("folder", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(5, 5, 5)).linear_interpolate(accent_color, 0.7));
+ theme->set_color("folder_icon_modulate", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(5, 5, 5)).linear_interpolate(accent_color, 0.7));
theme->set_color("files_disabled", "FileDialog", font_color_disabled);
// color picker
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 68e859966c..1447a143d4 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -590,7 +590,7 @@ Error ExportTemplateManager::install_android_template() {
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
unzFile pkg = unzOpen2(source_zip.utf8().get_data(), &io);
- ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android sources not in zip format.");
+ ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android sources not in ZIP format.");
int ret = unzGoToFirstFile(pkg);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 83904800e9..84631f3e38 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -53,10 +53,9 @@ Ref<Texture> FileSystemDock::_get_tree_item_icon(EditorFileSystemDirectory *p_di
}
bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites) {
-
bool parent_should_expand = false;
- // Create a tree item for the subdirectory
+ // Create a tree item for the subdirectory.
TreeItem *subdirectory_item = tree->create_item(p_parent);
String dname = p_dir->get_name();
if (dname == "")
@@ -64,7 +63,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
subdirectory_item->set_text(0, dname);
subdirectory_item->set_icon(0, get_icon("Folder", "EditorIcons"));
- subdirectory_item->set_icon_color(0, get_color("folder", "FileDialog"));
+ subdirectory_item->set_icon_color(0, get_color("folder_icon_modulate", "FileDialog"));
subdirectory_item->set_selectable(0, true);
String lpath = p_dir->get_path();
subdirectory_item->set_metadata(0, lpath);
@@ -81,28 +80,28 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
parent_should_expand = true;
}
- // Create items for all subdirectories
+ // Create items for all subdirectories.
for (int i = 0; i < p_dir->get_subdir_count(); i++)
parent_should_expand = (_create_tree(subdirectory_item, p_dir->get_subdir(i), uncollapsed_paths, p_select_in_favorites) || parent_should_expand);
- // Create all items for the files in the subdirectory
+ // Create all items for the files in the subdirectory.
if (display_mode == DISPLAY_MODE_TREE_ONLY) {
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 type is disabled, file won't be displayed.
+ // If type is disabled, file won't be displayed.
continue;
}
String file_name = p_dir->get_file(i);
if (searched_string.length() > 0) {
if (file_name.to_lower().find(searched_string) < 0) {
- // The searched string is not in the file name, we skip it
+ // The searched string is not in the file name, we skip it.
continue;
} else {
- // We expand all parents
+ // We expand all parents.
parent_should_expand = true;
}
}
@@ -135,7 +134,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
}
Vector<String> FileSystemDock::_compute_uncollapsed_paths() {
- // Register currently collapsed paths
+ // Register currently collapsed paths.
Vector<String> uncollapsed_paths;
TreeItem *root = tree->get_root();
if (root) {
@@ -166,14 +165,13 @@ Vector<String> FileSystemDock::_compute_uncollapsed_paths() {
}
void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, bool p_uncollapse_root, bool p_select_in_favorites) {
-
- // Recreate the tree
+ // Recreate the tree.
tree->clear();
tree_update_id++;
updating_tree = true;
TreeItem *root = tree->create_item();
- // Handles the favorites
+ // Handles the favorites.
TreeItem *favorites = tree->create_item(root);
favorites->set_icon(0, get_icon("Favorites", "EditorIcons"));
favorites->set_text(0, TTR("Favorites:"));
@@ -187,7 +185,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
continue;
Ref<Texture> folder_icon = get_icon("Folder", "EditorIcons");
- const Color folder_color = get_color("folder", "FileDialog");
+ const Color folder_color = get_color("folder_icon_modulate", "FileDialog");
String text;
Ref<Texture> icon;
@@ -238,7 +236,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
uncollapsed_paths.push_back("res://");
}
- // Create the remaining of the tree
+ // Create the remaining of the tree.
_create_tree(root, EditorFileSystem::get_singleton()->get_filesystem(), uncollapsed_paths, p_select_in_favorites);
tree->ensure_cursor_is_visible();
updating_tree = false;
@@ -250,7 +248,7 @@ void FileSystemDock::set_display_mode(DisplayMode p_display_mode) {
}
void FileSystemDock::_update_display_mode(bool p_force) {
- // Compute the new display mode
+ // Compute the new display mode.
if (p_force || old_display_mode != display_mode) {
button_toggle_display_mode->set_pressed(display_mode == DISPLAY_MODE_SPLIT);
switch (display_mode) {
@@ -283,11 +281,8 @@ void FileSystemDock::_update_display_mode(bool p_force) {
}
void FileSystemDock::_notification(int p_what) {
-
switch (p_what) {
-
case NOTIFICATION_ENTER_TREE: {
-
if (initialized)
return;
initialized = true;
@@ -327,18 +322,15 @@ void FileSystemDock::_notification(int p_what) {
} else {
_update_tree(Vector<String>(), true);
}
-
} break;
+
case NOTIFICATION_PROCESS: {
if (EditorFileSystem::get_singleton()->is_scanning()) {
scanning_progress->set_value(EditorFileSystem::get_singleton()->get_scanning_progress() * 100);
}
} break;
- case NOTIFICATION_EXIT_TREE: {
- } break;
case NOTIFICATION_DRAG_BEGIN: {
-
Dictionary dd = get_viewport()->gui_get_drag_data();
if (tree->is_visible_in_tree() && dd.has("type")) {
if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) {
@@ -347,20 +339,20 @@ void FileSystemDock::_notification(int p_what) {
tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
}
}
-
} break;
- case NOTIFICATION_DRAG_END: {
+ case NOTIFICATION_DRAG_END: {
tree->set_drop_mode_flags(0);
-
} break;
+
case NOTIFICATION_THEME_CHANGED: {
if (is_visible_in_tree()) {
_update_display_mode(true);
}
} break;
+
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- // Update icons
+ // Update icons.
String ei = "EditorIcons";
button_reload->set_icon(get_icon("Reload", ei));
button_toggle_display_mode->set_icon(get_icon("Panels2", ei));
@@ -377,48 +369,47 @@ void FileSystemDock::_notification(int p_what) {
file_list_search_box->set_right_icon(get_icon("Search", ei));
file_list_search_box->set_clear_button_enabled(true);
- // Update always showfolders
+ // Update always show folders.
bool new_always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
if (new_always_show_folders != always_show_folders) {
always_show_folders = new_always_show_folders;
_update_file_list(true);
}
- // Change full tree mode
+ // Change full tree mode.
_update_display_mode();
-
} break;
}
}
void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_selected) {
- // Update the import dock
+ // Update the import dock.
import_dock_needs_update = true;
call_deferred("_update_import_dock");
- // Return if we don't select something new
+ // Return if we don't select something new.
if (!p_selected)
return;
- // Tree item selected
+ // Tree item selected.
TreeItem *selected = tree->get_selected();
if (!selected)
return;
TreeItem *favorites_item = tree->get_root()->get_children();
if (selected->get_parent() == favorites_item && !String(selected->get_metadata(0)).ends_with("/")) {
- // Go to the favorites if we click in the favorites and the path has changed
+ // Go to the favorites if we click in the favorites and the path has changed.
path = "Favorites";
} else {
path = selected->get_metadata(0);
- // Note: the "Favorites" item also leads to this path
+ // Note: the "Favorites" item also leads to this path.
}
- // Set the current path
+ // Set the current path.
_set_current_path_text(path);
_push_to_history();
- // Update the file list
+ // Update the file list.
if (!updating_tree && display_mode == DISPLAY_MODE_SPLIT) {
_update_file_list(false);
}
@@ -432,7 +423,6 @@ String FileSystemDock::get_selected_path() const {
}
String FileSystemDock::get_current_path() const {
-
return path;
}
@@ -491,7 +481,6 @@ void FileSystemDock::navigate_to_path(const String &p_path) {
}
void FileSystemDock::_file_list_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
-
if ((file_list_vb->is_visible_in_tree() || path == p_path.get_base_dir()) && p_preview.is_valid()) {
Array uarr = p_udata;
int idx = uarr[0];
@@ -539,7 +528,6 @@ void FileSystemDock::_set_file_display(bool p_active) {
}
bool FileSystemDock::_is_file_type_disabled_by_feature_profile(const StringName &p_class) {
-
Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
if (profile.is_null()) {
return false;
@@ -559,7 +547,6 @@ bool FileSystemDock::_is_file_type_disabled_by_feature_profile(const StringName
}
void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *matches, int p_max_items) {
-
if (matches->size() > p_max_items)
return;
@@ -577,10 +564,9 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
fi.type = p_path->get_file_type(i);
fi.path = p_path->get_file_path(i);
fi.import_broken = !p_path->get_file_import_is_valid(i);
- fi.import_status = 0;
if (_is_file_type_disabled_by_feature_profile(fi.type)) {
- //this type is disabled, will not appear here
+ // This type is disabled, will not appear here.
continue;
}
@@ -592,8 +578,7 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
}
void FileSystemDock::_update_file_list(bool p_keep_selection) {
-
- // Register the previously selected items
+ // Register the previously selected items.
Set<String> cselection;
if (p_keep_selection) {
for (int i = 0; i < files->get_item_count(); i++) {
@@ -619,7 +604,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
bool use_thumbnails = (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS);
if (use_thumbnails) {
- // Thumbnails mode
+ // Thumbnails mode.
files->set_max_columns(0);
files->set_icon_mode(ItemList::ICON_MODE_TOP);
files->set_fixed_column_width(thumbnail_size * 3 / 2);
@@ -636,8 +621,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
file_thumbnail_broken = get_icon("FileDeadBigThumb", ei);
}
} else {
-
- // No thumbnails
+ // No thumbnails.
files->set_icon_mode(ItemList::ICON_MODE_LEFT);
files->set_max_columns(1);
files->set_max_text_lines(1);
@@ -646,12 +630,12 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
}
Ref<Texture> folder_icon = (use_thumbnails) ? folder_thumbnail : get_icon("folder", "FileDialog");
- const Color folder_color = get_color("folder", "FileDialog");
+ const Color folder_color = get_color("folder_icon_modulate", "FileDialog");
- // Build the FileInfo list
+ // Build the FileInfo list.
List<FileInfo> filelist;
if (path == "Favorites") {
- // Display the favorites
+ // Display the favorites.
Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
for (int i = 0; i < favorites.size(); i++) {
String favorite = favorites[i];
@@ -685,7 +669,6 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
fi.type = "";
fi.import_broken = true;
}
- fi.import_status = 0;
if (searched_string.length() == 0 || fi.name.to_lower().find(searched_string) >= 0) {
filelist.push_back(fi);
@@ -693,8 +676,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
}
}
} else {
-
- // Get infos on the directory + file
+ // Get infos on the directory + file.
if (directory.ends_with("/") && directory != "res://") {
directory = directory.substr(0, directory.length() - 1);
}
@@ -708,13 +690,11 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
return;
if (searched_string.length() > 0) {
- // Display the search results
+ // Display the search results.
_search(EditorFileSystem::get_singleton()->get_filesystem(), &filelist, 128);
} else {
-
if (display_mode == DISPLAY_MODE_TREE_ONLY || always_show_folders) {
- // Display folders in the list
-
+ // Display folders in the list.
if (directory != "res://") {
files->add_item("..", folder_icon, true);
@@ -728,7 +708,6 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
}
for (int i = 0; i < efd->get_subdir_count(); i++) {
-
String dname = efd->get_subdir(i)->get_name();
files->add_item(dname, folder_icon, true);
@@ -741,15 +720,13 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
}
}
- // Display the folder content
+ // Display the folder content.
for (int i = 0; i < efd->get_file_count(); i++) {
-
FileInfo fi;
fi.name = efd->get_file(i);
fi.path = directory.plus_file(fi.name);
fi.type = efd->get_file_type(i);
fi.import_broken = !efd->get_file_import_is_valid(i);
- fi.import_status = 0;
filelist.push_back(fi);
}
@@ -757,7 +734,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
filelist.sort();
}
- // Fills the ItemList control node from the FileInfos
+ // Fills the ItemList control node from the FileInfos.
String oi = "Object";
for (List<FileInfo>::Element *E = filelist.front(); E; E = E->next()) {
FileInfo *finfo = &(E->get());
@@ -770,7 +747,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
String tooltip = fpath;
- // Select the icons
+ // Select the icons.
if (!finfo->import_broken) {
type_icon = (has_icon(ftype, ei)) ? get_icon(ftype, ei) : get_icon(oi, ei);
big_icon = file_thumbnail;
@@ -780,7 +757,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
tooltip += "\n" + TTR("Status: Import of file failed. Please fix file and reimport manually.");
}
- // Add the item to the ItemList
+ // Add the item to the ItemList.
int item_index;
if (use_thumbnails) {
files->add_item(fname, big_icon, true);
@@ -794,7 +771,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->set_item_metadata(item_index, fpath);
}
- // Generate the preview
+ // Generate the preview.
if (!finfo->import_broken) {
Array udata;
udata.resize(2);
@@ -803,7 +780,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
EditorResourcePreview::get_singleton()->queue_resource_preview(fpath, this, "_file_list_thumbnail_done", udata);
}
- // Select the items
+ // Select the items.
if (cselection.has(fname))
files->select(item_index, false);
@@ -812,7 +789,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->ensure_current_is_visible();
}
- // Tooltip
+ // Tooltip.
if (finfo->sources.size()) {
for (int j = 0; j < finfo->sources.size(); j++) {
tooltip += "\nSource: " + finfo->sources[j];
@@ -859,13 +836,12 @@ void FileSystemDock::_file_list_activate_file(int p_idx) {
}
void FileSystemDock::_preview_invalidated(const String &p_path) {
-
if (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && searched_string.length() == 0 && file_list_vb->is_visible_in_tree()) {
for (int i = 0; i < files->get_item_count(); i++) {
if (files->get_item_metadata(i) == p_path) {
- //re-request preview
+ // Re-request preview.
Array udata;
udata.resize(2);
udata[0] = i;
@@ -878,7 +854,6 @@ void FileSystemDock::_preview_invalidated(const String &p_path) {
}
void FileSystemDock::_fs_changed() {
-
button_hist_prev->set_disabled(history_pos == 0);
button_hist_next->set_disabled(history_pos == history.size() - 1);
scanning_vb->hide();
@@ -896,7 +871,6 @@ void FileSystemDock::_fs_changed() {
}
void FileSystemDock::_set_scanning_mode() {
-
button_hist_prev->set_disabled(true);
button_hist_next->set_disabled(true);
split_box->hide();
@@ -910,7 +884,6 @@ void FileSystemDock::_set_scanning_mode() {
}
void FileSystemDock::_fw_history() {
-
if (history_pos < history.size() - 1)
history_pos++;
@@ -988,7 +961,7 @@ void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, const Map<Str
void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_new_path,
Map<String, String> &p_file_renames, Map<String, String> &p_folder_renames) {
- //Ensure folder paths end with "/"
+ // Ensure folder paths end with "/".
String old_path = (p_item.is_file || p_item.path.ends_with("/")) ? p_item.path : (p_item.path + "/");
String new_path = (p_item.is_file || p_new_path.ends_with("/")) ? p_new_path : (p_new_path + "/");
@@ -998,12 +971,12 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
EditorNode::get_singleton()->add_io_error(TTR("Cannot move/rename resources root."));
return;
} else if (!p_item.is_file && new_path.begins_with(old_path)) {
- //This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/"
+ // This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/".
EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.") + "\n" + old_path + "\n");
return;
}
- //Build a list of files which will have new paths as a result of this operation
+ // Build a list of files which will have new paths as a result of this operation.
Vector<String> file_changed_paths;
Vector<String> folder_changed_paths;
if (p_item.is_file) {
@@ -1017,8 +990,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
print_verbose("Moving " + old_path + " -> " + new_path);
Error err = da->rename(old_path, new_path);
if (err == OK) {
-
- //Move/Rename any corresponding import settings too
+ // Move/Rename any corresponding import settings too.
if (p_item.is_file && FileAccess::exists(old_path + ".import")) {
err = da->rename(old_path + ".import", new_path + ".import");
if (err != OK) {
@@ -1026,7 +998,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
}
}
- // update scene if it is open
+ // 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])) {
@@ -1041,7 +1013,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
}
}
- //Only treat as a changed dependency if it was successfully moved
+ // Only treat as a changed dependency if it was successfully moved.
for (int i = 0; i < file_changed_paths.size(); ++i) {
p_file_renames[file_changed_paths[i]] = file_changed_paths[i].replace_first(old_path, new_path);
print_verbose(" Remap: " + file_changed_paths[i] + " -> " + p_file_renames[file_changed_paths[i]]);
@@ -1058,7 +1030,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
}
void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const {
- //Ensure folder paths end with "/"
+ // Ensure folder paths end with "/".
String old_path = (p_item.is_file || p_item.path.ends_with("/")) ? p_item.path : (p_item.path + "/");
String new_path = (p_item.is_file || p_new_path.ends_with("/")) ? p_new_path : (p_new_path + "/");
@@ -1068,7 +1040,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
EditorNode::get_singleton()->add_io_error(TTR("Cannot move/rename resources root."));
return;
} else if (!p_item.is_file && new_path.begins_with(old_path)) {
- //This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/"
+ // This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/".
EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.") + "\n" + old_path + "\n");
return;
}
@@ -1077,7 +1049,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
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) {
- //Move/Rename any corresponding import settings too
+ // Move/Rename any corresponding import settings too.
if (p_item.is_file && FileAccess::exists(old_path + ".import")) {
err = da->copy(old_path + ".import", new_path + ".import");
if (err != OK) {
@@ -1091,13 +1063,11 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
}
void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> &p_renames) const {
-
- //Rename all resources loaded, be it subresources or actual resources
+ // Rename all resources loaded, be it subresources or actual resources.
List<Ref<Resource> > cached;
ResourceCache::get_cached_resources(&cached);
for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) {
-
Ref<Resource> r = E->get();
String base_path = r->get_path();
@@ -1116,7 +1086,6 @@ void FileSystemDock::_update_resource_paths_after_move(const Map<String, String>
}
for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {
-
String path;
if (i == EditorNode::get_editor_data().get_edited_scene()) {
if (!get_tree()->get_edited_scene_root())
@@ -1124,7 +1093,6 @@ void FileSystemDock::_update_resource_paths_after_move(const Map<String, String>
path = get_tree()->get_edited_scene_root()->get_filename();
} else {
-
path = EditorNode::get_editor_data().get_scene_path(i);
}
@@ -1133,23 +1101,21 @@ 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);
} else {
-
EditorNode::get_editor_data().set_scene_path(i, path);
}
}
}
void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const {
- //The following code assumes that the following holds:
+ // The following code assumes that the following holds:
// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
// 2) ResourceLoader can use the new paths without needing to call rescan.
Vector<String> remaps;
_find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), p_renames, remaps);
for (int i = 0; i < remaps.size(); ++i) {
- //Because we haven't called a rescan yet the found remap might still be an old path itself.
+ // Because we haven't called a rescan yet the found remap might still be an old path itself.
String file = p_renames.has(remaps[i]) ? p_renames[remaps[i]] : remaps[i];
print_verbose("Remapping dependencies for: " + file);
Error err = ResourceLoader::rename_dependencies(file, p_renames);
@@ -1163,8 +1129,7 @@ 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
+ // 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) {
@@ -1195,7 +1160,6 @@ void FileSystemDock::_update_project_settings_after_move(const Map<String, Strin
}
void FileSystemDock::_update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const {
-
Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
Vector<String> new_favorites;
@@ -1311,7 +1275,6 @@ void FileSystemDock::_folder_deleted(String p_folder) {
}
void FileSystemDock::_rename_operation_confirm() {
-
String new_name = rename_dialog_text->get_text().strip_edges();
if (new_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
@@ -1331,10 +1294,10 @@ void FileSystemDock::_rename_operation_confirm() {
EditorFileSystem::get_singleton()->move_group_file(old_path, new_path);
}
- //Present a more user friendly warning for name conflict
+ // Present a more user friendly warning for name conflict.
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
- // Workaround case insensitivity on Windows
+ // Workaround case insensitivity on Windows.
if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) {
#else
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
@@ -1366,7 +1329,6 @@ void FileSystemDock::_rename_operation_confirm() {
}
void FileSystemDock::_duplicate_operation_confirm() {
-
String new_name = duplicate_dialog_text->get_text().strip_edges();
if (new_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
@@ -1384,7 +1346,7 @@ void FileSystemDock::_duplicate_operation_confirm() {
String new_path = base_dir.plus_file(new_name);
- //Present a more user friendly warning for name conflict
+ // Present a more user friendly warning for name conflict
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."));
@@ -1395,7 +1357,7 @@ void FileSystemDock::_duplicate_operation_confirm() {
_try_duplicate_item(to_duplicate, new_path);
- //Rescan everything
+ // Rescan everything.
print_verbose("FileSystem: calling rescan.");
_rescan();
}
@@ -1428,14 +1390,14 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw
to_move_path = p_to_path;
bool can_move = _check_existing();
if (!can_move) {
- //ask to do something
+ // Ask to do something.
overwrite_dialog->popup_centered_minsize();
overwrite_dialog->grab_focus();
return;
}
}
- //check groups
+ // Check groups.
for (int i = 0; i < to_move.size(); i++) {
print_line("is group: " + to_move[i].path + ": " + itos(EditorFileSystem::get_singleton()->is_group_file(to_move[i].path)));
@@ -1476,7 +1438,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw
}
Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) {
- // Build a list of selected items with the active one at the first position
+ // Build a list of selected items with the active one at the first position.
Vector<String> selected_strings;
TreeItem *favorites_item = tree->get_root()->get_children();
@@ -1494,8 +1456,15 @@ Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) {
selected = tree->get_next_selected(selected);
}
- // Remove paths or files that are included into another
- if (remove_self_inclusion && selected_strings.size() > 1) {
+ if (remove_self_inclusion) {
+ selected_strings = _remove_self_included_paths(selected_strings);
+ }
+ return selected_strings;
+}
+
+Vector<String> FileSystemDock::_remove_self_included_paths(Vector<String> selected_strings) {
+ // Remove paths or files that are included into another.
+ if (selected_strings.size() > 1) {
selected_strings.sort_custom<NaturalNoCaseComparator>();
String last_path = "";
for (int i = 0; i < selected_strings.size(); i++) {
@@ -1512,10 +1481,9 @@ Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) {
}
void FileSystemDock::_tree_rmb_option(int p_option) {
+ Vector<String> selected_strings = _tree_get_selected(false);
- Vector<String> selected_strings = _tree_get_selected();
-
- // Execute the current option
+ // Execute the current option.
switch (p_option) {
case FOLDER_EXPAND_ALL:
case FOLDER_COLLAPSE_ALL: {
@@ -1555,11 +1523,11 @@ void FileSystemDock::_file_list_rmb_option(int p_option) {
}
void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected) {
- // The first one should be the active item
+ // The first one should be the active item.
switch (p_option) {
case FILE_SHOW_IN_EXPLORER: {
- // Show the file / folder in the OS explorer
+ // Show the file/folder in the OS explorer.
String fpath = path;
if (path == "Favorites") {
fpath = p_selected[0];
@@ -1573,7 +1541,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_OPEN: {
- // Open folders
+ // Open folders.
TreeItem *selected = tree->get_root();
selected = tree->get_next_selected(selected);
while (selected) {
@@ -1582,21 +1550,21 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
}
selected = tree->get_next_selected(selected);
}
- // Open the file
+ // Open the file.
for (int i = 0; i < p_selected.size(); i++) {
_select_file(p_selected[i]);
}
} break;
case FILE_INHERIT: {
- // Create a new scene inherited from the selected one
+ // Create a new scene inherited from the selected one.
if (p_selected.size() == 1) {
emit_signal("inherit", p_selected[0]);
}
} break;
case FILE_INSTANCE: {
- // Instance all selected scenes
+ // Instance all selected scenes.
Vector<String> paths;
for (int i = 0; i < p_selected.size(); i++) {
String fpath = p_selected[i];
@@ -1610,7 +1578,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_ADD_FAVORITE: {
- // Add the files from favorites
+ // 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) {
@@ -1622,7 +1590,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_REMOVE_FAVORITE: {
- // Remove the files from favorites
+ // Remove the files from favorites.
Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
for (int i = 0; i < p_selected.size(); i++) {
favorites.erase(p_selected[i]);
@@ -1634,7 +1602,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_DEPENDENCIES: {
- // Checkout the file dependencies
+ // Checkout the file dependencies.
if (!p_selected.empty()) {
String fpath = p_selected[0];
deps_editor->edit(fpath);
@@ -1642,7 +1610,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_OWNERS: {
- // Checkout the file owners
+ // Checkout the file owners.
if (!p_selected.empty()) {
String fpath = p_selected[0];
owners_editor->show(fpath);
@@ -1650,10 +1618,11 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_MOVE: {
- // Move the files to a given location
+ // Move the files to a given location.
to_move.clear();
- for (int i = 0; i < p_selected.size(); i++) {
- String fpath = p_selected[i];
+ Vector<String> collapsed_paths = _remove_self_included_paths(p_selected);
+ for (int i = collapsed_paths.size() - 1; i >= 0; i--) {
+ String fpath = collapsed_paths[i];
if (fpath != "res://") {
to_move.push_back(FileOrFolder(fpath, !fpath.ends_with("/")));
}
@@ -1664,7 +1633,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_RENAME: {
- // Rename the active file
+ // Rename the active file.
if (!p_selected.empty()) {
to_rename.path = p_selected[0];
if (to_rename.path != "res://") {
@@ -1687,12 +1656,13 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_REMOVE: {
- // Remove the selected files
+ // Remove the selected files.
Vector<String> remove_files;
Vector<String> remove_folders;
+ Vector<String> collapsed_paths = _remove_self_included_paths(p_selected);
- for (int i = 0; i < p_selected.size(); i++) {
- String fpath = p_selected[i];
+ for (int i = 0; i < collapsed_paths.size(); i++) {
+ String fpath = collapsed_paths[i];
if (fpath != "res://") {
if (fpath.ends_with("/")) {
remove_folders.push_back(fpath);
@@ -1708,7 +1678,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_DUPLICATE: {
- // Duplicate the selected files
+ // Duplicate the selected files.
for (int i = 0; i < p_selected.size(); i++) {
to_duplicate.path = p_selected[i];
to_duplicate.is_file = !to_duplicate.path.ends_with("/");
@@ -1733,7 +1703,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_REIMPORT: {
- // Reimport all selected files
+ // Reimport all selected files.
Vector<String> reimport;
for (int i = 0; i < p_selected.size(); i++) {
reimport.push_back(p_selected[i]);
@@ -1743,7 +1713,6 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_NEW_FOLDER: {
- // Create a new folder
make_dir_dialog_text->set_text("new folder");
make_dir_dialog_text->select_all();
make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
@@ -1758,7 +1727,6 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_NEW_SCRIPT: {
- // Create a new script
String fpath = path;
if (!fpath.ends_with("/")) {
fpath = fpath.get_base_dir();
@@ -1768,7 +1736,6 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_COPY_PATH: {
- // Copy the file path
if (!p_selected.empty()) {
String fpath = p_selected[0];
OS::get_singleton()->set_clipboard(fpath);
@@ -1776,7 +1743,6 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_NEW_RESOURCE: {
- // Create a new resource
new_resource_dialog->popup_create(true);
} break;
}
@@ -1804,7 +1770,7 @@ void FileSystemDock::_resource_created() const {
void FileSystemDock::_search_changed(const String &p_text, const Control *p_from) {
if (searched_string.length() == 0 && p_text.length() > 0) {
- // Register the uncollapsed paths before they change
+ // Register the uncollapsed paths before they change.
uncollapsed_paths_before_search = _compute_uncollapsed_paths();
}
@@ -1812,7 +1778,7 @@ void FileSystemDock::_search_changed(const String &p_text, const Control *p_from
if (p_from == tree_search_box)
file_list_search_box->set_text(searched_string);
- else // file_list_search_box
+ else // File_list_search_box.
tree_search_box->set_text(searched_string);
switch (display_mode) {
@@ -1827,7 +1793,6 @@ void FileSystemDock::_search_changed(const String &p_text, const Control *p_from
}
void FileSystemDock::_rescan() {
-
_set_scanning_mode();
EditorFileSystem::get_singleton()->scan();
}
@@ -1842,12 +1807,10 @@ void FileSystemDock::fix_dependencies(const String &p_for_file) {
}
void FileSystemDock::focus_on_filter() {
-
file_list_search_box->grab_focus();
}
void FileSystemDock::set_file_list_display_mode(FileListDisplayMode p_mode) {
-
if (p_mode == file_list_display_mode)
return;
@@ -1861,12 +1824,12 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from)
Vector<String> paths;
if (p_from == tree) {
- // Check if the first selected is in favorite
+ // Check if the first selected is in favorite.
TreeItem *selected = tree->get_next_selected(tree->get_root());
while (selected) {
TreeItem *favorites_item = tree->get_root()->get_children();
if (selected == favorites_item) {
- // The "Favorites" item is not draggable
+ // The "Favorites" item is not draggable.
return Variant();
}
@@ -1904,12 +1867,11 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from)
}
bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
-
Dictionary drag_data = p_data;
if (drag_data.has("type") && String(drag_data["type"]) == "favorite") {
- // Moving favorite around
+ // Moving favorite around.
TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return false;
@@ -1920,20 +1882,20 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
TreeItem *resources_item = favorites_item->get_next();
if (ti == favorites_item) {
- return (drop_section == 1); // The parent, first fav
+ return (drop_section == 1); // The parent, first fav.
}
if (ti->get_parent() && favorites_item == ti->get_parent()) {
return true; // A favorite
}
if (ti == resources_item) {
- return (drop_section == -1); // The tree, last fav
+ return (drop_section == -1); // The tree, last fav.
}
return false;
}
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
- // Move resources
+ // Move resources.
String to_dir;
bool favorite;
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
@@ -1941,7 +1903,7 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
- // Move files or dir
+ // Move files or dir.
String to_dir;
bool favorite;
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
@@ -1952,8 +1914,8 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
if (to_dir.empty())
return false;
- //Attempting to move a folder into itself will fail later
- //Rather than bring up a message don't try to do it in the first place
+ // Attempting to move a folder into itself will fail later,
+ // rather than bring up a message don't try to do it in the first place
to_dir = to_dir.ends_with("/") ? to_dir : (to_dir + "/");
Vector<String> fnames = drag_data["files"];
for (int i = 0; i < fnames.size(); ++i) {
@@ -1968,7 +1930,6 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
}
void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
-
if (!can_drop_data_fw(p_point, p_data, p_from))
return;
Dictionary drag_data = p_data;
@@ -1976,7 +1937,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
Vector<String> dirs = EditorSettings::get_singleton()->get_favorites();
if (drag_data.has("type") && String(drag_data["type"]) == "favorite") {
- // Moving favorite around
+ // Moving favorite around.
TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return;
@@ -1988,20 +1949,20 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
TreeItem *resources_item = favorites_item->get_next();
if (ti == favorites_item) {
- // Drop on the favorite folder
+ // Drop on the favorite folder.
drop_position = 0;
} else if (ti == resources_item) {
- // Drop on the resource item
+ // Drop on the resource item.
drop_position = dirs.size();
} else {
- // Drop in the list
+ // Drop in the list.
drop_position = dirs.find(ti->get_metadata(0));
if (drop_section == 1) {
drop_position++;
}
}
- // Remove dragged favorites
+ // Remove dragged favorites.
Vector<int> to_remove;
int offset = 0;
for (int i = 0; i < files.size(); i++) {
@@ -2017,7 +1978,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
dirs.remove(to_remove[i] - i);
}
- // Re-add them at the right position
+ // Re-add them at the right position.
for (int i = 0; i < files.size(); i++) {
dirs.insert(drop_position, files[i]);
drop_position++;
@@ -2032,7 +1993,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
- // Moving resource
+ // Moving resource.
Ref<Resource> res = drag_data["resource"];
String to_dir;
bool favorite;
@@ -2044,7 +2005,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
- // Move files or add to favorites
+ // Move files or add to favorites.
String to_dir;
bool favorite;
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
@@ -2074,7 +2035,7 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
target = String();
target_favorites = false;
- // In the file list
+ // In the file list.
if (p_from == files) {
int pos = files->get_item_at_position(p_point, true);
if (pos == -1) {
@@ -2086,12 +2047,12 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
return;
}
- // In the tree
+ // In the tree.
if (p_from == tree) {
TreeItem *ti = tree->get_item_at_position(p_point);
int section = tree->get_drop_section_at_position(p_point);
if (ti) {
- // Check the favorites first
+ // Check the favorites first.
if (ti == tree->get_root()->get_children() && section >= 0) {
target_favorites = true;
return;
@@ -2102,13 +2063,13 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
String fpath = ti->get_metadata(0);
if (section == 0) {
if (fpath.ends_with("/")) {
- // We drop on a folder
+ // We drop on a folder.
target = fpath;
return;
}
} else {
if (ti->get_parent() != tree->get_root()->get_children()) {
- // Not in the favorite section
+ // Not in the favorite section.
if (fpath != "res://") {
// We drop between two files
if (fpath.ends_with("/")) {
@@ -2125,7 +2086,7 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
}
void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths, bool p_display_path_dependent_options) {
- // Add options for files and folders
+ // Add options for files and folders.
ERR_FAIL_COND(p_paths.empty());
Vector<String> filenames;
@@ -2149,7 +2110,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
all_files_scenes &= (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene");
}
- // Check if in favorites
+ // Check if in favorites.
bool found = false;
for (int j = 0; j < favorites.size(); j++) {
if (favorites[j] == fpath) {
@@ -2165,7 +2126,6 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
}
if (all_files) {
-
if (all_files_scenes) {
if (filenames.size() == 1) {
p_popup->add_item(TTR("Open Scene"), FILE_OPEN);
@@ -2205,12 +2165,16 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
if (p_paths.size() == 1) {
p_popup->add_item(TTR("Copy Path"), FILE_COPY_PATH);
- p_popup->add_item(TTR("Rename..."), FILE_RENAME);
- p_popup->add_item(TTR("Duplicate..."), FILE_DUPLICATE);
+ if (p_paths[0] != "res://") {
+ p_popup->add_item(TTR("Rename..."), FILE_RENAME);
+ p_popup->add_item(TTR("Duplicate..."), FILE_DUPLICATE);
+ }
}
- p_popup->add_item(TTR("Move To..."), FILE_MOVE);
- p_popup->add_item(TTR("Delete"), FILE_REMOVE);
+ if (p_paths.size() > 1 || p_paths[0] != "res://") {
+ p_popup->add_item(TTR("Move To..."), FILE_MOVE);
+ p_popup->add_item(TTR("Delete"), FILE_REMOVE);
+ }
if (p_paths.size() == 1) {
p_popup->add_separator();
@@ -2219,6 +2183,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
p_popup->add_item(TTR("New Scene..."), FILE_NEW_SCENE);
p_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT);
p_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE);
+ p_popup->add_separator();
}
String fpath = p_paths[0];
@@ -2228,8 +2193,8 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
}
void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
- // Right click is pressed in the tree
- Vector<String> paths = _tree_get_selected();
+ // Right click is pressed in the tree.
+ Vector<String> paths = _tree_get_selected(false);
if (paths.size() == 1) {
if (paths[0].ends_with("/")) {
@@ -2239,7 +2204,7 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
}
}
- // Popup
+ // Popup.
if (!paths.empty()) {
tree_popup->clear();
tree_popup->set_size(Size2(1, 1));
@@ -2250,7 +2215,7 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
}
void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) {
- // Right click is pressed in the empty space of the tree
+ // Right click is pressed in the empty space of the tree.
path = "res://";
tree_popup->clear();
tree_popup->set_size(Size2(1, 1));
@@ -2267,7 +2232,7 @@ void FileSystemDock::_tree_empty_selected() {
}
void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) {
- // Right click is pressed in the file list
+ // Right click is pressed in the file list.
Vector<String> paths;
for (int i = 0; i < files->get_item_count(); i++) {
if (!files->is_selected(i))
@@ -2279,7 +2244,7 @@ void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) {
paths.push_back(files->get_item_metadata(i));
}
- // Popup
+ // Popup.
if (!paths.empty()) {
file_list_popup->clear();
file_list_popup->set_size(Size2(1, 1));
@@ -2290,7 +2255,7 @@ void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) {
}
void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) {
- // Right click on empty space for file list
+ // Right click on empty space for file list.
if (searched_string.length() > 0)
return;
@@ -2301,19 +2266,18 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) {
file_list_popup->add_item(TTR("New Scene..."), FILE_NEW_SCENE);
file_list_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT);
file_list_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE);
- file_list_popup->add_item(TTR("Show in File Manager"), FILE_SHOW_IN_EXPLORER);
+ file_list_popup->add_separator();
+ file_list_popup->add_item(TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER);
file_list_popup->set_position(files->get_global_position() + p_pos);
file_list_popup->popup();
}
void FileSystemDock::select_file(const String &p_file) {
-
_navigate_to_path(p_file);
}
void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) {
-
- // Set the path to the current focused item
+ // Set the path to the current focused item.
int current = files->get_current();
if (current == p_index) {
String fpath = files->get_item_metadata(current);
@@ -2325,15 +2289,14 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) {
}
}
- // Update the import dock
+ // Update the import dock.
import_dock_needs_update = true;
call_deferred("_update_import_dock");
}
void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
-
if (get_viewport()->get_modal_stack_top())
- return; //ignore because of modal window
+ return; // Ignore because of modal window.
Ref<InputEventKey> key = p_event;
if (key.is_valid() && key->is_pressed() && !key->is_echo()) {
@@ -2350,9 +2313,8 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
}
void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) {
-
if (get_viewport()->get_modal_stack_top())
- return; //ignore because of modal window
+ return; // Ignore because of modal window.
Ref<InputEventKey> key = p_event;
if (key.is_valid() && key->is_pressed() && !key->is_echo()) {
@@ -2369,18 +2331,17 @@ void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) {
}
void FileSystemDock::_update_import_dock() {
-
if (!import_dock_needs_update)
return;
- // List selected
+ // List selected.
Vector<String> selected;
if (display_mode == DISPLAY_MODE_TREE_ONLY) {
// Use the tree
selected = _tree_get_selected();
} else {
- // Use the file list
+ // Use the file list.
for (int i = 0; i < files->get_item_count(); i++) {
if (!files->is_selected(i))
continue;
@@ -2389,7 +2350,7 @@ void FileSystemDock::_update_import_dock() {
}
}
- // Check import
+ // Check import.
Vector<String> imports;
String import_type;
for (int i = 0; i < selected.size(); i++) {
@@ -2416,7 +2377,7 @@ void FileSystemDock::_update_import_dock() {
if (import_type == "") {
import_type = type;
} else if (import_type != type) {
- //all should be the same type
+ // All should be the same type.
imports.clear();
break;
}
@@ -2435,12 +2396,10 @@ void FileSystemDock::_update_import_dock() {
}
void FileSystemDock::_feature_profile_changed() {
-
_update_display_mode(true);
}
void FileSystemDock::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("_file_list_gui_input"), &FileSystemDock::_file_list_gui_input);
ClassDB::bind_method(D_METHOD("_tree_gui_input"), &FileSystemDock::_tree_gui_input);
@@ -2505,7 +2464,6 @@ void FileSystemDock::_bind_methods() {
}
FileSystemDock::FileSystemDock(EditorNode *p_editor) {
-
set_name("FileSystem");
editor = p_editor;
path = "res://";
@@ -2586,7 +2544,6 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
tree->set_custom_minimum_size(Size2(0, 15 * EDSCALE));
split_box->add_child(tree);
- tree->connect("item_edited", this, "_favorite_toggled");
tree->connect("item_activated", this, "_tree_activate_file");
tree->connect("multi_selected", this, "_tree_multi_selected");
tree->connect("item_rmb_selected", this, "_tree_rmb_select");
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index cc5ba94b48..49eb31e330 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -171,7 +171,7 @@ private:
bool updating_tree;
int tree_update_id;
- Tree *tree; //directories
+ Tree *tree;
ItemList *files;
bool import_dock_needs_update;
@@ -250,7 +250,6 @@ private:
String name;
String path;
StringName type;
- int import_status; //0 not imported, 1 - ok, 2- must reimport, 3- broken
Vector<String> sources;
bool import_broken;
@@ -279,6 +278,7 @@ private:
bool _is_file_type_disabled_by_feature_profile(const StringName &p_class);
void _feature_profile_changed();
+ Vector<String> _remove_self_included_paths(Vector<String> selected_strings);
protected:
void _notification(int p_what);
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 84dd1aa866..9ea7c86e0c 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "editor_scene_importer_gltf.h"
+#include "core/crypto/crypto_core.h"
#include "core/io/json.h"
-#include "core/math/crypto_core.h"
#include "core/math/math_defs.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index cc707dbf44..785a1c107a 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -174,15 +174,6 @@ public:
}
};
-void CanvasItemEditor::_snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius) {
- float radius = p_radius / zoom;
- float dist = Math::abs(p_value - p_target_snap);
- if ((p_radius < 0 || dist < radius) && (!r_snapped || dist < Math::abs(r_current_snap - p_value))) {
- r_current_snap = p_target_snap;
- r_snapped = true;
- }
-}
-
bool CanvasItemEditor::_is_node_locked(const Node *p_node) {
return p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_");
}
@@ -200,108 +191,174 @@ bool CanvasItemEditor::_is_node_movable(const Node *p_node, bool p_popup_warning
return true;
}
-void CanvasItemEditor::_snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) {
+void CanvasItemEditor::_snap_if_closer_float(
+ float p_value,
+ float &r_current_snap, SnapTarget &r_current_snap_target,
+ float p_target_value, SnapTarget p_snap_target,
+ float p_radius) {
+
+ float radius = p_radius / zoom;
+ float dist = Math::abs(p_value - p_target_value);
+ if ((p_radius < 0 || dist < radius) && (r_current_snap_target == SNAP_TARGET_NONE || dist < Math::abs(r_current_snap - p_value))) {
+ r_current_snap = p_target_value;
+ r_current_snap_target = p_snap_target;
+ }
+}
+
+void CanvasItemEditor::_snap_if_closer_point(
+ Point2 p_value,
+ Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
+ Point2 p_target_value, SnapTarget p_snap_target,
+ real_t rotation,
+ float p_radius) {
+
Transform2D rot_trans = Transform2D(rotation, Point2());
p_value = rot_trans.inverse().xform(p_value);
- p_target_snap = rot_trans.inverse().xform(p_target_snap);
+ p_target_value = rot_trans.inverse().xform(p_target_value);
r_current_snap = rot_trans.inverse().xform(r_current_snap);
- _snap_if_closer_float(p_value.x, p_target_snap.x, r_current_snap.x, r_snapped[0], p_radius);
- _snap_if_closer_float(p_value.y, p_target_snap.y, r_current_snap.y, r_snapped[1], p_radius);
+ _snap_if_closer_float(
+ p_value.x,
+ r_current_snap.x,
+ r_current_snap_target[0],
+ p_target_value.x,
+ p_snap_target,
+ p_radius);
+
+ _snap_if_closer_float(
+ p_value.y,
+ r_current_snap.y,
+ r_current_snap_target[1],
+ p_target_value.y,
+ p_snap_target,
+ p_radius);
r_current_snap = rot_trans.xform(r_current_snap);
}
-void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap) {
+void CanvasItemEditor::_snap_other_nodes(
+ const Point2 p_value,
+ const Transform2D p_transform_to_snap,
+ Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
+ const SnapTarget p_snap_target, List<const CanvasItem *> p_exceptions,
+ const Node *p_current) {
const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current);
- if (canvas_item && (!p_to_snap || p_current != p_to_snap)) {
+
+ // Check if the element is in the exception
+ bool exception = false;
+ for (List<const CanvasItem *>::Element *E = p_exceptions.front(); E; E = E->next()) {
+ if (E->get() == p_current) {
+ exception = true;
+ break;
+ }
+ };
+
+ if (canvas_item && !exception) {
Transform2D ci_transform = canvas_item->get_global_transform_with_canvas();
- Transform2D to_snap_transform = p_to_snap ? p_to_snap->get_global_transform_with_canvas() : Transform2D();
- if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), (real_t)360.0) == 0.0) {
+ if (fmod(ci_transform.get_rotation() - p_transform_to_snap.get_rotation(), (real_t)360.0) == 0.0) {
if (canvas_item->_edit_use_rect()) {
Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position());
Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size());
- _snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation());
- _snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation());
+
+ _snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, begin, p_snap_target, ci_transform.get_rotation());
+ _snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, end, p_snap_target, ci_transform.get_rotation());
} else {
Point2 position = ci_transform.xform(Point2());
- _snap_if_closer_point(p_value, position, r_current_snap, r_snapped, ci_transform.get_rotation());
+ _snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, position, p_snap_target, ci_transform.get_rotation());
}
}
}
for (int i = 0; i < p_current->get_child_count(); i++) {
- _snap_other_nodes(p_value, r_current_snap, r_snapped, p_current->get_child(i), p_to_snap);
+ _snap_other_nodes(p_value, p_transform_to_snap, r_current_snap, r_current_snap_target, p_snap_target, p_exceptions, p_current->get_child(i));
}
}
-Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const CanvasItem *p_canvas_item, unsigned int p_forced_modes) {
- bool snapped[2] = { false, false };
+Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsigned int p_forced_modes, const CanvasItem *p_self_canvas_item, List<CanvasItem *> p_other_nodes_exceptions) {
+
+ snap_target[0] = SNAP_TARGET_NONE;
+ snap_target[1] = SNAP_TARGET_NONE;
+
bool is_snap_active = snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
// Smart snap using the canvas position
Vector2 output = p_target;
real_t rotation = 0.0;
- if (p_canvas_item) {
- rotation = p_canvas_item->get_global_transform_with_canvas().get_rotation();
+ if (p_self_canvas_item) {
+ rotation = p_self_canvas_item->get_global_transform_with_canvas().get_rotation();
// Parent sides and center
if ((is_snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) {
- if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
- Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
- Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
- _snap_if_closer_point(p_target, begin, output, snapped, rotation);
- _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation);
- _snap_if_closer_point(p_target, end, output, snapped, rotation);
- } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) {
+ if (const Control *c = Object::cast_to<Control>(p_self_canvas_item)) {
+ Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
+ Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
+ _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_PARENT, rotation);
+ _snap_if_closer_point(p_target, output, snap_target, (begin + end) / 2.0, SNAP_TARGET_PARENT, rotation);
+ _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_PARENT, rotation);
+ } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_self_canvas_item->get_parent())) {
if (parent_ci->_edit_use_rect()) {
- Point2 begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position());
- Point2 end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size());
- _snap_if_closer_point(p_target, begin, output, snapped, rotation);
- _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation);
- _snap_if_closer_point(p_target, end, output, snapped, rotation);
+ Point2 begin = p_self_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position());
+ Point2 end = p_self_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size());
+ _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_PARENT, rotation);
+ _snap_if_closer_point(p_target, output, snap_target, (begin + end) / 2.0, SNAP_TARGET_PARENT, rotation);
+ _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_PARENT, rotation);
} else {
- Point2 position = p_canvas_item->get_transform().affine_inverse().xform(Point2());
- _snap_if_closer_point(p_target, position, output, snapped, rotation);
+ Point2 position = p_self_canvas_item->get_transform().affine_inverse().xform(Point2());
+ _snap_if_closer_point(p_target, output, snap_target, position, SNAP_TARGET_PARENT, rotation);
}
}
}
// Self anchors
if ((is_snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) {
- if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
- Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
- Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
- _snap_if_closer_point(p_target, begin, output, snapped, rotation);
- _snap_if_closer_point(p_target, end, output, snapped, rotation);
+ if (const Control *c = Object::cast_to<Control>(p_self_canvas_item)) {
+ Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
+ Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
+ _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_SELF_ANCHORS, rotation);
+ _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_SELF_ANCHORS, rotation);
}
}
// Self sides
if ((is_snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) {
- if (p_canvas_item->_edit_use_rect()) {
- Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position());
- Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size());
- _snap_if_closer_point(p_target, begin, output, snapped, rotation);
- _snap_if_closer_point(p_target, end, output, snapped, rotation);
+ if (p_self_canvas_item->_edit_use_rect()) {
+ Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(p_self_canvas_item->_edit_get_rect().get_position());
+ Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(p_self_canvas_item->_edit_get_rect().get_position() + p_self_canvas_item->_edit_get_rect().get_size());
+ _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_SELF, rotation);
+ _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_SELF, rotation);
}
}
// Self center
if ((is_snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) {
- if (p_canvas_item->_edit_use_rect()) {
- Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0);
- _snap_if_closer_point(p_target, center, output, snapped, rotation);
+ if (p_self_canvas_item->_edit_use_rect()) {
+ Point2 center = p_self_canvas_item->get_global_transform_with_canvas().xform(p_self_canvas_item->_edit_get_rect().get_position() + p_self_canvas_item->_edit_get_rect().get_size() / 2.0);
+ _snap_if_closer_point(p_target, output, snap_target, center, SNAP_TARGET_SELF, rotation);
} else {
- Point2 position = p_canvas_item->get_global_transform_with_canvas().xform(Point2());
- _snap_if_closer_point(p_target, position, output, snapped, rotation);
+ Point2 position = p_self_canvas_item->get_global_transform_with_canvas().xform(Point2());
+ _snap_if_closer_point(p_target, output, snap_target, position, SNAP_TARGET_SELF, rotation);
}
}
}
// Other nodes sides
if ((is_snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
- _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item);
+ Transform2D to_snap_transform = Transform2D();
+ List<const CanvasItem *> exceptions = List<const CanvasItem *>();
+ for (List<CanvasItem *>::Element *E = p_other_nodes_exceptions.front(); E; E = E->next()) {
+ exceptions.push_back(E->get());
+ }
+ if (p_self_canvas_item) {
+ exceptions.push_back(p_self_canvas_item);
+ to_snap_transform = p_self_canvas_item->get_global_transform_with_canvas();
+ }
+
+ _snap_other_nodes(
+ p_target, to_snap_transform,
+ output, snap_target,
+ SNAP_TARGET_OTHER_NODE,
+ exceptions,
+ get_tree()->get_edited_scene_root());
}
if (((is_snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, (real_t)360.0) == 0.0) {
@@ -309,14 +366,14 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
for (int i = 0; i < vguides.size(); i++) {
- _snap_if_closer_float(p_target.x, vguides[i], output.x, snapped[0]);
+ _snap_if_closer_float(p_target.x, output.x, snap_target[0], vguides[i], SNAP_TARGET_GUIDE);
}
}
if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
for (int i = 0; i < hguides.size(); i++) {
- _snap_if_closer_float(p_target.y, hguides[i], output.y, snapped[1]);
+ _snap_if_closer_float(p_target.y, output.y, snap_target[1], hguides[i], SNAP_TARGET_GUIDE);
}
}
}
@@ -335,7 +392,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
Point2 grid_output;
grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x;
grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y;
- _snap_if_closer_point(p_target, grid_output, output, snapped, 0.0, -1.0);
+ _snap_if_closer_point(p_target, output, snap_target, grid_output, SNAP_TARGET_GRID, 0.0, -1.0);
}
if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) {
@@ -343,6 +400,8 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
output = output.snapped(Size2(1, 1));
}
+ snap_transform = Transform2D(rotation, output);
+
return output;
}
@@ -1205,10 +1264,11 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
if (drag_selection.size() > 0) {
drag_from = transform.affine_inverse().xform((b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position());
Vector2 new_pos;
- if (drag_selection.size() == 1)
- new_pos = snap_point(drag_from, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, drag_selection[0]);
- else
- new_pos = snap_point(drag_from, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
+ if (drag_selection.size() == 1) {
+ new_pos = snap_point(drag_from, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, drag_selection[0]);
+ } else {
+ new_pos = snap_point(drag_from, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, NULL, drag_selection);
+ }
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
@@ -1228,7 +1288,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
_restore_canvas_item_state(drag_selection);
Vector2 new_pos;
if (drag_selection.size() == 1)
- new_pos = snap_point(drag_to, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, drag_selection[0]);
+ new_pos = snap_point(drag_to, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, drag_selection[0]);
else
new_pos = snap_point(drag_to, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
@@ -1478,7 +1538,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
previous_anchor.y = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT) ? control->get_anchor(MARGIN_TOP) : control->get_anchor(MARGIN_BOTTOM);
previous_anchor = xform.affine_inverse().xform(_anchor_to_position(control, previous_anchor));
- Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, control, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER));
+ Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER, control));
new_anchor = _position_to_anchor(control, new_anchor).snapped(Vector2(0.001, 0.001));
bool use_single_axis = m->get_shift();
@@ -1624,8 +1684,8 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse();
- Point2 drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, canvas_item);
- Point2 drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, canvas_item);
+ Point2 drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, canvas_item);
+ Point2 drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, canvas_item);
Point2 drag_begin = xform.xform(drag_to_snapped_begin);
Point2 drag_end = xform.xform(drag_to_snapped_end);
@@ -1866,7 +1926,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
} else {
previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
}
- Point2 new_pos = snap_point(previous_pos + (drag_to - drag_from), SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES);
+ Point2 new_pos = snap_point(previous_pos + (drag_to - drag_from), SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES, 0, NULL, drag_selection);
bool single_axis = m->get_shift();
if (single_axis) {
if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) {
@@ -2421,6 +2481,20 @@ void CanvasItemEditor::_draw_guides() {
}
}
+void CanvasItemEditor::_draw_smart_snapping() {
+ Color line_color = EditorSettings::get_singleton()->get("editors/2d/smart_snapping_line_color");
+ if (snap_target[0] != SNAP_TARGET_NONE && snap_target[0] != SNAP_TARGET_GRID) {
+ viewport->draw_set_transform_matrix(viewport->get_transform() * transform * snap_transform);
+ viewport->draw_line(Point2(0, -1.0e+10F), Point2(0, 1.0e+10F), line_color);
+ viewport->draw_set_transform_matrix(viewport->get_transform());
+ }
+ if (snap_target[1] != SNAP_TARGET_NONE && snap_target[1] != SNAP_TARGET_GRID) {
+ viewport->draw_set_transform_matrix(viewport->get_transform() * transform * snap_transform);
+ viewport->draw_line(Point2(-1.0e+10F, 0), Point2(1.0e+10F, 0), line_color);
+ viewport->draw_set_transform_matrix(viewport->get_transform());
+ }
+}
+
void CanvasItemEditor::_draw_rulers() {
Color bg_color = get_color("dark_color_2", "Editor");
Color graduation_color = get_color("font_color", "Editor").linear_interpolate(bg_color, 0.5);
@@ -2505,6 +2579,8 @@ void CanvasItemEditor::_draw_rulers() {
}
}
}
+
+ // Draw the top left corner
viewport->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
}
@@ -2623,7 +2699,7 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
if (dragged_anchor >= 0) {
// Draw the 4 lines when dragged
- bool snapped;
+ bool anchor_snapped;
Color color_snapped = Color(0.64, 0.93, 0.67, 0.5);
Vector2 corners_pos[4];
@@ -2637,14 +2713,8 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i];
line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val);
line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val);
- snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0;
- int line_width;
- if (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) {
- line_width = 2;
- } else {
- line_width = 1;
- }
- viewport->draw_line(line_starts[i], line_ends[i], snapped ? color_snapped : color_base, Math::round(line_width * EDSCALE));
+ anchor_snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0;
+ viewport->draw_line(line_starts[i], line_ends[i], anchor_snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1);
}
// Display the percentages next to the lines
@@ -3312,6 +3382,7 @@ void CanvasItemEditor::_draw_viewport() {
_draw_rulers();
if (show_guides)
_draw_guides();
+ _draw_smart_snapping();
_draw_focus();
_draw_hover();
}
@@ -3321,6 +3392,10 @@ void CanvasItemEditor::update_viewport() {
viewport->update();
}
+void CanvasItemEditor::set_current_tool(Tool p_tool) {
+ _button_tool_select(p_tool);
+}
+
void CanvasItemEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index e6eab57810..a16d07599a 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -86,6 +86,17 @@ public:
private:
EditorNode *editor;
+ enum SnapTarget {
+ SNAP_TARGET_NONE = 0,
+ SNAP_TARGET_PARENT,
+ SNAP_TARGET_SELF_ANCHORS,
+ SNAP_TARGET_SELF,
+ SNAP_TARGET_OTHER_NODE,
+ SNAP_TARGET_GUIDE,
+ SNAP_TARGET_GRID,
+ SNAP_TARGET_PIXEL
+ };
+
enum MenuOption {
SNAP_USE,
SNAP_USE_NODE_PARENT,
@@ -440,6 +451,7 @@ private:
void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side);
void _draw_straight_line(Point2 p_from, Point2 p_to, Color p_color);
+ void _draw_smart_snapping();
void _draw_rulers();
void _draw_guides();
void _draw_focus();
@@ -475,9 +487,25 @@ private:
void _solve_IK(Node2D *leaf_node, Point2 target_position);
- void _snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius = 10.0);
- void _snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0);
- void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap = NULL);
+ SnapTarget snap_target[2];
+ Transform2D snap_transform;
+ void _snap_if_closer_float(
+ float p_value,
+ float &r_current_snap, SnapTarget &r_current_snap_target,
+ float p_target_value, SnapTarget p_snap_target,
+ float p_radius = 10.0);
+ void _snap_if_closer_point(
+ Point2 p_value,
+ Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
+ Point2 p_target_value, SnapTarget p_snap_target,
+ real_t rotation = 0.0,
+ float p_radius = 10.0);
+ void _snap_other_nodes(
+ const Point2 p_value,
+ const Transform2D p_transform_to_snap,
+ Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
+ const SnapTarget p_snap_target, List<const CanvasItem *> p_exceptions,
+ const Node *p_current);
void _set_anchors_preset(Control::LayoutPreset p_preset);
void _set_margins_preset(Control::LayoutPreset p_preset);
@@ -558,7 +586,7 @@ public:
SNAP_DEFAULT = SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL,
};
- Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0);
+ Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, unsigned int p_forced_modes = 0, const CanvasItem *p_self_canvas_item = NULL, List<CanvasItem *> p_other_nodes_exceptions = List<CanvasItem *>());
float snap_angle(float p_target, float p_start = 0) const;
Transform2D get_canvas_transform() const { return transform; }
@@ -581,6 +609,7 @@ public:
void update_viewport();
Tool get_current_tool() { return tool; }
+ void set_current_tool(Tool p_tool);
void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
void edit(CanvasItem *p_canvas_item);
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index b4cce9745e..26fae96025 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -972,7 +972,7 @@ static inline Vector<Point2i> line(int x0, int x1, int y0, int y1) {
bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
- if (!node || !node->get_tileset().is_valid() || !node->is_visible_in_tree())
+ if (!node || !node->get_tileset().is_valid() || !node->is_visible_in_tree() || CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT)
return false;
Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
@@ -1533,7 +1533,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
- if (!node)
+ if (!node || CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT)
return;
Transform2D cell_xf = node->get_cell_transform();
@@ -2136,6 +2136,7 @@ void TileMapEditorPlugin::make_visible(bool p_visible) {
tile_map_editor->show();
tile_map_editor->get_toolbar()->show();
tile_map_editor->get_toolbar_right()->show();
+ CanvasItemEditor::get_singleton()->set_current_tool(CanvasItemEditor::TOOL_SELECT); //Change to TOOL_SELECT when TileMap node is selected, to prevent accidental movement.
} else {
tile_map_editor->hide();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index a418773131..5709bdc3fa 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -195,7 +195,7 @@ private:
unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io);
if (!pkg) {
- set_message(TTR("Error opening package file, not in zip format."), MESSAGE_ERROR);
+ set_message(TTR("Error opening package file, not in ZIP format."), MESSAGE_ERROR);
memdelete(d);
get_ok()->set_disabled(true);
unzClose(pkg);
@@ -519,7 +519,7 @@ private:
unzFile pkg = unzOpen2(zip_path.utf8().get_data(), &io);
if (!pkg) {
- dialog_error->set_text(TTR("Error opening package file, not in zip format."));
+ dialog_error->set_text(TTR("Error opening package file, not in ZIP format."));
dialog_error->popup_centered_minsize();
return;
}
@@ -1255,19 +1255,22 @@ void ProjectList::create_project_item_control(int p_index) {
TextureRect *tf = memnew(TextureRect);
tf->set_texture(get_icon("DefaultProjectIcon", "EditorIcons"));
+ if (item.missing) {
+ tf->set_modulate(Color(1, 1, 1, 0.5));
+ }
hb->add_child(tf);
hb->icon = tf;
VBoxContainer *vb = memnew(VBoxContainer);
if (item.grayed)
- vb->set_modulate(Color(0.5, 0.5, 0.5));
+ vb->set_modulate(Color(1, 1, 1, 0.5));
vb->set_h_size_flags(SIZE_EXPAND_FILL);
hb->add_child(vb);
Control *ec = memnew(Control);
ec->set_custom_minimum_size(Size2(0, 1));
ec->set_mouse_filter(MOUSE_FILTER_PASS);
vb->add_child(ec);
- Label *title = memnew(Label(item.project_name));
+ Label *title = memnew(Label(!item.missing ? item.project_name : TTR("Missing Project")));
title->add_font_override("font", get_font("title", "EditorFonts"));
title->add_color_override("font_color", font_color);
title->set_clip_text(true);
@@ -1278,12 +1281,21 @@ void ProjectList::create_project_item_control(int p_index) {
vb->add_child(path_hb);
Button *show = memnew(Button);
- show->set_icon(get_icon("Load", "EditorIcons")); // Folder icon
+ // Display a folder icon if the project directory can be opened, or a "broken file" icon if it can't
+ show->set_icon(get_icon(!item.missing ? "Load" : "FileBroken", "EditorIcons"));
show->set_flat(true);
- show->set_modulate(Color(1, 1, 1, 0.5));
+ if (!item.grayed) {
+ // Don't make the icon less prominent if the parent is already grayed out
+ show->set_modulate(Color(1, 1, 1, 0.5));
+ }
path_hb->add_child(show);
- show->connect("pressed", this, "_show_project", varray(item.path));
- show->set_tooltip(TTR("Show in File Manager"));
+
+ if (!item.missing) {
+ show->connect("pressed", this, "_show_project", varray(item.path));
+ show->set_tooltip(TTR("Show in File Manager"));
+ } else {
+ show->set_tooltip(TTR("Error: Project is missing on the filesystem."));
+ }
Label *fpath = memnew(Label(item.path));
path_hb->add_child(fpath);
@@ -1737,10 +1749,18 @@ void ProjectManager::_update_project_buttons() {
Vector<ProjectList::Item> selected_projects = _project_list->get_selected_projects();
bool empty_selection = selected_projects.empty();
+ bool is_missing_project_selected = false;
+ for (int i = 0; i < selected_projects.size(); ++i) {
+ if (selected_projects[i].missing) {
+ is_missing_project_selected = true;
+ break;
+ }
+ }
+
erase_btn->set_disabled(empty_selection);
- open_btn->set_disabled(empty_selection);
- rename_btn->set_disabled(empty_selection);
- run_btn->set_disabled(empty_selection);
+ open_btn->set_disabled(empty_selection || is_missing_project_selected);
+ rename_btn->set_disabled(empty_selection || is_missing_project_selected);
+ run_btn->set_disabled(empty_selection || is_missing_project_selected);
erase_missing_btn->set_visible(_project_list->is_any_project_missing());
}
@@ -1928,6 +1948,9 @@ void ProjectManager::_open_selected_projects_ask() {
}
ProjectList::Item project = _project_list->get_selected_projects()[0];
+ if (project.missing) {
+ return;
+ }
// Update the project settings or don't open
String conf = project.path.plus_file("project.godot");
@@ -2110,7 +2133,7 @@ void ProjectManager::_erase_project() {
void ProjectManager::_erase_missing_projects() {
- erase_missing_ask->set_text(TTR("Remove all missing projects from the list? (Folders contents will not be modified)"));
+ erase_missing_ask->set_text(TTR("Remove all missing projects from the list?\nThe project folders' contents won't be modified."));
erase_missing_ask->popup_centered_minsize();
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index f1eb7adbd2..f0114b393d 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -2709,6 +2709,7 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &SceneTreeDock::_feature_profile_changed);
ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance);
+ ClassDB::bind_method(D_METHOD("get_tree_editor"), &SceneTreeDock::get_tree_editor);
ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::replace_node);
ADD_SIGNAL(MethodInfo("remote_tree_selected"));
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index f7ba5e5e3c..4c5371769f 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -2037,8 +2037,11 @@ PortalSpatialGizmo::PortalSpatialGizmo(Portal *p_portal) {
RayCastSpatialGizmoPlugin::RayCastSpatialGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
create_material("shape_material", gizmo_color);
+ const float gizmo_value = gizmo_color.get_v();
+ const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
+ create_material("shape_material_disabled", gizmo_color_disabled);
}
bool RayCastSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) {
@@ -2064,7 +2067,8 @@ void RayCastSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
lines.push_back(Vector3());
lines.push_back(raycast->get_cast_to());
- Ref<SpatialMaterial> material = get_material("shape_material", p_gizmo);
+ const Ref<SpatialMaterial> material =
+ get_material(raycast->is_enabled() ? "shape_material" : "shape_material_disabled", p_gizmo);
p_gizmo->add_lines(lines, material);
p_gizmo->add_collision_segments(lines);
@@ -3108,8 +3112,11 @@ void BakedIndirectLightGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
////
CollisionShapeSpatialGizmoPlugin::CollisionShapeSpatialGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
create_material("shape_material", gizmo_color);
+ const float gizmo_value = gizmo_color.get_v();
+ const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
+ create_material("shape_material_disabled", gizmo_color_disabled);
create_handle_material("handles");
}
@@ -3432,7 +3439,8 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
if (s.is_null())
return;
- Ref<Material> material = get_material("shape_material", p_gizmo);
+ const Ref<Material> material =
+ get_material(!cs->is_disabled() ? "shape_material" : "shape_material_disabled", p_gizmo);
Ref<Material> handles_material = get_material("handles");
if (Object::cast_to<SphereShape>(*s)) {
@@ -3733,8 +3741,11 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
/////
CollisionPolygonSpatialGizmoPlugin::CollisionPolygonSpatialGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
create_material("shape_material", gizmo_color);
+ const float gizmo_value = gizmo_color.get_v();
+ const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
+ create_material("shape_material_disabled", gizmo_color_disabled);
}
bool CollisionPolygonSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) {
@@ -3770,7 +3781,8 @@ void CollisionPolygonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
lines.push_back(Vector3(points[i].x, points[i].y, -depth));
}
- Ref<Material> material = get_material("shape_material", p_gizmo);
+ const Ref<Material> material =
+ get_material(!polygon->is_disabled() ? "shape_material" : "shape_material_disabled", p_gizmo);
p_gizmo->add_lines(lines, material);
p_gizmo->add_collision_segments(lines);