Browse Source

Merge pull request #96590 from reduz/list-directory

Provide a reliable way to see original resources in a directory
Thaddeus Crews 9 months ago
parent
commit
c8ff788052

+ 5 - 0
core/core_bind.cpp

@@ -132,6 +132,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);
@@ -147,6 +151,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);

+ 2 - 0
core/core_bind.h

@@ -86,6 +86,8 @@ public:
 	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; }
 };
 

+ 56 - 0
core/io/resource_loader.cpp

@@ -32,6 +32,7 @@
 
 #include "core/config/project_settings.h"
 #include "core/core_bind.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"
@@ -40,6 +41,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"
 
@@ -1474,6 +1476,60 @@ 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.is_empty()) {
+		bool recognized = false;
+		if (dir->current_is_dir()) {
+			if (d != "." && d != "..") {
+				d += "/";
+				recognized = true;
+			}
+		} else {
+			if (d.ends_with(".import") || d.ends_with(".remap") || d.ends_with(".uid")) {
+				d = d.substr(0, d.rfind("."));
+			}
+
+			if (d.ends_with(".gdc")) {
+				d = d.substr(0, d.rfind("."));
+				d += ".gd";
+			}
+
+			const 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() {}

+ 2 - 0
core/io/resource_loader.h

@@ -304,6 +304,8 @@ public:
 
 	static bool is_cleaning_tasks();
 
+	static Vector<String> list_directory(const String &p_directory);
+
 	static void initialize();
 	static void finalize();
 };

+ 1 - 0
doc/classes/DirAccess.xml

@@ -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>

+ 7 - 0
doc/classes/ResourceLoader.xml

@@ -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" />