summaryrefslogtreecommitdiff
path: root/core/io
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2023-01-19 19:12:25 +0100
committerJuan Linietsky <reduzio@gmail.com>2023-01-21 14:19:27 +0100
commitdddd8d43f618874642a228800187fb0912c46c20 (patch)
treeffb66d3db3d61157b119b0e1610a558170f506af /core/io
parent14fdd28de9f1f9979cb6cffa4b715a16d406439d (diff)
Support script global resource name in EditorFileSystem
* Works for binary and text files. * Makes EditorQuickOpen work with custom resources again. * Information is cached and easily accessible. Properly fixes #66179. Supersedes #66215 and supersedes #62417 **WARNING**: This required breaking backwards binary compatibility (.res and .scn files). Files saved after this PR is merged will no longer open in any earlier versions of Godot.
Diffstat (limited to 'core/io')
-rw-r--r--core/io/resource_format_binary.cpp93
-rw-r--r--core/io/resource_format_binary.h4
-rw-r--r--core/io/resource_loader.cpp20
-rw-r--r--core/io/resource_loader.h3
4 files changed, 119 insertions, 1 deletions
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 45e1301930..3dc1e98a21 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -91,7 +91,8 @@ enum {
// Version 2: added 64 bits support for float and int.
// Version 3: changed nodepath encoding.
// Version 4: new string ID for ext/subresources, breaks forward compat.
- FORMAT_VERSION = 4,
+ // Version 5: Ability to store script class in the header.
+ FORMAT_VERSION = 5,
FORMAT_VERSION_CAN_RENAME_DEPS = 1,
FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3,
};
@@ -1013,6 +1014,10 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
uid = ResourceUID::INVALID_ID;
}
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ script_class = get_unicode_string();
+ }
+
for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) {
f->get_32(); //skip a few reserved fields
}
@@ -1117,6 +1122,57 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
return get_unicode_string();
}
+String ResourceLoaderBinary::recognize_script_class(Ref<FileAccess> p_f) {
+ error = OK;
+
+ f = p_f;
+ uint8_t header[4];
+ f->get_buffer(header, 4);
+ if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
+ // Compressed.
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
+ error = fac->open_after_magic(f);
+ if (error != OK) {
+ f.unref();
+ return "";
+ }
+ f = fac;
+
+ } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
+ // Not normal.
+ error = ERR_FILE_UNRECOGNIZED;
+ f.unref();
+ return "";
+ }
+
+ bool big_endian = f->get_32();
+ f->get_32(); // use_real64
+
+ f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
+
+ uint32_t ver_major = f->get_32();
+ f->get_32(); // ver_minor
+ uint32_t ver_fmt = f->get_32();
+
+ if (ver_fmt > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
+ f.unref();
+ return "";
+ }
+
+ get_unicode_string(); // type
+
+ f->get_64(); // Metadata offset
+ uint32_t flags = f->get_32();
+ f->get_64(); // UID
+
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ return get_unicode_string();
+ } else {
+ return String();
+ }
+}
+
Ref<Resource> ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
@@ -1299,6 +1355,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
fw->store_32(flags);
fw->store_64(uid_data);
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ save_ustring(fw, get_ustring(f));
+ }
for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) {
fw->store_32(0); // reserved
@@ -1420,6 +1479,18 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
return ClassDB::get_compatibility_remapped_class(r);
}
+String ResourceFormatLoaderBinary::get_resource_script_class(const String &p_path) const {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
+ return ""; //could not read
+ }
+
+ ResourceLoaderBinary loader;
+ loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ loader.res_path = loader.local_path;
+ return loader.recognize_script_class(f);
+}
+
ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_path) const {
String ext = p_path.get_extension().to_lower();
if (!ClassDB::is_resource_extension(ext)) {
@@ -2037,15 +2108,31 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
save_unicode_string(f, _resource_get_class(p_resource));
f->store_64(0); //offset to import metadata
+
+ String script_class;
{
uint32_t format_flags = FORMAT_FLAG_NAMED_SCENE_IDS | FORMAT_FLAG_UIDS;
#ifdef REAL_T_IS_DOUBLE
format_flags |= FORMAT_FLAG_REAL_T_IS_DOUBLE;
#endif
+ if (!p_resource->is_class("PackedScene")) {
+ Ref<Script> s = p_resource->get_script();
+ if (s.is_valid()) {
+ script_class = s->get_global_name();
+ if (!script_class.is_empty()) {
+ format_flags |= ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS;
+ }
+ }
+ }
+
f->store_32(format_flags);
}
ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(p_path, true);
f->store_64(uid);
+ if (!script_class.is_empty()) {
+ save_unicode_string(f, script_class);
+ }
+
for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) {
f->store_32(0); // reserved
}
@@ -2298,6 +2385,10 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
fw->store_32(flags);
fw->store_64(p_uid);
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ save_ustring(fw, get_ustring(f));
+ }
+
//rest of file
uint8_t b = f->get_8();
while (!f->eof_reached()) {
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 2e8988005f..41536491a2 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -65,6 +65,7 @@ class ResourceLoaderBinary {
bool using_named_scene_ids = false;
bool using_uids = false;
+ String script_class;
bool use_sub_threads = false;
float *progress = nullptr;
Vector<ExtResource> external_resources;
@@ -100,6 +101,7 @@ public:
void set_remaps(const HashMap<String, String> &p_remaps) { remaps = p_remaps; }
void open(Ref<FileAccess> p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
String recognize(Ref<FileAccess> p_f);
+ String recognize_script_class(Ref<FileAccess> p_f);
void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
void get_classes_used(Ref<FileAccess> p_f, HashSet<StringName> *p_classes);
@@ -113,6 +115,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual String get_resource_script_class(const String &p_path) const;
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
@@ -165,6 +168,7 @@ public:
FORMAT_FLAG_NAMED_SCENE_IDS = 1,
FORMAT_FLAG_UIDS = 2,
FORMAT_FLAG_REAL_T_IS_DOUBLE = 4,
+ FORMAT_FLAG_HAS_SCRIPT_CLASS = 8,
// Amount of reserved 32-bit fields in resource header
RESERVED_FIELDS = 11
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 946c31cf0d..05acbf0e2e 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -99,6 +99,12 @@ String ResourceFormatLoader::get_resource_type(const String &p_path) const {
return ret;
}
+String ResourceFormatLoader::get_resource_script_class(const String &p_path) const {
+ String ret;
+ GDVIRTUAL_CALL(_get_resource_script_class, p_path, ret);
+ return ret;
+}
+
ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const {
int64_t uid = ResourceUID::INVALID_ID;
GDVIRTUAL_CALL(_get_resource_uid, p_path, uid);
@@ -184,6 +190,7 @@ void ResourceFormatLoader::_bind_methods() {
GDVIRTUAL_BIND(_recognize_path, "path", "type");
GDVIRTUAL_BIND(_handles_type, "type");
GDVIRTUAL_BIND(_get_resource_type, "path");
+ GDVIRTUAL_BIND(_get_resource_script_class, "path");
GDVIRTUAL_BIND(_get_resource_uid, "path");
GDVIRTUAL_BIND(_get_dependencies, "path", "add_types");
GDVIRTUAL_BIND(_rename_dependencies, "path", "renames");
@@ -764,6 +771,19 @@ String ResourceLoader::get_resource_type(const String &p_path) {
return "";
}
+String ResourceLoader::get_resource_script_class(const String &p_path) {
+ String local_path = _validate_local_path(p_path);
+
+ for (int i = 0; i < loader_count; i++) {
+ String result = loader[i]->get_resource_script_class(local_path);
+ if (!result.is_empty()) {
+ return result;
+ }
+ }
+
+ return "";
+}
+
ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
String local_path = _validate_local_path(p_path);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 41ba0dc6e6..4f308e3d65 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -54,6 +54,7 @@ protected:
GDVIRTUAL2RC(bool, _recognize_path, String, StringName)
GDVIRTUAL1RC(bool, _handles_type, StringName)
GDVIRTUAL1RC(String, _get_resource_type, String)
+ GDVIRTUAL1RC(String, _get_resource_script_class, String)
GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String)
GDVIRTUAL2RC(Vector<String>, _get_dependencies, String, bool)
GDVIRTUAL1RC(Vector<String>, _get_classes_used, String)
@@ -71,6 +72,7 @@ public:
virtual bool handles_type(const String &p_type) const;
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
virtual String get_resource_type(const String &p_path) const;
+ virtual String get_resource_script_class(const String &p_path) const;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);
@@ -175,6 +177,7 @@ public:
static void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader);
static void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
static String get_resource_type(const String &p_path);
+ static String get_resource_script_class(const String &p_path);
static ResourceUID::ID get_resource_uid(const String &p_path);
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);