Skip to content

Commit

Permalink
Provide a reliable way to see original resources in a directory
Browse files Browse the repository at this point in the history
When exporting a project, resources are often moved, converted or
remapped (source import files are gone, text scenes are converted to binary,
etc).

This new function allows to list a directory and obtain the actual original
resource files.

Example

```GDScript
var resources = ResourceLoader.list_directory("res://images")
print(resources)
```
Result will be something like:
```
["image1.png","image2.png","image3.png"]
```
instead of
```
["image1.png.import","image2.png.import","image3.png.import"]
```
  • Loading branch information
reduz committed Sep 5, 2024
1 parent b6223c0 commit b60208a
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 0 deletions.
5 changes: 5 additions & 0 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
return ::ResourceLoader::get_resource_uid(p_path);
}

Vector<String> ResourceLoader::list_directory(const String &p_directory) {
return ::ResourceLoader::list_directory(p_directory);
}

void ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads", "cache_mode"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE));
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
Expand All @@ -144,6 +148,7 @@ void ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cached_ref", "path"), &ResourceLoader::get_cached_ref);
ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &ResourceLoader::exists, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_resource_uid", "path"), &ResourceLoader::get_resource_uid);
ClassDB::bind_method(D_METHOD("list_directory", "directory_path"), &ResourceLoader::list_directory);

BIND_ENUM_CONSTANT(THREAD_LOAD_INVALID_RESOURCE);
BIND_ENUM_CONSTANT(THREAD_LOAD_IN_PROGRESS);
Expand Down
2 changes: 2 additions & 0 deletions core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class ResourceLoader : public Object {
bool exists(const String &p_path, const String &p_type_hint = "");
ResourceUID::ID get_resource_uid(const String &p_path);

Vector<String> list_directory(const String &p_directory);

ResourceLoader() { singleton = this; }
};

Expand Down
49 changes: 49 additions & 0 deletions core/io/resource_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "resource_loader.h"

#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/resource_importer.h"
#include "core/object/script_language.h"
Expand All @@ -39,6 +40,7 @@
#include "core/os/safe_binary_mutex.h"
#include "core/string/print_string.h"
#include "core/string/translation_server.h"
#include "core/templates/rb_set.h"
#include "core/variant/variant_parser.h"
#include "servers/rendering_server.h"

Expand Down Expand Up @@ -1354,6 +1356,53 @@ bool ResourceLoader::is_cleaning_tasks() {
return cleaning_tasks;
}

Vector<String> ResourceLoader::list_directory(const String &p_directory) {
RBSet<String> files_found;
Ref<DirAccess> dir = DirAccess::open(p_directory);
if (dir.is_null()) {
return Vector<String>();
}

Error err = dir->list_dir_begin();
if (err != OK) {
return Vector<String>();
}

String d = dir->get_next();
while (d != String()) {
bool recognized = false;
if (dir->current_is_dir()) {
d += "/";
recognized = true;
} else {
if (d.ends_with(".import") || d.ends_with(".remap")) {
int idx = d.rfind(".");
d = d.substr(0, idx);
}

String full_path = p_directory.path_join(d);
// Try all loaders and pick the first match for the type hint
for (int i = 0; i < loader_count; i++) {
if (loader[i]->recognize_path(full_path)) {
recognized = true;
break;
}
}
}
if (recognized) {
files_found.insert(d);
}
d = dir->get_next();
}

Vector<String> ret;
for (const String &f : files_found) {
ret.push_back(f);
}

return ret;
}

void ResourceLoader::initialize() {}

void ResourceLoader::finalize() {}
Expand Down
2 changes: 2 additions & 0 deletions core/io/resource_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ class ResourceLoader {

static bool is_cleaning_tasks();

static Vector<String> list_directory(const String &p_directory);

static void initialize();
static void finalize();
};
Expand Down
1 change: 1 addition & 0 deletions doc/classes/DirAccess.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
}
[/csharp]
[/codeblocks]
Keep in mind that file names may change or be remapped after export. If you want to see the actual resource file list as it appears in the editor, use [method ResourceLoader.list_directory] instead.
</description>
<tutorials>
<link title="File system">$DOCS_URL/tutorials/scripting/filesystem.html</link>
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/ResourceLoader.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@
Once a resource has been loaded by the engine, it is cached in memory for faster access, and future calls to the [method load] method will use the cached version. The cached resource can be overridden by using [method Resource.take_over_path] on a new resource for that same path.
</description>
</method>
<method name="list_directory">
<return type="PackedStringArray" />
<param index="0" name="directory_path" type="String" />
<description>
Lists a directory (as example: "res://assets/enemies"), returning all resources contained within. The resource files are the original file names as visible in the editor before exporting.
</description>
</method>
<method name="load">
<return type="Resource" />
<param index="0" name="path" type="String" />
Expand Down

0 comments on commit b60208a

Please sign in to comment.