Outliner: modernize Purge operator.
authorBastien Montagne <montagne29@wanadoo.fr>
Thu, 7 Feb 2019 16:17:24 +0000 (17:17 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Thu, 7 Feb 2019 19:46:53 +0000 (20:46 +0100)
That guy was still from the era where only way to remove an ID was to
save & reload the .blend file. Use modern code instead, should also be
much, much more efficient in big production files.

And that’s another nice occasion to add/test new batch ID deletion code, too. ;)

Related to T61276 Make Single User unlinks original object.

source/blender/editors/space_outliner/outliner_edit.c

index 274897c0a13d45fe3bffdf14e7c32f077457f34b..2f765fd0c664f255adb4b1271342c45cd0a1f314 100644 (file)
@@ -1856,16 +1856,37 @@ static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEv
                                           "Click here to proceed...");
 }
 
+static bool outliner_orphans_purge_tag_cb(Main *UNUSED(bmain), ID *id, void *UNUSED(user_data))
+{
+       if (id->us == 0) {
+               id->tag |= LIB_TAG_DOIT;
+       }
+       else {
+               id->tag &= ~LIB_TAG_DOIT;
+       }
+       return true;
+}
+
 static int outliner_orphans_purge_exec(bContext *C, wmOperator *UNUSED(op))
 {
-       /* Firstly, ensure that the file has been saved,
-        * so that the latest changes since the last save
-        * are retained...
-        */
-       WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL);
+       Main *bmain = CTX_data_main(C);
+       SpaceOops *soops = CTX_wm_space_outliner(C);
+
+       /* Tag all IDs having zero users. */
+       BKE_main_foreach_id(bmain, false, outliner_orphans_purge_tag_cb, NULL);
 
-       /* Now, reload the file to get rid of the orphans... */
-       WM_operator_name_call(C, "WM_OT_revert_mainfile", WM_OP_EXEC_DEFAULT, NULL);
+       BKE_id_multi_tagged_delete(bmain);
+
+       /* XXX: tree management normally happens from draw_outliner(), but when
+        *      you're clicking to fast on Delete object from context menu in
+        *      outliner several mouse events can be handled in one cycle without
+        *      handling notifiers/redraw which leads to deleting the same object twice.
+        *      cleanup tree here to prevent such cases. */
+       outliner_cleanup_tree(soops);
+
+       DEG_relations_tag_update(bmain);
+       WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
        return OPERATOR_FINISHED;
 }
 
@@ -1874,8 +1895,7 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
        /* identifiers */
        ot->idname = "OUTLINER_OT_orphans_purge";
        ot->name = "Purge All";
-       ot->description = "Clear all orphaned data-blocks without any users from the file "
-                         "(cannot be undone, saves to current .blend file)";
+       ot->description = "Clear all orphaned data-blocks without any users from the file.";
 
        /* callbacks */
        ot->invoke = outliner_orphans_purge_invoke;