Commit: 842310a9b0d70b48634e18e44775359bbd18ed4f
Author: Bastien Montagne
Date:   Tue Dec 1 15:33:44 2015 +0100
Branches: master
https://developer.blender.org/rB842310a9b0d70b48634e18e44775359bbd18ed4f

Outliner: add an option to "delete" libraries.

Caminandes team request. In current master it's not possible to do this in a 
total
clean way, so we are simply setting all user counts of given lib's datablocks 
to zero
(similar to rna_ID_user_clear()'s doing).

This is a bit crappy because it still lets datablocks floating around (with 
invalid
user count values), and requires a save & reload cycle to be finalized. But for 
now
it should be good enough. Propper implementation will be added to id-remap.

===================================================================

M       source/blender/editors/space_outliner/outliner_edit.c
M       source/blender/editors/space_outliner/outliner_intern.h
M       source/blender/editors/space_outliner/outliner_ops.c
M       source/blender/editors/space_outliner/outliner_tools.c

===================================================================

diff --git a/source/blender/editors/space_outliner/outliner_edit.c 
b/source/blender/editors/space_outliner/outliner_edit.c
index 6d42067..094407b 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -290,6 +290,103 @@ void OUTLINER_OT_item_rename(wmOperatorType *ot)
        ot->poll = ED_operator_outliner_active;
 }
 
