godot icon indicating copy to clipboard operation
godot copied to clipboard

Ability to change a resource UID from API

Open reduz opened this issue 3 years ago • 1 comments

  • 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.

reduz avatar Dec 05 '22 18:12 reduz

I don't like how set_uid() duplicates lots of code. Can't it just re-use the saving code?

KoBeWi avatar Dec 06 '22 12:12 KoBeWi

@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.

reduz avatar Dec 10 '22 19:12 reduz

Duplicating big complex functions makes them more difficult to keep in sync in case a modification is needed.

KoBeWi avatar Dec 11 '22 20:12 KoBeWi

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

reduz avatar Dec 17 '22 10:12 reduz

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 avatar Dec 20 '22 13:12 KoBeWi

@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.

reduz avatar Jan 06 '23 20:01 reduz

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 avatar Jan 06 '23 21:01 KoBeWi

@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.

reduz avatar Jan 06 '23 21:01 reduz

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 avatar Jan 06 '23 23:01 KoBeWi

@KoBeWi I fixed that, do you still see it?

reduz avatar Jan 09 '23 09:01 reduz

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 avatar Jan 09 '23 12:01 KoBeWi

@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.

reduz avatar Jan 09 '23 15:01 reduz

Maybe it's system-specific? I'm on Windows. image I even checked out to your branch to make sure and it's still the same.

KoBeWi avatar Jan 09 '23 15:01 KoBeWi

@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

reduz avatar Jan 09 '23 16:01 reduz

@KoBeWi Nevermind, I think I found the problem. Let me amend. The strange thing is that this should also fail in many other places.

reduz avatar Jan 09 '23 16:01 reduz

Alright, I think it should work now.

reduz avatar Jan 09 '23 16:01 reduz

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

KoBeWi avatar Jan 09 '23 17:01 KoBeWi

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.

reduz avatar Jan 09 '23 17:01 reduz

:tada:

reduz avatar Jan 09 '23 18:01 reduz

Thanks!

akien-mga avatar Jan 09 '23 22:01 akien-mga