Fix T98029: Support isolated islands of IDs when purging unused ones.

Cases were e.g. an object would use a material, and this material would
use this object (e.g. through a driver), even if both those data-blocks
are technically unused, they would remain forever since they were not
detected as such.

Now this is properly detected and purged as part of the 'recursive
purge' operation.
This commit is contained in:
Bastien Montagne 2022-07-07 12:33:45 +02:00
parent 051a341cf0
commit 97dd107070
Notes: blender-bot 2023-05-03 09:43:22 +02:00
Referenced by issue #98029, Handle 'isolated islands' of cyclic dependencies of effectively unused data-blocks in 'Recursive cleanup' code
Referenced by issue #107573, Purging orphan data deletes used mesh
1 changed files with 12 additions and 1 deletions

View File

@ -693,6 +693,13 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
* First recursively check all its valid users, if all of them can be tagged as
* unused, then we can tag this ID as such too. */
bool has_valid_from_users = false;
/* Preemptively consider this ID as unused. That way if there is a loop of dependency leading
* back to it, it won't create a fake 'valid user' detection.
* NOTE: This can only only be done for a subset of IDs, some types are never 'indirectly
* unused', same for IDs with a fake user. */
if ((id->flag & LIB_FAKEUSER) == 0 && !ELEM(GS(id->name), ID_SCE, ID_WM, ID_SCR, ID_WS, ID_LI)) {
id->tag |= tag;
}
for (MainIDRelationsEntryItem *id_from_item = id_relations->from_ids; id_from_item != NULL;
id_from_item = id_from_item->next) {
if ((id_from_item->usage_flag & ignored_usages) != 0 ||
@ -715,7 +722,11 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
break;
}
}
if (!has_valid_from_users) {
if (has_valid_from_users) {
/* This ID has 'valid' users, clear the 'tag as unused' preemptively set above. */
id->tag &= ~tag;
}
else {
/* This ID has no 'valid' users, tag it as unused. */
id->tag |= tag;
if (r_num_tagged != NULL) {