The easiest way to go about this is to switch the underlying icon which represents the file type.
tool
extends EditorPlugin
func _enter_tree() -> void:
var base_theme := get_editor_interface().get_base_control().theme
base_theme.set_icon("GDScript", "EditorIcons", preload("res://icon.png"))
# Other common icons
base_theme.set_icon("PackedScene", "EditorIcons", preload("res://icon.png"))
base_theme.set_icon("Folder", "EditorIcons", preload("res://icon.png"))
# If you are changing folder icons, you probably want to remove the blue tint
base_theme.set_color("folder_icon_modulate", "FileDialog", Color.white)
# If you want to use an existing editor icon, you can also get it from the base theme
base_theme.set_icon("GDScript", "EditorIcons", base_theme.get_icon("Clear", "EditorIcons"))
If you want to change a different icon, there is a very helpful plugin to see them and get their code names: the Editor Theme Explorer by YuriSizov https://godotengine.org/asset-library/asset/557
Be careful though, as these icons will change everywhere they are used in the editor - GDScript
, for example,
is also used in the little file menu next to the code editor.
All of these icons will reset once the project reloads. If you want to be clean about it though,
you should save the previous icons into a variable and apply those back again in _exit_tree()
Now, if you want more fine grained control over what should change, you can use methods like the ones below to get a result like this.
To start, we need to get the file system Tree.
This code is borrowed from https://gist.github.com/Qubus0/#file-context_actions-md
func _enter_tree() -> void:
var file_tree: Tree
var file_list: ItemList
for node in get_editor_interface().get_file_system_dock().get_children():
# Only the parent of the file tree and file list is a VSplit
if node is VSplitContainer:
file_tree = node.get_child(0)
file_list = node.get_child(1).get_child(1)
break
Now that we have the tree (I won't be covering the ItemList for now) we can change it.
Note that the Tree is completely discarded and built again every time something changes in the file system. You can circumvent that by connecting to the file system's signal - not the dock, the file system itself.
# Refresh the tree appearance when enabling for the first time and also every time it changes
change_tree_appearance(file_tree)
var file_system := get_editor_interface().get_resource_filesystem()
file_system.connect("filesystem_changed", self, "change_tree_appearance", [file_tree])
# Get the first TreeItem. This is the entrypoint to our recursive method.
func change_tree_appearance(tree: Tree) -> void:
change_item_appearance(tree.get_root())
# Recursive
func change_item_appearance(tree_item: TreeItem) -> void:
while tree_item:
var metadata = tree_item.get_metadata(0)
var file_path: String
if metadata is String:
file_path = metadata
# A few examples for what to change and how. Not a style guide, make yours prettier
if file_path:
if file_path.ends_with("res://"):
tree_item.set_icon(0, preload("res://icon.png"))
# Make sure the icon doesn't become oversized
tree_item.set_icon_max_width(0, 32)
# Folder icons have a blue tint, reset that
tree_item.set_icon_modulate(0, Color.white)
# Stop teammates from messing with the singletons
if "global" in file_path:
tree_item.set_suffix(0, "(DO NOT TOUCH)")
# Full match. Directories end with a slash
if file_path == "res://addons/":
tree_item.set_custom_color(0, Color.lightgreen)
if file_path.ends_with(".gd"):
tree_item.set_icon_modulate(0, Color.black)
if Directory.new().dir_exists(file_path):
tree_item.set_custom_bg_color(0, Color(0, 0, 0, .1))
# Check if a plugin has an icon and use it as icon for the folder
if file_path.begins_with("res://addons/"):
var icon_path := file_path.plus_file("plugin-icon.png")
if File.new().file_exists(icon_path):
tree_item.set_icon(0, load(icon_path))
tree_item.set_icon_max_width(0, 32)
change_item_appearance(tree_item.get_children())
tree_item = tree_item.get_next()
Also, don't forget to clean up when the plugin is disabled
func _exit_tree() -> void:
var file_system := get_editor_interface().get_resource_filesystem()
file_system.disconnect("filesystem_changed", self, "change_tree_appearance")
# Refresh the file system to discard visual changes
file_system.scan()
Have fun with it! If you have more questions, feel free to ask.
If you want to support me, you can