1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-12 13:20:55 +00:00

Fix for directory duplication

This change makes it so if you duplicate a folder, the asset references between resources in that folder will point to the new duplicated files.

For instance, if you had dir-a/foo.tscn and dir-a/foo.png where your scene references the png. Previously duplicate would copy both of them to dir-b but dir-b/foo.tscn would still be referencing dir-a/foo.png!
This commit is contained in:
David Nikdel
2025-05-23 21:18:30 -05:00
parent 45fc515ae3
commit 33c83a3257
2 changed files with 44 additions and 24 deletions

View File

@@ -3041,15 +3041,21 @@ Error EditorFileSystem::_copy_file(const String &p_from, const String &p_to) {
return err; return err;
} }
// Remove uid from .import file to avoid conflict. // Roll a new uid for this copied .import file to avoid conflict.
ResourceUID::ID res_uid = ResourceUID::get_singleton()->create_id();
// Save the new .import file
Ref<ConfigFile> cfg; Ref<ConfigFile> cfg;
cfg.instantiate(); cfg.instantiate();
cfg->load(p_from + ".import"); cfg->load(p_from + ".import");
cfg->erase_section_key("remap", "uid"); cfg->set_value("remap", "uid", ResourceUID::get_singleton()->id_to_text(res_uid));
err = cfg->save(p_to + ".import"); err = cfg->save(p_to + ".import");
if (err != OK) { if (err != OK) {
return err; return err;
} }
// Make sure it's immediately added to the map so we can remap dependencies if we want to after this.
ResourceUID::get_singleton()->add_id(res_uid, p_to);
} else if (ResourceLoader::get_resource_uid(p_from) == ResourceUID::INVALID_ID) { } else if (ResourceLoader::get_resource_uid(p_from) == ResourceUID::INVALID_ID) {
// Files which do not use an uid can just be copied. // Files which do not use an uid can just be copied.
Error err = da->copy(p_from, p_to); Error err = da->copy(p_from, p_to);
@@ -3074,7 +3080,7 @@ Error EditorFileSystem::_copy_file(const String &p_from, const String &p_to) {
return OK; return OK;
} }
bool EditorFileSystem::_copy_directory(const String &p_from, const String &p_to, List<CopiedFile> *p_files) { bool EditorFileSystem::_copy_directory(const String &p_from, const String &p_to, HashMap<String, String> *p_files) {
Ref<DirAccess> old_dir = DirAccess::open(p_from); Ref<DirAccess> old_dir = DirAccess::open(p_from);
ERR_FAIL_COND_V(old_dir.is_null(), false); ERR_FAIL_COND_V(old_dir.is_null(), false);
@@ -3091,10 +3097,7 @@ bool EditorFileSystem::_copy_directory(const String &p_from, const String &p_to,
if (old_dir->current_is_dir()) { if (old_dir->current_is_dir()) {
success = _copy_directory(p_from.path_join(F), p_to.path_join(F), p_files) && success; success = _copy_directory(p_from.path_join(F), p_to.path_join(F), p_files) && success;
} else if (F.get_extension() != "import" && F.get_extension() != "uid") { } else if (F.get_extension() != "import" && F.get_extension() != "uid") {
CopiedFile copy; (*p_files)[p_from.path_join(F)] = p_to.path_join(F);
copy.from = p_from.path_join(F);
copy.to = p_to.path_join(F);
p_files->push_back(copy);
} }
} }
return success; return success;
@@ -3489,24 +3492,46 @@ Error EditorFileSystem::copy_file(const String &p_from, const String &p_to) {
} }
Error EditorFileSystem::copy_directory(const String &p_from, const String &p_to) { Error EditorFileSystem::copy_directory(const String &p_from, const String &p_to) {
List<CopiedFile> files; // Recursively copy directories and build a map of files to copy.
HashMap<String, String> files;
bool success = _copy_directory(p_from, p_to, &files); bool success = _copy_directory(p_from, p_to, &files);
EditorProgress *ep = nullptr; // Copy the files themselves
if (files.size() > 10) { if (success) {
ep = memnew(EditorProgress("_copy_files", TTR("Copying files..."), files.size())); EditorProgress *ep = nullptr;
if (files.size() > 10) {
ep = memnew(EditorProgress("copy_directory", TTR("Copying files..."), files.size()));
}
int i = 0;
for (const KeyValue<String, String> &tuple : files) {
if (_copy_file(tuple.key, tuple.value) != OK) {
success = false;
}
if (ep) {
ep->step(tuple.key.get_file(), i++, false);
}
}
memdelete_notnull(ep);
} }
int i = 0; // Now remap any internal dependencies (within the folder) to use the new files.
for (const CopiedFile &F : files) { if (success) {
if (_copy_file(F.from, F.to) != OK) { EditorProgress *ep = nullptr;
success = false; if (files.size() > 10) {
ep = memnew(EditorProgress("copy_directory", TTR("Remapping dependencies..."), files.size()));
} }
if (ep) { int i = 0;
ep->step(F.from.get_file(), i++, false); for (const KeyValue<String, String> &tuple : files) {
if (ResourceLoader::rename_dependencies(tuple.value, files) != OK) {
success = false;
}
update_file(tuple.value);
if (ep) {
ep->step(tuple.key.get_file(), i++, false);
}
} }
memdelete_notnull(ep);
} }
memdelete_notnull(ep);
EditorFileSystemDirectory *efd = get_filesystem_path(p_to); EditorFileSystemDirectory *efd = get_filesystem_path(p_to);
ERR_FAIL_NULL_V(efd, FAILED); ERR_FAIL_NULL_V(efd, FAILED);

View File

@@ -344,16 +344,11 @@ class EditorFileSystem : public Node {
HashSet<String> group_file_cache; HashSet<String> group_file_cache;
HashMap<String, String> file_icon_cache; HashMap<String, String> file_icon_cache;
struct CopiedFile {
String from;
String to;
};
bool refresh_queued = false; bool refresh_queued = false;
HashSet<ObjectID> folders_to_sort; HashSet<ObjectID> folders_to_sort;
Error _copy_file(const String &p_from, const String &p_to); Error _copy_file(const String &p_from, const String &p_to);
bool _copy_directory(const String &p_from, const String &p_to, List<CopiedFile> *p_files); bool _copy_directory(const String &p_from, const String &p_to, HashMap<String, String> *p_files);
void _queue_refresh_filesystem(); void _queue_refresh_filesystem();
void _refresh_filesystem(); void _refresh_filesystem();