Page MenuHome

Remove orphan datablocks directly from File->Clean Up menu
ClosedPublic

Authored by Antonio Vazquez (antoniov) on Dec 18 2019, 7:57 PM.

Details

Summary

Actually, to purge orphans datablock you need go to Outliner, enable Orphan mode and press Purge button (that sometimes is out of the view because the window is too narrow).

To have this option hidden make very difficult to users use and understand what means orphan data, so this patch just adds a new Clean Up menu to File menu with this option. This menu could be used in the future for more clean up options. To have a general Clean Up menu is common used in other softwares.

Here an example video (the outlines is displayed only to see the effect of the operator, but is not required):

Diff Detail

Event Timeline

  • Move function to library module
Antonio Vazquez (antoniov) retitled this revision from Remove orphan datablocks directly from menu to Remove orphan datablocks directly from File->Clean Up menu.Dec 18 2019, 8:07 PM
Antonio Vazquez (antoniov) edited the summary of this revision. (Show Details)
This comment was removed by Juan Gea (juang3d).
  • Change Text and Tooltip
William Reynish (billreynish) requested changes to this revision.Dec 19 2019, 5:55 PM

Seems reasonable to me. Slight correction is needed for the name, which seems to have a typo.

I would suggest 'Purge Unused Data', but we could also use 'Purge Orphaned Data'.

This revision now requires changes to proceed.Dec 19 2019, 5:55 PM

To me this seems ok now, but probably best if @Bastien Montagne (mont29) takes a look too.

This revision is now accepted and ready to land.Dec 19 2019, 6:03 PM
Bastien Montagne (mont29) requested changes to this revision.Dec 20 2019, 12:29 PM

EDIT: Meeeh, just realized/remembered we already had OUTLINER_OT_orphans_purge(), which basically does all that what I said above… Besides not handling linked data at all, which am not sure we should care about anyway?

So just move most of that operator's code in the BKE function I guess? Not sure why you went on and re-invented the whole wheel here… ;)


Think the feature is interesting indeed. However, there are several issues with current patch:

The BKE code need to be changed, it is currently rather inefficient in case you have lots of orphans to delete, and/or have a big production file with thousands of datablocks in it. See comments below for details.

It is also very bad to have the same logic replicated twice, once for just the confirmation message in the invoke callback of the operator. This should be moved to the BKE function as well, with a 'simulate' toggle to prevent actual deletion.

And this operator has nothing to do in scene area. Best place I can think for it currently is with the files/linking ops, in WM area. Probably even add a new implementation file for this, wm_files_cleanup.c.

source/blender/blenkernel/intern/library.c
2483 ↗(On Diff #20417)

Name: while current BKE_library is a mess of various old ugly names, new convention is relatively clear - BKE_library is for operations over *libraries* only. Operation over the whole Main are using BKE_main_id_ prefix.

So BKE_main_id_orphaned_delete() ?

2491–2497 ↗(On Diff #20417)

In the end, I think you should only care about local data-blocks in that loop, and use existing BKE_library_unused_linked_data_set_tag() to tag unused linked data? If we actually want to manage linked data at all here, that is…

This should also take care of the 'archipelago' case (when you have a dependency loop between linked IDs, and none is actually used by any local data).

2494–2495 ↗(On Diff #20417)

This is fairly unclear to me… Needs some comments about what case this is addressing. Also, ID_REAL_USERS(id) <= 1 is always true here (first if above).

And calling BKE_library_ID_is_indirectly_used() is everything but cheap (loop on bmain inside loop on bmain…). You can alleviate that last point by using BKE_main_relations_create()/_free() around that whole loop (together with not deleting IDs in that same loop, as said in next comment below).

You might then miss some 'closed dependency loop' cases (indirectly linked data used by linked data that is to be removed), but think we can live with that for now.

2500 ↗(On Diff #20417)

Deleting an ID after the other is very inefficient. You should rather tag all IDs to be deleted, and then call BKE_id_multi_tagged_delete() outside of the loop.

source/blender/editors/scene/scene_edit.c
287–297 ↗(On Diff #20417)

This uses two different code paths to do the same thing, one to count items to be deleted, one to actually delete them. Not a good idea.

Think the BKE function could easily take such int array parameter, and a bool flag to say 'simulate only'. That way, you could also print an info string about amount of deleted IDs at the end of the exec callback (since that operator might also be called without invoke...).

347 ↗(On Diff #20417)

Just use name you want in menu entry, instead of defining one UI name here and then overriding it in the menu entry.

This revision now requires changes to proceed.Dec 20 2019, 12:29 PM

Refactor the patch and now reuse the Outliner operator.

@Bastien Montagne (mont29) I have reused the outliner operator changing only the poll function and avoid an update of the outliner tree (crash if it's executed from Topbar).

That’s even simpler indeed… LGTM.

source/blender/editors/space_outliner/outliner_edit.c
2180

sa != NULL (better to be explicit here…)

2279

sa != NULL (better to be explicit here…)

This revision is now accepted and ready to land.Dec 20 2019, 5:14 PM