The FileSystem Dock is Godot's primary asset browser within the editor. It provides a visual tree of the project's res:// directory, displays resource type icons and thumbnails, handles file operations (import, move, delete, rename, duplicate), and integrates with the EditorFileSystem scanning backend to track and manage project resources.
This page documents the FileSystem Dock UI (editor/filesystem_dock.cpp), the background scanning system (editor/editor_file_system.cpp), and the lower-level resource I/O classes they depend on.
For resource loading and caching details, see page 5.1 For the import pipeline internals, see page 5.4
The FileSystem Dock coordinates three layers: the editor UI (FileSystemDock), the background scanning system (EditorFileSystem), and the core resource I/O infrastructure (ResourceLoader, ResourceFormatImporter, ResourceSaver).
Component Map
Sources: core/io/resource_loader.h47-311 core/io/resource_importer.h41-107 core/io/resource_saver.h36-100 core/io/resource.h198-216
editor/filesystem_dock.cpp)The main UI panel that renders the res:// directory tree as an interactive Tree control. It listens to signals from EditorFileSystem to refresh when files change, and dispatches file operation requests back through the editor.
Primary responsibilities:
EditorFileSystemDirectory dataDirAccess / FileAccess for disk operationsEditorResourcePrevieweditor/editor_file_system.cpp)Background singleton that scans res://, maintains the EditorFileSystemDirectory tree, and drives resource reimport when source files change.
| Responsibility | Details |
|---|---|
| Initial scan | Full traversal of res:// on project open |
| Incremental update | File-watcher events trigger partial rescans |
| Import detection | Checks .import file freshness against source timestamps |
| Dependency tracking | Calls ResourceLoader::get_dependencies() per file |
| UID registration | Reads UIDs from import/resource files and populates ResourceUID |
Sources: core/io/resource_loader.h247-260 core/io/resource_importer.h41-107 core/io/resource_importer.cpp43-155
EditorFileSystem walks res:// and, for each file, delegates format detection and UID extraction to the registered ResourceFormatLoader chain and ResourceFormatImporter.
EditorFileSystem scan flow
Sources: core/io/resource_loader.h247-260 core/io/resource_importer.cpp43-155 core/io/resource_loader.cpp139-143
When a source asset is imported, ResourceFormatImporter writes a .import sidecar file. EditorFileSystem reads these to determine import freshness and locate the processed output.
.import file layout
ResourceFormatImporter::_get_path_and_type() parses the [remap] section to resolve the actual .godot/imported/ path used at load time. Feature-specific overrides (path.s3tc, path.etc2, etc.) are checked against OS::has_feature() to select the correct platform variant.
Sources: core/io/resource_importer.cpp44-155 core/io/resource_importer.h44-52
Every resource tracked by EditorFileSystem is assigned a stable UID via the ResourceUID singleton. This allows references to survive file renames and moves.
UID storage by resource type
| Resource Type | UID Storage | Reader |
|---|---|---|
Imported (.png, .gltf, etc.) | uid= in .import file | ResourceFormatImporter::_get_path_and_type() |
Text resources (.tres, .tscn) | uid= in file header | ResourceFormatLoaderText |
Binary resources (.res, .scn) | Binary header field | ResourceFormatLoaderBinary |
| Custom formats | Override _get_resource_uid() | ResourceFormatLoader::get_resource_uid() |
UID resolution flow
The ResourceFormatLoader::has_custom_uid_support() check at core/io/resource_loader.cpp129-131 gates whether the .uid sidecar file or the virtual method is used.
Sources: core/io/resource_loader.cpp116-131 core/io/resource_loader.h85-87 core/io/resource_format_binary.cpp441-467 core/io/resource_importer.cpp109-110
When the FileSystem Dock (or any editor system) opens a resource by path, ResourceLoader::load() is the entry point. For imported assets, ResourceFormatImporter intercepts and redirects to the processed .godot/imported/ file.
ResourceLoader::load() call chain
Sources: core/io/resource_loader.cpp273-331 core/io/resource_loader.cpp536-640 core/io/resource_importer.cpp158-200
ResourceFormatLoader::CacheMode controls how ResourceLoader interacts with ResourceCache for each load call:
| Enum Value | Behavior |
|---|---|
CACHE_MODE_IGNORE | Bypass cache for main resource; deps use REUSE |
CACHE_MODE_REUSE | Return cached instance if present (default) |
CACHE_MODE_REPLACE | Refresh cached instance in-place if types match |
CACHE_MODE_IGNORE_DEEP | IGNORE applied recursively to all deps |
CACHE_MODE_REPLACE_DEEP | REPLACE applied recursively to all deps |
The editor uses CACHE_MODE_REPLACE on reimport so that already-referenced resource objects are updated in place rather than creating new objects that existing scene nodes do not hold.
Sources: core/io/resource_loader.h51-57 core/io/resource_loader.cpp389-414
editor/editor_resource_preview.cpp)EditorResourcePreview is a singleton that manages asynchronous thumbnail generation and a disk-backed cache of generated previews. The FileSystemDock calls it to populate icons in the tree view.
Thumbnail generation flow
The preview system relies on ResourceLoader::load() to obtain the resource before passing it to the appropriate EditorResourcePreviewGenerator subclass. Different built-in generators exist for textures, meshes, materials, scenes, scripts, and audio streams.
Sources: Architecture from editor/editor_resource_preview.cpp; resource loading path via core/io/resource_loader.cpp273-331
The FileSystem Dock provides UI for common file operations. Each operation feeds back into EditorFileSystem so the directory tree stays current.
File operation dispatch map
When creating a new resource, ResourceSaver::save() writes the file and the UID system assigns a fresh ID. When moving a resource, ResourceLoader::rename_dependencies() iterates dependents and updates their ext_resource references.
Sources: core/io/resource_saver.cpp102-142 core/io/resource_loader.h256-258 core/io/resource_loader.cpp1-55
When a file is moved or renamed, FileSystemDock must rewrite all ext_resource references in dependent files. The process uses ResourceFormatLoader::get_dependencies() to enumerate dependents, then ResourceFormatLoader::rename_dependencies() to rewrite them.
Dependency update on move
Dependency reference format (as returned by get_dependencies()):
| Format | Example |
|---|---|
| UID with fallback | uid://abc123def456::::res://scripts/player.gd |
| UID with type | uid://abc123def456::Script::res://scripts/player.gd |
| Direct path | res://scripts/player.gd |
| Direct path with type | res://scripts/player.gd::Script |
The UID form is preferred because it survives subsequent renames without requiring another dependency rewrite.
Sources: core/io/resource_loader.cpp180-201 core/io/resource_loader.h255-258 scene/resources/resource_format_text.cpp924-972
EditorFileSystem drives reimport by comparing source-file modification timestamps against what is recorded in the .import file. It calls ResourceFormatImporter to find the right ResourceImporter subclass.
Reimport decision flow
ResourceFormatImporter::are_import_settings_valid() computes a hash of the importer parameters to detect settings changes even when source file timestamps have not changed.
Sources: core/io/resource_importer.cpp43-155 core/io/resource_importer.h100-104 core/io/resource_importer.cpp158-200
ResourceLoader maintains a fixed-size array of up to MAX_LOADERS (64) ResourceFormatLoader instances. On load(), it iterates them in registration order and calls recognize_path() on each. The first match wins.
Loader dispatch in ResourceLoader::_load()
ResourceFormatLoader::recognize_path() defaults to matching by file extension against get_recognized_extensions(), but can be overridden via the _recognize_path GDVirtual method core/io/resource_loader.cpp60-81
Sources: core/io/resource_loader.cpp273-330 core/io/resource_loader.h109-112 core/io/resource_loader.h62-63
Text resources (.tres, .tscn) are parsed by ResourceLoaderText inside ResourceFormatLoaderText. The format is sectioned and human-readable, making it diff-friendly for version control.
[gd_resource type="Resource" load_steps=3 format=3 uid="uid://abc123"]
[ext_resource type="Texture2D" path="res://icon.png" id="1_abc"]
[sub_resource type="Material" id="2_def"]
[resource]
property = "value"
texture = ExtResource("1_abc")
material = SubResource("2_def")
| Section | Parsed by | Purpose |
|---|---|---|
[gd_resource] / [gd_scene] | Header parse | Type, format version, UID |
[ext_resource] | _parse_ext_resource() | Kick off async sub-loads via ResourceLoader::_load_start() |
[sub_resource] | Main load loop | Instantiate and populate embedded resources |
[resource] / [node] | load() / _parse_node_tag() | Main resource or scene node tree |
External resources are loaded eagerly as ResourceLoader::LoadToken references, allowing concurrent loading. They are resolved at property-assignment time via ResourceLoader::_load_complete().
Sources: scene/resources/resource_format_text.cpp451-545 scene/resources/resource_format_text.h40-113 scene/resources/resource_format_text.cpp125-181
Binary resources (.res, .scn) are loaded by ResourceLoaderBinary (instantiated inside ResourceFormatLoaderBinary). They are more compact and faster to deserialize than text resources.
Binary file layout
Variant type tags (defined in resource_format_binary.cpp):
| Constant | Value | Notes |
|---|---|---|
VARIANT_NIL | 1 | No data |
VARIANT_BOOL | 2 | 32-bit |
VARIANT_INT | 3 | 32-bit |
VARIANT_INT64 | 40 | 64-bit |
VARIANT_FLOAT | 4 | real_t |
VARIANT_STRING | 5 | Length-prefixed UTF-8 |
VARIANT_OBJECT | 24 | External or internal resource ref |
FORMAT_VERSION | 6 | Current binary format version |
External resource entries are loaded asynchronously as ResourceLoader::LoadToken objects, mirroring the text format approach.
Sources: core/io/resource_format_binary.cpp45-101 core/io/resource_format_binary.h38-107 core/io/resource_format_binary.cpp681-708
| Error Condition | Mechanism |
|---|---|
Missing .import file | ResourceFormatImporter::_get_path_and_type() returns ERR_FILE_NOT_FOUND |
| Broken dependency | ResourceLoader::notify_dependency_error() fires dep_err_notify callback |
| Load failure | ResourceLoader::notify_load_error() fires err_notify callback |
| Corrupted binary/text | Parser returns ERR_FILE_CORRUPT; ResourceLoader logs and returns null |
| UID conflict | Resource::set_path() calls ERR_FAIL_MSG on collision unless p_take_over is set |
| Class unavailable | ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled() gate; creates MissingResource stub |
Dependency error callback wiring in ResourceLoader:
set_error_notify_func() — sets err_notify function pointer called on load errors core/io/resource_loader.h269-272set_dependency_error_notify_func() — sets dep_err_notify called when a specific dependency fails core/io/resource_loader.h276-278notify_load_error() pushes to MessageQueue::get_main_singleton() so errors always reach the main thread core/io/resource_loader.cpp794-798Sources: core/io/resource_loader.cpp794-808 core/io/resource_loader.h99-101 core/io/resource.cpp71-108
EditorFileSystem communicates status changes back to the dock via signals (filesystem_changed, resources_reimported, sources_changed). The dock also connects to EditorNode for scene-level operations like opening a scene on double-click.
Sources: core/io/resource_loader.h105-311 core/io/resource_saver.h60-100
| Strategy | Implementation |
|---|---|
| Lazy tree population | FileSystemDock only expands directory nodes on demand |
| Disk-cached thumbnails | EditorResourcePreview stores PNGs under .godot/editor/thumbnails/ |
| Incremental filesystem scan | EditorFileSystem::scan_changes() rescans only changed directories |
| Worker-thread loading | ResourceLoader::_load_start() dispatches to WorkerThreadPool when LOAD_THREAD_SPAWN_SINGLE or LOAD_THREAD_DISTRIBUTE is used |
| UID index | ResourceUID singleton maps IDs to paths in memory; no per-file I/O for UID lookups |
| Resource cache | ResourceCache prevents redundant disk reads; subsequent loads of the same path return the cached Resource* |
Threaded load modes (from ResourceLoader::LoadThreadMode):
| Mode | Behavior |
|---|---|
LOAD_THREAD_FROM_CURRENT | Load synchronously on the calling thread |
LOAD_THREAD_SPAWN_SINGLE | Spawn a dedicated WorkerThreadPool task |
LOAD_THREAD_DISTRIBUTE | Allow sub-resources to be distributed across pool threads |
Sources: core/io/resource_loader.h123-127 core/io/resource_loader.cpp536-640 core/io/resource.h198-216
The FileSystem Dock serves as the central asset management interface in the Godot editor, coordinating between:
Together, these systems provide a robust file management experience that handles resource discovery, loading, importing, dependency tracking, and file operations while maintaining performance in large projects.
Sources: core/io/resource_loader.cpp1-1095 core/io/resource_importer.cpp1-520 core/io/resource.cpp1-700
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.