+/* Library delete --------------------------------------------------- */
+
+static void lib_delete(bContext *C, TreeElement *te, TreeStoreElem *tselem, 
ReportList *reports)
+{
+       Library *lib = (Library *)tselem->id;
+       ListBase *lbarray[MAX_LIBARRAY];
+       int a;
+
+       BLI_assert(te->idcode == ID_LI && lib != NULL);
+       UNUSED_VARS_NDEBUG(te);
+
+       /* We simply set all ID from given lib (including lib itself) to zero 
user count.
+        * It is not possible to do a proper cleanup without a save/reload in 
current master. */
+       a = set_listbasepointers(CTX_data_main(C), lbarray);
+       while (a--) {
+               ListBase *lb = lbarray[a];
+               ID *id;
+
+               for (id = lb->first; id; id = id->next) {
+                       if (id->lib == lib) {
+                               id_fake_user_clear(id);
+                               id->us = 0;
+                       }
+               }
+       }
+
+       BKE_reportf(reports, RPT_WARNING,
+                   "Please save and reload .blend file to complete deletion of 
'%s' library",
+                   ((Library *)tselem->id)->filepath);
+}
+
+void lib_delete_cb(
+        bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem 
*UNUSED(tsep), TreeStoreElem *tselem)
+{
+       lib_delete(C, te, tselem, CTX_wm_reports(C));
+}
+
+static int outliner_lib_delete_invoke_do(bContext *C, ReportList *reports, 
TreeElement *te, const float mval[2])
+{
+       if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+               TreeStoreElem *tselem = TREESTORE(te);
+
+               if (te->idcode == ID_LI && tselem->id) {
+                       if (((Library *)tselem->id)->parent) {
+                               BKE_reportf(reports, RPT_ERROR_INVALID_INPUT,
+                                           "Cannot delete indirectly linked 
library '%s'", ((Library *)tselem->id)->filepath);
+                               return OPERATOR_CANCELLED;
+                       }
+
+                       lib_delete(C, te, tselem, reports);
+                       return OPERATOR_FINISHED;
+               }
+       }
+       else {
+               for (te = te->subtree.first; te; te = te->next) {
+                       int ret;
+                       if ((ret = outliner_lib_delete_invoke_do(C, reports, 
te, mval))) {
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int outliner_lib_delete_invoke(bContext *C, wmOperator *op, const 
wmEvent *event)
+{
+       ARegion *ar = CTX_wm_region(C);
+       SpaceOops *soops = CTX_wm_space_outliner(C);
+       TreeElement *te;
+       float fmval[2];
+
+       BLI_assert(ar && soops);
+
+       UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], 
&fmval[0], &fmval[1]);
+
+       for (te = soops->tree.first; te; te = te->next) {
+               int ret;
+
+               if ((ret = outliner_lib_delete_invoke_do(C, op->reports, te, 
fmval))) {
+                       return ret;
+               }
+       }
+
+       return OPERATOR_CANCELLED;
+}
+
+void OUTLINER_OT_lib_delete(wmOperatorType *ot)
+{
+       ot->name = "Delete Library";
+       ot->idname = "OUTLINER_OT_lib_delete";
+       ot->description = "Delete the library under cursorn (needs a 
save/reload)";
+
+       ot->invoke = outliner_lib_delete_invoke;
+       ot->poll = ED_operator_outliner_active;
+}
+
 /* ************************************************************** */
 /* Setting Toggling Operators */
 
diff --git a/source/blender/editors/space_outliner/outliner_intern.h 
b/source/blender/editors/space_outliner/outliner_intern.h
index f10e6be..262aa9b 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -176,6 +176,10 @@ void group_toggle_renderability_cb(struct bContext *C, 
struct Scene *scene, Tree
 
 void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, 
struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
 
+void lib_delete_cb(
+        struct bContext *C, struct Scene *scene, struct TreeElement *te,
+        struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
+
 TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float 
fmval[2], const bool children);
 /* ...................................................... */
 
@@ -183,6 +187,8 @@ void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
 void OUTLINER_OT_item_openclose(struct wmOperatorType *ot);
 void OUTLINER_OT_item_rename(struct wmOperatorType *ot);
 
+void OUTLINER_OT_lib_delete(struct wmOperatorType *ot);
+
 void OUTLINER_OT_show_one_level(struct wmOperatorType *ot);
 void OUTLINER_OT_show_active(struct wmOperatorType *ot);
 void OUTLINER_OT_show_hierarchy(struct wmOperatorType *ot);
@@ -218,6 +224,7 @@ void OUTLINER_OT_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_group_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_data_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c 
b/source/blender/editors/space_outliner/outliner_ops.c
index 839d44d..9710c3f 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -47,10 +47,12 @@ void outliner_operatortypes(void)
        WM_operatortype_append(OUTLINER_OT_select_border);
        WM_operatortype_append(OUTLINER_OT_item_openclose);
        WM_operatortype_append(OUTLINER_OT_item_rename);
+       WM_operatortype_append(OUTLINER_OT_lib_delete);
        WM_operatortype_append(OUTLINER_OT_operation);
        WM_operatortype_append(OUTLINER_OT_scene_operation);
        WM_operatortype_append(OUTLINER_OT_object_operation);
        WM_operatortype_append(OUTLINER_OT_group_operation);
+       WM_operatortype_append(OUTLINER_OT_lib_operation);
        WM_operatortype_append(OUTLINER_OT_id_operation);
        WM_operatortype_append(OUTLINER_OT_data_operation);
        WM_operatortype_append(OUTLINER_OT_animdata_operation);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c 
b/source/blender/editors/space_outliner/outliner_tools.c
index 313a75f..dd0b29c 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -119,6 +119,7 @@ static void set_operation_types(SpaceOops *soops, ListBase 
*lb,
                                        case ID_MA: case ID_TE: case ID_IP: 
case ID_IM:
                                        case ID_SO: case ID_KE: case ID_WO: 
case ID_AC:
                                        case ID_NLA: case ID_TXT: case ID_GR: 
case ID_LS:
+                                       case ID_LI:
                                                if (*idlevel == 0) *idlevel = 
idcode;
                                                else if (*idlevel != idcode) 
*idlevel = -1;
                                                break;
@@ -846,7 +847,7 @@ enum {
        OL_OP_TOGVIS,
        OL_OP_TOGSEL,
        OL_OP_TOGREN,
-       OL_OP_RENAME
+       OL_OP_RENAME,
 };
 
 static EnumPropertyItem prop_object_op_types[] = {
@@ -1246,6 +1247,88 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot)
 
 /* **************************************** */
 
+typedef enum eOutlinerLibOpTypes {
+       OL_LIB_INVALID = 0,
+
+       OL_LIB_RENAME,
+       OL_LIB_DELETE,
+} eOutlinerLibOpTypes;
+
+static EnumPropertyItem outliner_lib_op_type_items[] = {
+       {OL_LIB_RENAME, "RENAME", 0, "Rename", ""},
+    {OL_LIB_DELETE, "DELETE", 0, "Delete", "Delete this library and all its 
item from Blender (needs a save/reload)"},
+       {0, NULL, 0, NULL, NULL}
+
+};
+
+static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       SpaceOops *soops = CTX_wm_space_outliner(C);
+       int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+       eOutlinerIdOpTypes event;
+
+       /* check for invalid states */
+       if (soops == NULL)
+               return OPERATOR_CANCELLED;
+
+       set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, 
&idlevel, &datalevel);
+
+       event = RNA_enum_get(op->ptr, "type");
+
+       switch (event) {
+               case OL_LIB_RENAME:
+               {
+                       /* rename */
+                       outliner_do_libdata_operation(C, scene, soops, 
&soops->tree, item_rename_cb);
+
+                       WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+                       ED_undo_push(C, "Rename");
+                       break;
+               }
+               case OL_LIB_DELETE:
+               {
+                       /* delete */
+                       outliner_do_libdata_operation(C, scene, soops, 
&soops->tree, lib_delete_cb);
+
+                       WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+                       /* Note: no undo possible here really, not 100% sure 
why... Probably because of library optimisations
+                        *       in undo/redo process? */
+                       /* ED_undo_push(C, "Rename"); */
+                       break;
+               }
+               default:
+                       /* invalid - unhandled */
+                       break;
+       }
+
+       /* wrong notifier still... */
+       WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+
+       /* XXX: this is just so that outliner is always up to date */
+       WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+       return OPERATOR_FINISHED;
+}
+
+
+void OUTLINER_OT_lib_operation(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Outliner Library Operation";
+       ot->idname = "OUTLINER_OT_lib_operation";
+       ot->description = "";
+
+       /* callbacks */
+       ot->invoke = WM_menu_invoke;
+       ot->exec = outliner_lib_operation_exec;
+       ot->poll = ED_operator_outliner_active;
+
+       ot->prop = RNA_def_enum(ot->srna, "type", outliner_lib_op_type_items, 
0, "Library Operation", "");
+}
+
+/* **************************************** */
+
 static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase 
*lb, ID *newid,
                                          void (*operation_cb)(TreeElement *, 
TreeStoreElem *, TreeStoreElem *, ID *))
 {
@@ -1703,10 +1786,17 @@ static int do_outliner_operation_event(bContext *C, 
Scene *scene, ARegion *ar, S
                                BKE_report(reports, RPT_WARNING, "Mixed 
selection");
                        }
                        else {
-                               if (idlevel == ID_GR)
-                                       WM_operator_name_call(C, 
"OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
-                               else
-                                       WM_operator_name_call(C, 
"OUTLINER_OT_id_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+                               switch (idlevel) {
+                                       case ID_GR:
+                                               WM_operator_name_call(C, 
"OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+                                               break;
+                                       case ID_LI:
+                                               WM_operator_name_call(C, 
"OUTLINER_OT_lib_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+                                               break;
+                                       default:
+                                               WM_operator_name_call(C, 
"OUTLINER_OT_id_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+                                               br

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to