Simplify Subresource Saving

Redo edited subresource (and resource) saving in a much more simplified way.
I think this should work (unless I am missing something) and be faster than what is there.
It should also supersede #55885.

I am not 100% entirely convinced that this approach works, but I think it should so please test.
This commit is contained in:
reduz 2022-06-22 19:03:43 +02:00
parent 3ccff61979
commit 9eb5f2a0d7
1 changed files with 27 additions and 41 deletions

View File

@ -1614,34 +1614,6 @@ bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_nod
return false;
}
static bool _find_edited_resources(const Ref<Resource> &p_resource, HashSet<Ref<Resource>> &edited_resources) {
if (p_resource->is_edited()) {
edited_resources.insert(p_resource);
return true;
}
List<PropertyInfo> plist;
p_resource->get_property_list(&plist);
for (const PropertyInfo &E : plist) {
if (E.type == Variant::OBJECT && E.usage & PROPERTY_USAGE_STORAGE && !(E.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT)) {
Ref<Resource> res = p_resource->get(E.name);
if (res.is_null()) {
continue;
}
if (res->get_path().is_resource_file()) { // Not a subresource, continue.
continue;
}
if (_find_edited_resources(res, edited_resources)) {
return true;
}
}
}
return false;
}
int EditorNode::_save_external_resources() {
// Save external resources and its subresources if any was modified.
@ -1651,27 +1623,41 @@ int EditorNode::_save_external_resources() {
}
flg |= ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
HashSet<Ref<Resource>> edited_subresources;
HashSet<String> edited_resources;
int saved = 0;
List<Ref<Resource>> cached;
ResourceCache::get_cached_resources(&cached);
for (const Ref<Resource> &res : cached) {
if (!res->get_path().is_resource_file()) {
for (Ref<Resource> res : cached) {
if (!res->is_edited()) {
continue;
}
// not only check if this resource is edited, check contained subresources too
if (_find_edited_resources(res, edited_subresources)) {
ResourceSaver::save(res->get_path(), res, flg);
saved++;
String path = res->get_path();
if (path.begins_with("res://")) {
int subres_pos = path.find("::");
if (subres_pos == -1) {
// Actual resource.
edited_resources.insert(path);
} else {
edited_resources.insert(path.substr(0, subres_pos));
}
}
res->set_edited(false);
}
// Clear later, because user may have put the same subresource in two different resources,
// which will be shared until the next reload.
for (const Ref<Resource> &E : edited_subresources) {
Ref<Resource> res = E;
res->set_edited(false);
for (const String &E : edited_resources) {
Ref<Resource> res = Ref<Resource>(ResourceCache::get(E));
if (!res.is_valid()) {
continue; // Maybe it was erased in a thread, who knows.
}
Ref<PackedScene> ps = res;
if (ps.is_valid()) {
continue; // Do not save PackedScenes, this will mess up the editor.
}
ResourceSaver::save(res->get_path(), res, flg);
saved++;
}
return saved;