Add experimental batch-delete of hierarchy to Outliner.

This uses the same command as regular hierarchy delete, and is only
activated when debug value is set to 666 for now.

Here on file from T60419, it gives about 20% speed-up (from 5.5s to 4.4s).
This commit is contained in:
Bastien Montagne 2019-01-17 12:09:07 +01:00
parent 33dcde4865
commit 32dc085289
Notes: blender-bot 2023-02-14 06:49:54 +01:00
Referenced by commit 2b91445ddd, Cleanup: rename Outliner function
Referenced by issue #60419, Delete Hierarchy - To delete a hierarchy takes very long
2 changed files with 90 additions and 2 deletions

View File

@ -82,6 +82,7 @@ typedef struct Global {
* * 1 - 30: EEVEE debug/stats values (01/2018).
* * 101: Enable UI debug drawing of fullscreen area's corner widget (10/2014).
* * 527: Old mysterious switch in behavior of MeshDeform modifier (before 04/2010).
* * 666: Use quicker batch delete for outliners' delete hierarchy (01/2019).
* * 777: Enable UI node panel's sockets polling (11/2011).
* * 799: Enable some mysterious new depsgraph behavior (05/2015).
* * 1112: Disable new Cloth internal springs hanlding (09/2014).

View File

@ -55,6 +55,7 @@
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_override.h"
@ -901,6 +902,80 @@ static void object_delete_hierarchy_cb(
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
static Base *outline_batch_delete_hierarchy(
ReportList *reports, Main *bmain, ViewLayer *view_layer, Scene *scene, Base *base)
{
Base *child_base, *base_next;
Object *object, *parent;
if (!base) {
return NULL;
}
object = base->object;
for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
base_next = child_base->next;
for (parent = child_base->object->parent; parent && (parent != object); parent = parent->parent);
if (parent) {
base_next = outline_batch_delete_hierarchy(reports, bmain, view_layer, scene, child_base);
}
}
base_next = base->next;
if (object->id.tag & LIB_TAG_INDIRECT) {
BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
return base_next;
}
else if (BKE_library_ID_is_indirectly_used(bmain, object) &&
ID_REAL_USERS(object) <= 1 && ID_EXTRA_USERS(object) == 0)
{
BKE_reportf(reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
object->id.name + 2, scene->id.name + 2);
return base_next;
}
DEG_id_tag_update_ex(bmain, &object->id, ID_RECALC_BASE_FLAGS);
BKE_scene_collections_object_remove(bmain, scene, object, false);
if (object->id.us == 0) {
object->id.tag |= LIB_TAG_DOIT;
}
return base_next;
}
static void object_batch_delete_hierarchy_cb(
bContext *C, ReportList *reports, Scene *scene,
TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base = (Base *)te->directdata;
Object *obedit = CTX_data_edit_object(C);
if (!base) {
base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
}
if (base) {
/* Check also library later. */
for (; obedit && (obedit != base->object); obedit = obedit->parent);
if (obedit == base->object) {
ED_object_editmode_exit(C, EM_FREEDATA);
}
outline_batch_delete_hierarchy(reports, CTX_data_main(C), view_layer, scene, base);
/* leave for ED_outliner_id_unref to handle */
#if 0
te->directdata = NULL;
tselem->id = NULL;
#endif
}
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
/* **************************************** */
enum {
@ -992,8 +1067,20 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else if (event == OL_OP_DELETE_HIERARCHY) {
outliner_do_object_operation_ex(
C, op->reports, scene, soops, &soops->tree, object_delete_hierarchy_cb, NULL, false);
/* For now, usage of batch-deletion of objects it hidden behind that debug value,
* until we get some more testing of it - *should* be safe, but... */
if (G.debug_value == 666) {
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
outliner_do_object_operation_ex(
C, op->reports, scene, soops, &soops->tree, object_batch_delete_hierarchy_cb, NULL, false);
BKE_id_multi_tagged_delete(bmain);
}
else {
outliner_do_object_operation_ex(
C, op->reports, scene, soops, &soops->tree, object_delete_hierarchy_cb, NULL, false);
}
/* XXX: See OL_OP_DELETE comment above. */
outliner_cleanup_tree(soops);