Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 75 additions & 18 deletions editor/docks/filesystem_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/templates/list.h"
#include "core/variant/variant.h"
#include "editor/docks/editor_dock_manager.h"
#include "editor/docks/import_dock.h"
#include "editor/docks/scene_tree_dock.h"
Expand All @@ -66,6 +67,8 @@
#include "editor/shader/shader_create_dialog.h"
#include "editor/themes/editor_scale.h"
#include "editor/themes/editor_theme_manager.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/item_list.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
Expand Down Expand Up @@ -238,7 +241,11 @@ void FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory

// Set custom folder color (if applicable).
bool has_custom_color = assigned_folder_colors.has(lpath);
Color custom_color = has_custom_color ? folder_colors[assigned_folder_colors[lpath]] : Color();
Color custom_color = Color();
if (has_custom_color) {
Variant color = assigned_folder_colors[lpath];
custom_color = color.is_string() ? folder_colors[color] : Color(color);
}
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);

if (has_custom_color) {
Expand Down Expand Up @@ -1074,7 +1081,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
}

if (assigned_folder_colors.has(color_scan_dir)) {
inherited_folder_color = folder_colors[assigned_folder_colors[color_scan_dir]];
Variant assigned_color = assigned_folder_colors[color_scan_dir];
inherited_folder_color = assigned_color.is_string() ? folder_colors[assigned_folder_colors[color_scan_dir]] : Color(assigned_color);
Comment on lines +1084 to +1085

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Stop inheritance when an explicit default-matching color is found.

A custom color equal to default_folder_color leaves the loop condition true, allowing an ancestor color to override it. Track assignment discovery separately from color equality.

Proposed fix
 Color inherited_folder_color = default_folder_color;
+bool inherited_color_found = false;
 String color_scan_dir = directory;
-while (color_scan_dir != "res://" && inherited_folder_color == default_folder_color) {
+while (color_scan_dir != "res://" && !inherited_color_found) {
 	...
 	if (assigned_folder_colors.has(color_scan_dir)) {
 		Variant assigned_color = assigned_folder_colors[color_scan_dir];
-		inherited_folder_color = assigned_color.is_string() ? folder_colors[assigned_folder_colors[color_scan_dir]] : Color(assigned_color);
+		inherited_folder_color = assigned_color.is_string() ? folder_colors[assigned_color] : Color(assigned_color);
+		inherited_color_found = true;
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Variant assigned_color = assigned_folder_colors[color_scan_dir];
inherited_folder_color = assigned_color.is_string() ? folder_colors[assigned_folder_colors[color_scan_dir]] : Color(assigned_color);
Variant assigned_color = assigned_folder_colors[color_scan_dir];
inherited_folder_color = assigned_color.is_string() ? folder_colors[assigned_color] : Color(assigned_color);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/docks/filesystem_dock.cpp` around lines 1084 - 1085, Update the
folder-color inheritance logic around assigned_folder_colors and
inherited_folder_color to track whether an ancestor assignment was found
separately from whether its color equals default_folder_color. Stop scanning
once an explicit assignment is discovered, including custom colors matching the
default, so ancestor colors cannot override it.

}

color_scan_dir = color_scan_dir.rstrip("/").get_base_dir();
Expand Down Expand Up @@ -1104,7 +1112,11 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {

files->add_item(dname, folder_icon, true);
files->set_item_metadata(-1, dpath);
Color this_folder_color = has_custom_color ? folder_colors[assigned_folder_colors[dpath]] : inherited_folder_color;
Color this_folder_color = inherited_folder_color;
if (has_custom_color) {
Variant custom_color = assigned_folder_colors[dpath];
this_folder_color = custom_color.is_string() ? folder_colors[custom_color] : Color(custom_color);
}
files->set_item_icon_modulate(-1, editor_is_dark_theme ? this_folder_color : this_folder_color * ITEM_COLOR_SCALE);

if (previous_selection.has(dname)) {
Expand Down Expand Up @@ -3221,39 +3233,77 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
}

void FileSystemDock::_update_folder_colors_setting() {
if (!ProjectSettings::get_singleton()->has_setting("file_customization/folder_colors")) {
ProjectSettings::get_singleton()->set_setting("file_customization/folder_colors", assigned_folder_colors);
} else if (assigned_folder_colors.is_empty()) {
if (assigned_folder_colors.is_empty()) {
ProjectSettings::get_singleton()->set_setting("file_customization/folder_colors", Variant());
} else {
ProjectSettings::get_singleton()->set_setting("file_customization/folder_colors", assigned_folder_colors);
}
ProjectSettings::get_singleton()->save();
}

void FileSystemDock::_folder_color_index_pressed(int p_index, PopupMenu *p_menu) {
Variant chosen_color_name = p_menu->get_item_metadata(p_index);
Vector<String> FileSystemDock::_get_selected_folders() {
Vector<String> selected;

// Get all selected folders based on whether the files panel or tree panel is currently focused.
if (files->has_focus()) {
Vector<int> files_selected_ids = files->get_selected_items();

for (int i = 0; i < files_selected_ids.size(); i++) {
selected.push_back(files->get_item_metadata(files_selected_ids[i]));
selected.push_back(
files->get_item_metadata(files_selected_ids[i]));
}
} else {
TreeItem *tree_selected = tree->get_root();
tree_selected = tree->get_next_selected(tree_selected);

while (tree_selected) {
selected.push_back(tree_selected->get_metadata(0));
tree_selected = tree->get_next_selected(tree_selected);
}
}

// Update project settings with new folder colors.
for (int i = 0; i < selected.size(); i++) {
const String &fpath = selected[i];
return selected;
}

if (chosen_color_name) {
assigned_folder_colors[fpath] = chosen_color_name;
void FileSystemDock::_folder_color_confirmed() {
_set_folder_color(custom_color_selected_folders, folder_color_picker->get_pick_color());
custom_color_selected_folders.clear();
}

void FileSystemDock::_folder_color_index_pressed(int p_index, PopupMenu *p_menu) {
Variant chosen_color_name = p_menu->get_item_metadata(p_index);

if (chosen_color_name.get_type() == Variant::STRING_NAME && StringName(chosen_color_name) == "_custom") {
custom_color_selected_folders = _get_selected_folders();

if (!folder_color_dialog) {
folder_color_dialog = memnew(AcceptDialog);
folder_color_dialog->set_title(TTR("Select Folder Color"));

folder_color_picker = memnew(ColorPicker);
folder_color_dialog->add_child(folder_color_picker);

add_child(folder_color_dialog);

folder_color_dialog->connect(
SceneStringName(confirmed),
callable_mp(this, &FileSystemDock::_folder_color_confirmed));
}

folder_color_dialog->popup_centered();
return;
}

_set_folder_color(_get_selected_folders(), chosen_color_name);
}

void FileSystemDock::_set_folder_color(const Vector<String> &p_selected_folders, const Variant &p_color) {
// Update project settings with new folder colors.
for (int i = 0; i < p_selected_folders.size(); i++) {
const String &fpath = p_selected_folders[i];
if (p_color.is_string() && !String(p_color).is_empty()) {
assigned_folder_colors[fpath] = p_color;
} else if (p_color.get_type() == Variant::COLOR) {
assigned_folder_colors[fpath] = p_color;
} else {
assigned_folder_colors.erase(fpath);
}
Expand Down Expand Up @@ -3391,6 +3441,10 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect
folder_colors_menu->set_item_icon_modulate(-1, editor_is_dark_theme ? E.value : E.value * 2);
folder_colors_menu->set_item_metadata(-1, E.key);
}

folder_colors_menu->add_separator();
folder_colors_menu->add_icon_item(get_editor_theme_icon(SNAME("FolderQuestion")), TTRC("Custom"));
folder_colors_menu->set_item_metadata(-1, SNAME("_custom"));
}
}

Expand Down Expand Up @@ -3995,9 +4049,12 @@ Color FileSystemDock::get_dir_icon_color(const String &p_dir_path, const Color &
parent_dir += "/";
}

const String color_name = singleton->assigned_folder_colors.get(parent_dir, String());
if (!color_name.is_empty()) {
folder_icon_color = singleton->folder_colors[color_name];
Variant color = singleton->assigned_folder_colors.get(parent_dir, String());
if (color.get_type() == Variant::STRING && !String(color).is_empty()) {
folder_icon_color = singleton->folder_colors[String(color)];
break;
} else if (color.get_type() == Variant::COLOR) {
folder_icon_color = color;
break;
}
parent_dir = parent_dir.trim_suffix("/").get_base_dir();
Expand Down
7 changes: 7 additions & 0 deletions editor/docks/filesystem_dock.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "editor/script/script_create_dialog.h"
#include "editor/script/script_editor_plugin.h"
#include "scene/gui/box_container.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/control.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/menu_button.h"
Expand Down Expand Up @@ -189,6 +190,9 @@ class FileSystemDock : public VBoxContainer {

PopupMenu *file_list_popup = nullptr;
PopupMenu *tree_popup = nullptr;
AcceptDialog *folder_color_dialog = nullptr;
ColorPicker *folder_color_picker = nullptr;
Vector<String> custom_color_selected_folders;

DependencyEditor *deps_editor = nullptr;
DependencyEditorOwners *owners_editor = nullptr;
Expand Down Expand Up @@ -338,6 +342,9 @@ class FileSystemDock : public VBoxContainer {
void _file_sort_popup(int p_id);

void _folder_color_index_pressed(int p_index, PopupMenu *p_menu);
void _set_folder_color(const Vector<String> &p_selected_folders, const Variant &p_color);
Vector<String> _get_selected_folders();
void _folder_color_confirmed();
void _file_and_folders_fill_popup(PopupMenu *p_popup, const Vector<String> &p_paths, bool p_display_path_dependent_options = true);
void _tree_rmb_select(const Vector2 &p_pos, MouseButton p_button);
void _file_list_item_clicked(int p_item, const Vector2 &p_pos, MouseButton p_mouse_button_index);
Expand Down
1 change: 1 addition & 0 deletions editor/icons/FolderQuestion.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading