Repository: godotengine/godot (language: cpp)

Issue:
[4.4beta1] ResourceLoader.has_cached() does not return proper values for UIDs
### Tested versions

Reproducible in 4.4 dev 4, 5, 6, 7, and beta 1. Probably in previous 4.4 dev builds as well.

### System information

Godot v4.4.beta1 - Arch Linux #1 SMP PREEMPT_DYNAMIC Fri, 10 Jan 2025 00:39:41 +0000 on Wayland - X11 display driver, Multi-window, 2 monitors - Vulkan (Forward+) - dedicated AMD Radeon RX 6600 XT (RADV NAVI23) - AMD Ryzen 5 5600X 6-Core Processor (12 threads)

### Issue description

Passing a UID into `ResourceLoader.has_cached()` returns `false` for a resource that is cached. Passing the resource path for the resource with the same UID properly returns `true`.

### Steps to reproduce

1. Create a Sprite2D node and attach the `icon.svg` as the texture.
2. Attach a script to the Sprite2D node to see if the `icon.svg` resource is cached. Something like:
```
extends Sprite2D

var resource_path: String = "res://icon.svg"
var uid: String = "" # Insert UID of icon.svg here.


func _ready():
	print("ResourceLoader.has_cached results:\nResource Path: ",
			ResourceLoader.has_cached(resource_path), " UID: ", ResourceLoader.has_cached(uid))
```
3. Observe that passing the resource path returns `true` whereas passing the UID returns `false`.

### Minimal reproduction project (MRP)

[resource-loader-bug.zip](https://github.com/user-attachments/files/18463852/resource-loader-bug.zip)


Discussion / hints:
While ResourceLoader class in core has been properly changed to handle UIDs, the `has_cached()` function has no ResourceLoader equivalent and is just handled in `core_bind.cpp`.
https://github.com/godotengine/godot/blob/7b1ed520bdcca21d36e25e2094802b9b33dae2c6/core/core_bind.cpp#L115-L118
Doing a brief once over of the `localize_path()` function, it does not seem to be able to handle UIDs.
https://github.com/godotengine/godot/blob/7b1ed520bdcca21d36e25e2094802b9b33dae2c6/core/config/project_settings.cpp#L149-L213
Somewhere in this chain, UIDs probably need to be properly handled as the rest of ResourceLoader functions seem fit to handle them.

Edit: As reference, ResourceLoader passes `path`s to this function and refers to the returned path as the `local_path`:
https://github.com/godotengine/godot/blob/7b1ed520bdcca21d36e25e2094802b9b33dae2c6/core/io/resource_loader.cpp#L498-L507
`ResourceLoader.get_cached_ref()` probably has the same problem.
https://github.com/godotengine/godot/blob/7b1ed520bdcca21d36e25e2094802b9b33dae2c6/core/core_bind.cpp#L120-L122

Fix patch:
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 6974d98234cc..acd589783ece 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -113,12 +113,12 @@ PackedStringArray ResourceLoader::get_dependencies(const String &p_path) {
 }
 
 bool ResourceLoader::has_cached(const String &p_path) {
-	String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+	String local_path = ::ResourceLoader::_validate_local_path(p_path);
 	return ResourceCache::has(local_path);
 }
 
 Ref<Resource> ResourceLoader::get_cached_ref(const String &p_path) {
-	String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+	String local_path = ::ResourceLoader::_validate_local_path(p_path);
 	return ResourceCache::get_ref(local_path);
 }
 
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 8f873d859b65..7cc91ef4318b 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -495,7 +495,7 @@ void ResourceLoader::_run_load_task(void *p_userdata) {
 	curr_load_task = curr_load_task_backup;
 }
 
-static String _validate_local_path(const String &p_path) {
+String ResourceLoader::_validate_local_path(const String &p_path) {
 	ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(p_path);
 	if (uid != ResourceUID::INVALID_ID) {
 		return ResourceUID::get_singleton()->get_id_path(uid);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index f933e88b23bf..56052b6a6fc4 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -36,6 +36,10 @@
 #include "core/object/worker_thread_pool.h"
 #include "core/os/thread.h"
 
+namespace core_bind {
+class ResourceLoader;
+}
+
 class ConditionVariable;
 
 template <int Tag>
@@ -101,6 +105,7 @@ typedef void (*ResourceLoadedCallback)(Ref<Resource> p_resource, const String &p
 
 class ResourceLoader {
 	friend class LoadToken;
+	friend class core_bind::ResourceLoader;
 
 	enum {
 		MAX_LOADERS = 64
@@ -217,6 +222,8 @@ class ResourceLoader {
 
 	static bool _ensure_load_progress();
 
+	static String _validate_local_path(const String &p_path);
+
 public:
 	static Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE);
 	static ThreadLoadStatus load_threaded_get_status(const String &p_path, float *r_progress = nullptr);


Test patch: