Merge pull request #71687 from reduz/support-script-class-name-in-efs

Support script global resource name in EditorFileSystem
This commit is contained in:
Rémi Verschelde 2023-01-21 16:54:23 +01:00
commit ebd0b40f6e
No known key found for this signature in database
GPG Key ID: C3336907360768E1
17 changed files with 250 additions and 18 deletions

View File

@ -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,
};
@ -1009,6 +1010,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
}
@ -1113,6 +1118,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;
@ -1295,6 +1351,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
@ -1416,6 +1475,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)) {
@ -2033,15 +2104,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
}
@ -2294,6 +2381,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()) {

View File

@ -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;
@ -99,6 +100,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);
@ -112,6 +114,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);
@ -164,6 +167,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

View File

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

View File

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

View File

@ -123,7 +123,7 @@ public:
virtual bool can_instantiate() const = 0;
virtual Ref<Script> get_base_script() const = 0; //for script inheritance
virtual StringName get_global_name() const = 0;
virtual bool inherits_script(const Ref<Script> &p_script) const = 0;
virtual StringName get_instance_base_type() const = 0; // this may not work in all scripts, will return empty if so

View File

@ -53,6 +53,7 @@ protected:
public:
EXBIND0RC(bool, can_instantiate)
EXBIND0RC(Ref<Script>, get_base_script)
EXBIND0RC(StringName, get_global_name)
EXBIND1RC(bool, inherits_script, const Ref<Script> &)
EXBIND0RC(StringName, get_instance_base_type)

View File

@ -38,6 +38,13 @@
Gets the list of extensions for files this loader is able to read.
</description>
</method>
<method name="_get_resource_script_class" qualifiers="virtual const">
<return type="String" />
<param index="0" name="path" type="String" />
<description>
Returns the script class name associated with the [Resource] under the given [param path]. If the resource has no script or the script isn't a named class, it should return [code]""[/code].
</description>
</method>
<method name="_get_resource_type" qualifiers="virtual const">
<return type="String" />
<param index="0" name="path" type="String" />

View File

@ -47,7 +47,7 @@
EditorFileSystem *EditorFileSystem::singleton = nullptr;
//the name is the version, to keep compatibility with different versions of Godot
#define CACHE_FILE_NAME "filesystem_cache7"
#define CACHE_FILE_NAME "filesystem_cache8"
void EditorFileSystemDirectory::sort_files() {
files.sort_custom<FileInfoSort>();
@ -169,6 +169,11 @@ StringName EditorFileSystemDirectory::get_file_type(int p_idx) const {
return files[p_idx]->type;
}
StringName EditorFileSystemDirectory::get_file_resource_script_class(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, files.size(), "");
return files[p_idx]->resource_script_class;
}
String EditorFileSystemDirectory::get_name() {
return name;
}
@ -266,6 +271,10 @@ void EditorFileSystem::_scan_filesystem() {
FileCache fc;
fc.type = split[1];
if (fc.type.find("/") != -1) {
fc.type = fc.type.get_slice("/", 0);
fc.resource_script_class = fc.type.get_slice("/", 1);
}
fc.uid = split[2].to_int();
fc.modification_time = split[3].to_int();
fc.import_modification_time = split[4].to_int();
@ -854,6 +863,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc
if (fc && fc->modification_time == mt && fc->import_modification_time == import_mt && !_test_for_reimport(path, true)) {
fi->type = fc->type;
fi->resource_script_class = fc->resource_script_class;
fi->uid = fc->uid;
fi->deps = fc->deps;
fi->modified_time = fc->modification_time;
@ -875,6 +885,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc
if (fc->type.is_empty()) {
fi->type = ResourceLoader::get_resource_type(path);
fi->resource_script_class = ResourceLoader::get_resource_script_class(path);
fi->import_group_file = ResourceLoader::get_import_group_file(path);
//there is also the chance that file type changed due to reimport, must probably check this somehow here (or kind of note it for next time in another file?)
//note: I think this should not happen any longer..
@ -904,6 +915,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc
if (fc && fc->modification_time == mt) {
//not imported, so just update type if changed
fi->type = fc->type;
fi->resource_script_class = fc->resource_script_class;
fi->uid = fc->uid;
fi->modified_time = fc->modification_time;
fi->deps = fc->deps;
@ -915,6 +927,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc
} else {
//new or modified time
fi->type = ResourceLoader::get_resource_type(path);
fi->resource_script_class = ResourceLoader::get_resource_script_class(path);
if (fi->type == "" && textfile_extensions.has(ext)) {
fi->type = "TextFile";
}
@ -1029,6 +1042,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
fi->modified_time = FileAccess::get_modified_time(path);
fi->import_modified_time = 0;
fi->type = ResourceLoader::get_resource_type(path);
fi->resource_script_class = ResourceLoader::get_resource_script_class(path);
if (fi->type == "" && textfile_extensions.has(ext)) {
fi->type = "TextFile";
}
@ -1285,7 +1299,12 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir,
if (!p_dir->files[i]->import_group_file.is_empty()) {
group_file_cache.insert(p_dir->files[i]->import_group_file);
}
String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->uid) + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->import_group_file + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path;
String type = p_dir->files[i]->type;
if (p_dir->files[i]->resource_script_class) {
type += "/" + String(p_dir->files[i]->resource_script_class);
}
String s = p_dir->files[i]->file + "::" + type + "::" + itos(p_dir->files[i]->uid) + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->import_group_file + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path;
s += "::";
for (int j = 0; j < p_dir->files[i]->deps.size(); j++) {
if (j > 0) {
@ -1612,6 +1631,8 @@ void EditorFileSystem::update_file(const String &p_file) {
if (type.is_empty() && textfile_extensions.has(p_file.get_extension())) {
type = "TextFile";
}
String script_class = ResourceLoader::get_resource_script_class(p_file);
ResourceUID::ID uid = ResourceLoader::get_resource_uid(p_file);
if (cpos == -1) {
@ -1645,6 +1666,7 @@ void EditorFileSystem::update_file(const String &p_file) {
}
fs->files[cpos]->type = type;
fs->files[cpos]->resource_script_class = script_class;
fs->files[cpos]->uid = uid;
fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path);
fs->files[cpos]->import_group_file = ResourceLoader::get_import_group_file(p_file);

View File

@ -54,6 +54,7 @@ class EditorFileSystemDirectory : public Object {
struct FileInfo {
String file;
StringName type;
StringName resource_script_class; // If any resource has script with a global class name, its found here.
ResourceUID::ID uid = ResourceUID::INVALID_ID;
uint64_t modified_time = 0;
uint64_t import_modified_time = 0;
@ -61,6 +62,7 @@ class EditorFileSystemDirectory : public Object {
String import_group_file;
Vector<String> deps;
bool verified = false; //used for checking changes
// These are for script resources only.
String script_class_name;
String script_class_extends;
String script_class_icon_path;
@ -90,6 +92,7 @@ public:
String get_file(int p_idx) const;
String get_file_path(int p_idx) const;
StringName get_file_type(int p_idx) const;
StringName get_file_resource_script_class(int p_idx) const;
Vector<String> get_file_deps(int p_idx) const;
bool get_file_import_is_valid(int p_idx) const;
uint64_t get_file_modified_time(int p_idx) const;
@ -189,6 +192,7 @@ class EditorFileSystem : public Node {
/* Used for reading the filesystem cache file */
struct FileCache {
String type;
String resource_script_class;
ResourceUID::ID uid = ResourceUID::INVALID_ID;
uint64_t modification_time = 0;
uint64_t import_modification_time = 0;

View File

@ -69,17 +69,9 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) {
for (int i = 0; i < p_efsd->get_file_count(); i++) {
String file = p_efsd->get_file_path(i);
String engine_type = p_efsd->get_file_type(i);
// TODO: Fix lack of caching for resource's script's global class name (if applicable).
String script_type;
if (_load_resources) {
Ref<Resource> res = ResourceLoader::load(file);
if (res.is_valid()) {
Ref<Script> scr = res->get_script();
if (scr.is_valid()) {
script_type = scr->get_language()->get_global_class_name(file);
}
}
}
String script_type = p_efsd->get_file_resource_script_class(i);
String actual_type = script_type.is_empty() ? engine_type : script_type;
// Iterate all possible base types.
for (String &parent_type : base_types) {

View File

@ -43,7 +43,6 @@ class EditorQuickOpen : public ConfirmationDialog {
Tree *search_options = nullptr;
String base_type;
bool allow_multi_select = false;
bool _load_resources = false; // Prohibitively slow for now.
Vector<String> files;
OAHashMap<String, Ref<Texture2D>> icons;

View File

@ -248,6 +248,10 @@ Ref<Script> GDScript::get_base_script() const {
}
}
StringName GDScript::get_global_name() const {
return name;
}
StringName GDScript::get_instance_base_type() const {
if (native.is_valid()) {
return native->get_name();

View File

@ -228,6 +228,7 @@ public:
virtual bool can_instantiate() const override;
virtual Ref<Script> get_base_script() const override;
virtual StringName get_global_name() const override;
virtual StringName get_instance_base_type() const override; // this may not work in all scripts, will return empty if so
virtual ScriptInstance *instance_create(Object *p_this) override;

View File

@ -2606,6 +2606,10 @@ Ref<Script> CSharpScript::get_base_script() const {
return base_script;
}
StringName CSharpScript::get_global_name() const {
return StringName();
}
void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
#ifdef TOOLS_ENABLED
const CSharpScript *top = this;

View File

@ -186,6 +186,8 @@ public:
bool inherits_script(const Ref<Script> &p_script) const override;
Ref<Script> get_base_script() const override;
StringName get_global_name() const override;
ScriptLanguage *get_language() const override;
void get_script_method_list(List<MethodInfo> *p_list) const override;

View File

@ -923,7 +923,11 @@ Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String
if (is_scene) {
fw->store_line("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + "]\n");
} else {
fw->store_line("[gd_resource type=\"" + res_type + "\" load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + "]\n");
String script_res_text;
if (!script_class.is_empty()) {
script_res_text = "script_class=\"" + script_class + "\" ";
}
fw->store_line("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + "]\n");
}
}
@ -1047,6 +1051,10 @@ void ResourceLoaderText::open(Ref<FileAccess> p_f, bool p_skip_first_tag) {
return;
}
if (tag.fields.has("script_class")) {
script_class = tag.fields["script_class"];
}
res_type = tag.fields["type"];
} else {
@ -1493,6 +1501,44 @@ Error ResourceLoaderText::get_classes_used(HashSet<StringName> *r_classes) {
return OK;
}
String ResourceLoaderText::recognize_script_class(Ref<FileAccess> p_f) {
error = OK;
lines = 1;
f = p_f;
stream.f = f;
ignore_resource_parsing = true;
VariantParser::Tag tag;
Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
if (err) {
_printerr();
return "";
}
if (tag.fields.has("format")) {
int fmt = tag.fields["format"];
if (fmt > FORMAT_VERSION) {
error_text = "Saved with newer format version";
_printerr();
return "";
}
}
if (tag.name != "gd_resource") {
return "";
}
if (tag.fields.has("script_class")) {
return tag.fields["script_class"];
}
return "";
}
String ResourceLoaderText::recognize(Ref<FileAccess> p_f) {
error = OK;
@ -1662,6 +1708,25 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
return ClassDB::get_compatibility_remapped_class(r);
}
String ResourceFormatLoaderText::get_resource_script_class(const String &p_path) const {
String ext = p_path.get_extension().to_lower();
if (ext != "tres") {
return String();
}
// ...for anything else must test...
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) {
return ""; //could not read
}
ResourceLoaderText 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 ResourceFormatLoaderText::get_resource_uid(const String &p_path) const {
String ext = p_path.get_extension().to_lower();
@ -1905,7 +1970,12 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso
String title = packed_scene.is_valid() ? "[gd_scene " : "[gd_resource ";
if (packed_scene.is_null()) {
title += "type=\"" + _resource_get_class(p_resource) + "\" ";
Ref<Script> script = p_resource->get_script();
if (script.is_valid() && script->get_global_name()) {
title += "script_class=\"" + String(script->get_global_name()) + "\" ";
}
}
int load_steps = saved_resources.size() + external_resources.size();
if (load_steps > 1) {
@ -2244,7 +2314,12 @@ Error ResourceLoaderText::set_uid(Ref<FileAccess> p_f, ResourceUID::ID p_uid) {
if (is_scene) {
fw->store_string("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]");
} else {
fw->store_string("[gd_resource type=\"" + res_type + "\" load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]");
String script_res_text;
if (!script_class.is_empty()) {
script_res_text = "script_class=\"" + script_class + "\" ";
}
fw->store_string("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]");
}
uint8_t c = f->get_8();

View File

@ -64,6 +64,7 @@ class ResourceLoaderText {
int resources_total = 0;
int resource_current = 0;
String resource_type;
String script_class;
VariantParser::Tag next_tag;
@ -124,6 +125,7 @@ public:
void open(Ref<FileAccess> p_f, bool p_skip_first_tag = false);
String recognize(Ref<FileAccess> p_f);
String recognize_script_class(Ref<FileAccess> p_f);
ResourceUID::ID get_uid(Ref<FileAccess> p_f);
void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
Error rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const HashMap<String, String> &p_map);
@ -143,6 +145,7 @@ public:
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);