Repository: godotengine/godot (language: cpp)

Issue:
`.uid` files are not recreated if deleted by the user
### Tested versions

- Reproducible in: v4.4.dev5.official.9e6098432
- Not reproducible in: 4.4.dev4 and earlier (not applicable)

### System information

Godot v4.4.dev5 - Ubuntu 24.04.1 LTS 24.04 on X11 - X11 display driver, Multi-window, 2 monitors - OpenGL 3 (Compatibility) - NVIDIA GeForce GTX 1060 6GB (nvidia; 535.183.01) - Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz (4 threads)

### Issue description

If you delete the new `.uid` file for a resource (such as a .gd script), it will not be recreated and there's no way to force recreation other than deleting the .godot directory.

Bit of a weird bug because it's in part due to user error. But it's a simple mistake that gets your project into a broken state. I hit this by upgrading one of my old projects (from 4.4.dev3), a whole bunch of UID files were created and I thought "that's weird" and git clean'd them. Then I read about the design of it and realized they needed to be committed to revision control, so I tried everything I could to get them recreated, but nothing worked, other than deleting the entire .godot directory.

I gather from the design of the .uid files that this means the project is now in a broken state, as every file is expected to have a UID. I can't find any way to force the regeneration of the UID other than to delete the `.godot` directory, after which time it will create new UID files.

### Steps to reproduce

1. Create a new project.
2. Create a new scene (just based on Node, or whatever). Save as `scene.tscn`.
3. Attach a script to that scene. Save as `scene.gd` and re-save `scene.tscn`. **Verify** that `scene.gd.uid` has automatically been created with contents: `uid://pug2wk8lb40l`. I will also note that `scene.tscn` will _not_ reference the UID - it just references `scene.gd` by filename: `[ext_resource type="Script" path="res://scene.gd" id="1_ulcgi"]`.)
4. In Godot, Reload Current Project. Re-save `scene.tscn`. **Verify** that in `scene.tscn` it _will_ refer to `scene.gd` using its UID: `[ext_resource type="Script" uid="uid://pug2wk8lb40l" path="res://scene.gd" id="1_ulcgi"]`.
5. In an external program, delete `scene.gd.uid`.
6. In Godot, Reload Current Project. **Bug**: `scene.gd.uid` will not be recreated.

So there are two seemingly related issues here: firstly, on Step 3, it's weird that the scene does not reference the UID of the script it just created. Note that I needed to add Step 4 because if you delete `scene.gd.uid` while in this state, it will actually get recreated. The .uid only doesn't get recreated after a project reload, which makes the UID show up in the .tscn file.

### Minimal reproduction project (MRP)

[uid-recreate-issue.zip](https://github.com/user-attachments/files/17942391/uid-recreate-issue.zip)

Project state after following the steps to reproduce above. However note that if you open this, it _will_ recreate the .uid file because the .godot directory has been removed. Try deleting the file again and note that it won't be recreated.


Discussion / hints:

Fix patch:
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index e6047064f1ce..7a8f42c7da83 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -1260,11 +1260,15 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
 				}
 			}
 
-			if (fi->uid == ResourceUID::INVALID_ID && ResourceLoader::exists(path) && !ResourceLoader::has_custom_uid_support(path) && !FileAccess::exists(path + ".uid")) {
-				// Create a UID.
+			if (ResourceLoader::exists(path) && !ResourceLoader::has_custom_uid_support(path) && !FileAccess::exists(path + ".uid")) {
+				// Create a UID file and new UID, if it's invalid.
 				Ref<FileAccess> f = FileAccess::open(path + ".uid", FileAccess::WRITE);
 				if (f.is_valid()) {
-					fi->uid = ResourceUID::get_singleton()->create_id();
+					if (fi->uid == ResourceUID::INVALID_ID) {
+						fi->uid = ResourceUID::get_singleton()->create_id();
+					} else {
+						WARN_PRINT(vformat("Missing .uid file for path \"%s\". The file was re-created from cache.", path));
+					}
 					f->store_line(ResourceUID::get_singleton()->id_to_text(fi->uid));
 				}
 			}


Test patch: