Ability to change a resource UID from API
- Works for text, binary and imported resources
- Allows better clean up of duplicate files.
TODO (future PRs):
- Use this API for assigning new UIDs to copied files in FS dock instead of current (kind of hackish) code.
- Use this API for UID conflict on FS scanning (if more than one file has the same UID, the newer one(s) should get assigned a different UID).
This API can be used together with:
ResourceUID::get_singleton()->create_id()
// To assign new UID to a file:
ResourceSaver::set_uid( "<filepath>", ResourceUID::get_singleton()->create_id() );
to assign new Unique IDs to files.
I don't like how set_uid() duplicates lots of code. Can't it just re-use the saving code?
@KoBeWi I generally prefer that this code is duplicated rather than reused and make a complex function even more complex. Its still a very simple change so it should be fine I think.
Duplicating big complex functions makes them more difficult to keep in sync in case a modification is needed.
@KoBeWi The problem is that they do different things and, honestly, its quite sensible code that will corrupt stuff if there is a bug so I prefer to not touch it and keep it simple/separate to ensure this PR can be merged at no risk of breaking things.
Feel free to clean it up and merge code if you feel like it after this PR is merged, as long as you want to assume that risk. (I would do it after 4.0 as part of broader clean up).
Sooo I tried to test if it works and used this hack (editor node)
case EDIT_REDO: {
ResourceSaver::set_uid("res://icon.svg", ResourceUID::get_singleton()->text_to_id("test1"));
ResourceSaver::set_uid("res://new_theme.tres", ResourceUID::get_singleton()->text_to_id("test2"));
ResourceSaver::set_uid("res://new_theme.res", ResourceUID::get_singleton()->text_to_id("test3"));
The method has no effect (no UID is changed in any of the files) and icon.svg import becomes corrupted (to the point that I had to delete the source file and copy a new one).
How is this new function supposed to be used?
@KoBeWi Did some fixes, tested more thoroughly this time and it seems to be working fine now. If you want to check whether its working, you can use this code instead of the one you wrote:
case EDIT_REDO: {
ResourceSaver::set_uid("res://icon.svg", 123);
ResourceSaver::set_uid("res://new_theme.tres",456);
ResourceSaver::set_uid("res://new_theme.res", 789);
Then exit the editor, open it again and open .godot/editor/filesystem_cache7, you should see those numbers as the cached UIDs.
Why won't text_to_id() work though? The UID is stored as <invalid>.
But the number UIDs work. Except for new_theme.tres, which for whatever reason gets saved as new_theme.tres.uidren (with correct UID) and the original file isn't modified.
@KoBeWi text_to_id expects a valid uid text format (beginning with uid://, followed by hexadecimal, as a example: uid://123abc ), since UIDs are 64 bits integers, not text. I used numbers entered manually to test more easily whether the ID was correctly set.
And what about the uidren thing? It was created by set_uid() so it's probably related. (I tested with newly created, empty Theme)
@KoBeWi I fixed that, do you still see it?
It's still there, here's MRP: Uidren.zip Note that I'm testing on newest master, so you might need to rebase to get the same result.
@KoBeWi I really can't reproduce it, even rebasing on master and testing your sample project it seems to work fine for me. The .tres file appears correct with the UID changed:
[gd_resource type="Theme" load_steps=0 format=3 uid="uid://e6a"]
[resource]
And no .uidren files.
I pushed the repo again just in case I forgot to commit something, so please make sure to test it again.
Maybe it's system-specific? I'm on Windows.
I even checked out to your branch to make sure and it's still the same.
@KoBeWi I tested on Windows and everything works fine here. Can you try debugging why this piece of code fails in your build?
https://github.com/godotengine/godot/pull/69616/files#diff-1de98c58c8105cadebe21331cf1355ec08ea32baeda8bb25fb975f79e767426cR2266
@KoBeWi Nevermind, I think I found the problem. Let me amend. The strange thing is that this should also fail in many other places.
Alright, I think it should work now.
It doesn't 🙃
And the UID is wrong now 🙃🙃
[gd_resource type="Theme" load_steps=0 format=3 uid="uid://no"]
EDIT: Also I did this test
if (!all_ok) {
print_line(">", fw->get_error());
return ERR_CANT_CREATE;
} else {
print_line("OK");
}
It prints OK
EDIT2:
print_line(da->remove(local_path));
print_line(da->rename(local_path + ".uidren", local_path));
Results in 1 1
This is because of the removal of the close() function, in cases like this its difficult to keep track of where there are still references to the file.
@KoBeWi I think it should be working fine now.
:tada:
Thanks!