Browse Source

Merge pull request #106902 from lyuma/config_file_uids

Implement UID references in VariantParser
Rémi Verschelde 3 months ago
parent
commit
f759f52d8f
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()) {