Browse Source

Implement uid Resource references in VariantWriter

VariantWriter now writes the uid and the path into Resource() references.
This change will affect ConfigFile, used for .import or project settings.
Lyuma 2 months ago
parent
commit
f948ab5366
2 changed files with 65 additions and 12 deletions
  1. 1 0
      core/io/resource_loader.cpp
  2. 64 12
      core/variant/variant_parser.cpp

+ 1 - 0
core/io/resource_loader.cpp

@@ -565,6 +565,7 @@ Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hi
 
 Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path, const String &p_type_hint, LoadThreadMode p_thread_mode, ResourceFormatLoader::CacheMode p_cache_mode, bool p_for_user) {
 	String local_path = _validate_local_path(p_path);
+	ERR_FAIL_COND_V(local_path.is_empty(), Ref<ResourceLoader::LoadToken>());
 
 	bool ignoring_cache = p_cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE || p_cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP;
 

+ 64 - 12
core/variant/variant_parser.cpp

@@ -32,6 +32,7 @@
 
 #include "core/crypto/crypto_core.h"
 #include "core/io/resource_loader.h"
+#include "core/io/resource_uid.h"
 #include "core/object/script_language.h"
 #include "core/string/string_buffer.h"
 
@@ -1123,13 +1124,55 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type == TK_STRING) {
 					String path = token.value;
-					Ref<Resource> res = ResourceLoader::load(path);
+					String uid_string;
+
+					get_token(p_stream, token, line, r_err_str);
+
+					if (path.begins_with("uid://")) {
+						uid_string = path;
+						path = "";
+					}
+					if (token.type == TK_COMMA) {
+						get_token(p_stream, token, line, r_err_str);
+						if (token.type != TK_STRING) {
+							r_err_str = "Expected string in Resource reference";
+							return ERR_PARSE_ERROR;
+						}
+						String extra_path = token.value;
+						if (extra_path.begins_with("uid://")) {
+							if (!uid_string.is_empty()) {
+								r_err_str = "Two uid:// paths in one Resource reference";
+								return ERR_PARSE_ERROR;
+							}
+							uid_string = extra_path;
+						} else {
+							if (!path.is_empty()) {
+								r_err_str = "Two non-uid paths in one Resource reference";
+								return ERR_PARSE_ERROR;
+							}
+							path = extra_path;
+						}
+						get_token(p_stream, token, line, r_err_str);
+					}
+
+					Ref<Resource> res;
+					if (!uid_string.is_empty()) {
+						ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(uid_string);
+						if (uid != ResourceUID::INVALID_ID && ResourceUID::get_singleton()->has_id(uid)) {
+							const String id_path = ResourceUID::get_singleton()->get_id_path(uid);
+							if (!id_path.is_empty()) {
+								res = ResourceLoader::load(id_path);
+							}
+						}
+					}
+					if (res.is_null() && !path.is_empty()) {
+						res = ResourceLoader::load(path);
+					}
 					if (res.is_null()) {
-						r_err_str = "Can't load resource at path: " + path;
+						r_err_str = "Can't load resource at path: " + path + " with uid: " + uid_string;
 						return ERR_PARSE_ERROR;
 					}
 
-					get_token(p_stream, token, line, r_err_str);
 					if (token.type != TK_PARENTHESIS_CLOSE) {
 						r_err_str = "Expected ')'";
 						return ERR_PARSE_ERROR;
@@ -1960,6 +2003,16 @@ static String rtos_fix(double p_value, bool p_compat) {
 	return String::num_scientific(p_value);
 }
 
+static String encode_resource_reference(const String &path) {
+	ResourceUID::ID uid = ResourceLoader::get_resource_uid(path);
+	if (uid != ResourceUID::INVALID_ID) {
+		return "Resource(\"" + ResourceUID::get_singleton()->id_to_text(uid) +
+				"\", \"" + path.c_escape_multiline() + "\")";
+	} else {
+		return "Resource(\"" + path.c_escape_multiline() + "\")";
+	}
+}
+
 Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count, bool p_compat) {
 	switch (p_variant.get_type()) {
 		case Variant::NIL: {
@@ -2146,22 +2199,21 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 
 			Ref<Resource> res = p_variant;
 			if (res.is_valid()) {
-				//is resource
 				String res_text;
 
-				//try external function
+				// Try external function.
 				if (p_encode_res_func) {
 					res_text = p_encode_res_func(p_encode_res_ud, res);
 				}
 
-				//try path because it's a file
+				// Try path, because it's a file.
 				if (res_text.is_empty() && res->get_path().is_resource_file()) {
-					//external resource
+					// External resource.
 					String path = res->get_path();
-					res_text = "Resource(\"" + path + "\")";
+					res_text = encode_resource_reference(path);
 				}
 
-				//could come up with some sort of text
+				// Could come up with some sort of text.
 				if (!res_text.is_empty()) {
 					p_store_string_func(p_store_string_ud, res_text);
 					break;
@@ -2209,7 +2261,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 						resource_text = p_encode_res_func(p_encode_res_ud, key_script);
 					}
 					if (resource_text.is_empty() && key_script->get_path().is_resource_file()) {
-						resource_text = "Resource(\"" + key_script->get_path() + "\")";
+						resource_text = encode_resource_reference(key_script->get_path());
 					}
 
 					if (!resource_text.is_empty()) {
@@ -2238,7 +2290,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 						resource_text = p_encode_res_func(p_encode_res_ud, value_script);
 					}
 					if (resource_text.is_empty() && value_script->get_path().is_resource_file()) {
-						resource_text = "Resource(\"" + value_script->get_path() + "\")";
+						resource_text = encode_resource_reference(value_script->get_path());
 					}
 
 					if (!resource_text.is_empty()) {
@@ -2310,7 +2362,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 						resource_text = p_encode_res_func(p_encode_res_ud, script);
 					}
 					if (resource_text.is_empty() && script->get_path().is_resource_file()) {
-						resource_text = "Resource(\"" + script->get_path() + "\")";
+						resource_text = encode_resource_reference(script->get_path());
 					}
 
 					if (!resource_text.is_empty()) {