RNA: make bpy.data.orphans_purge() return number of deleted datablocks
Sometimes multiple calls to `bpy.data.orphans_purge()` are needed to delete all orphans, because a call can turn previously-used datablocks into orphans. Returning the number of deleted datablocks makes it possible to keep looping until nothing can be deleted any more. This patch keeps track of deletions in `id_delete()` so that it can be returned up the call stack. Reviewed By: mont29 Differential Revision: https://developer.blender.org/D9918
This commit is contained in:
@@ -200,7 +200,7 @@ void BKE_id_free(struct Main *bmain, void *idv);
|
||||
void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
|
||||
|
||||
void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
|
||||
void BKE_id_multi_tagged_delete(struct Main *bmain) ATTR_NONNULL();
|
||||
size_t BKE_id_multi_tagged_delete(struct Main *bmain) ATTR_NONNULL();
|
||||
|
||||
void BKE_libblock_management_main_add(struct Main *bmain, void *idv);
|
||||
void BKE_libblock_management_main_remove(struct Main *bmain, void *idv);
|
||||
|
||||
@@ -237,7 +237,7 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */
|
||||
}
|
||||
}
|
||||
|
||||
static void id_delete(Main *bmain, const bool do_tagged_deletion)
|
||||
static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
||||
{
|
||||
const int tag = LIB_TAG_DOIT;
|
||||
ListBase *lbarray[MAX_LIBARRAY];
|
||||
@@ -346,6 +346,7 @@ static void id_delete(Main *bmain, const bool do_tagged_deletion)
|
||||
* have been already cleared when we reach it
|
||||
* (e.g. Objects being processed before meshes, they'll have already released their 'reference'
|
||||
* over meshes when we come to freeing obdata). */
|
||||
size_t num_datablocks_deleted = 0;
|
||||
for (i = do_tagged_deletion ? 1 : base_count; i--;) {
|
||||
ListBase *lb = lbarray[i];
|
||||
ID *id, *id_next;
|
||||
@@ -360,11 +361,13 @@ static void id_delete(Main *bmain, const bool do_tagged_deletion)
|
||||
BLI_assert(id->us == 0);
|
||||
}
|
||||
BKE_id_free_ex(bmain, id, free_flag, !do_tagged_deletion);
|
||||
++num_datablocks_deleted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bmain->is_memfile_undo_written = false;
|
||||
return num_datablocks_deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,8 +389,9 @@ void BKE_id_delete(Main *bmain, void *idv)
|
||||
*
|
||||
* \warning Considered experimental for now, seems to be working OK but this is
|
||||
* risky code in a complicated area.
|
||||
* \return Number of deleted datablocks.
|
||||
*/
|
||||
void BKE_id_multi_tagged_delete(Main *bmain)
|
||||
size_t BKE_id_multi_tagged_delete(Main *bmain)
|
||||
{
|
||||
id_delete(bmain, true);
|
||||
return id_delete(bmain, true);
|
||||
}
|
||||
|
||||
@@ -353,6 +353,8 @@ PyDoc_STRVAR(bpy_orphans_purge_doc,
|
||||
"\n"
|
||||
" Remove (delete) all IDs with no user.\n"
|
||||
"\n"
|
||||
" :return: The number of deleted IDs.\n"
|
||||
"\n"
|
||||
" WARNING: Considered experimental feature currently.\n");
|
||||
static PyObject *bpy_orphans_purge(PyObject *UNUSED(self),
|
||||
PyObject *UNUSED(args),
|
||||
@@ -376,13 +378,11 @@ static PyObject *bpy_orphans_purge(PyObject *UNUSED(self),
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
BKE_id_multi_tagged_delete(bmain);
|
||||
const size_t num_datablocks_deleted = BKE_id_multi_tagged_delete(bmain);
|
||||
/* Force full redraw, mandatory to avoid crashes when running this from UI... */
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
|
||||
return Py_None;
|
||||
return PyLong_FromSize_t(num_datablocks_deleted);
|
||||
}
|
||||
|
||||
PyMethodDef BPY_rna_id_collection_user_map_method_def = {
|
||||
|
||||
Reference in New Issue
Block a user