Outliner: Added recursive select/deselect (CTRL+LMB) and extend (CTRL+SHIFT+LMB)
[blender.git] / source / blender / editors / space_outliner / outliner_edit.c
index 4fa8686..78346dc 100644 (file)
@@ -81,7 +81,7 @@ static int outliner_open_back(SpaceOops *soops, TreeElement *te)
        
        for (te = te->parent; te; te = te->parent) {
                tselem = TREESTORE(te);
-               if (tselem->flag & TSE_CLOSED) { 
+               if (tselem->flag & TSE_CLOSED) {
                        tselem->flag &= ~TSE_CLOSED;
                        retval = 1;
                }
@@ -183,8 +183,8 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
 
 static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
 {
-       /* can't rename rna datablocks entries */
-       if (ELEM3(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+       /* can't rename rna datablocks entries or listbases */
+       if (ELEM4(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
                /* do nothing */;
        }
        else if (ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
@@ -197,10 +197,10 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
        }
        else if (tselem->id->lib) {
                // XXX                                          error_libdata();
-       } 
+       }
        else if (te->idcode == ID_LI && te->parent) {
                BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
-       } 
+       }
        else {
                tselem->flag |= TSE_TEXTBUT;
                ED_region_tag_redraw(ar);
@@ -222,12 +222,12 @@ static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, T
        if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
                TreeStoreElem *tselem = TREESTORE(te);
                
-               /* name and first icon */
-               if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) {
-                       
+               /* click on name */
+               if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
                        do_item_rename(ar, te, tselem, reports);
+                       return 1;
                }
-               return 1;
+               return 0;
        }
        
        for (te = te->subtree.first; te; te = te->next) {
@@ -242,14 +242,18 @@ static int outliner_item_rename(bContext *C, wmOperator *UNUSED(op), wmEvent *ev
        SpaceOops *soops = CTX_wm_space_outliner(C);
        TreeElement *te;
        float fmval[2];
+       int any_renamed = FALSE;
        
        UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval + 1);
        
        for (te = soops->tree.first; te; te = te->next) {
-               if (do_outliner_item_rename(C, ar, soops, te, fmval)) break;
+               if (do_outliner_item_rename(C, ar, soops, te, fmval)) {
+                       any_renamed = TRUE;
+                       break;
+               }
        }
        
-       return OPERATOR_FINISHED;
+       return any_renamed ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
 }
 
 
@@ -368,12 +372,14 @@ void group_toggle_visibility_cb(bContext *UNUSED(C), Scene *scene, TreeElement *
 
 static int outliner_toggle_visibility_exec(bContext *C, wmOperator *UNUSED(op))
 {
+       Main *bmain = CTX_data_main(C);
        SpaceOops *soops = CTX_wm_space_outliner(C);
        Scene *scene = CTX_data_scene(C);
        ARegion *ar = CTX_wm_region(C);
        
        outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb);
        
+       DAG_id_type_tag(bmain, ID_OB);
        WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
        ED_region_tag_redraw(ar);
        
@@ -464,11 +470,13 @@ void group_toggle_renderability_cb(bContext *UNUSED(C), Scene *scene, TreeElemen
 
 static int outliner_toggle_renderability_exec(bContext *C, wmOperator *UNUSED(op))
 {
+       Main *bmain = CTX_data_main(C);
        SpaceOops *soops = CTX_wm_space_outliner(C);
        Scene *scene = CTX_data_scene(C);
        
        outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb);
        
+       DAG_id_type_tag(bmain, ID_OB);
        WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene);
        
        return OPERATOR_FINISHED;
@@ -579,11 +587,11 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
        te = outliner_find_id(so, &so->tree, (ID *)OBACT);
        if (te) {
                /* make te->ys center of view */
-               ytop = (int)(te->ys + (v2d->mask.ymax - v2d->mask.ymin) / 2);
+               ytop = (int)(te->ys + BLI_rcti_size_y(&v2d->mask) / 2);
                if (ytop > 0) ytop = 0;
                
                v2d->cur.ymax = (float)ytop;
-               v2d->cur.ymin = (float)(ytop - (v2d->mask.ymax - v2d->mask.ymin));
+               v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask));
                
                /* make te->xs ==> te->xend center of view */
                xdelta = (int)(te->xs - v2d->cur.xmin);
@@ -615,7 +623,7 @@ void OUTLINER_OT_show_active(wmOperatorType *ot)
 static int outliner_scroll_page_exec(bContext *C, wmOperator *op)
 {
        ARegion *ar = CTX_wm_region(C);
-       int dy = ar->v2d.mask.ymax - ar->v2d.mask.ymin;
+       int dy = BLI_rcti_size_y(&ar->v2d.mask);
        int up = 0;
        
        if (RNA_boolean_get(op->ptr, "up"))
@@ -726,7 +734,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
        
        /* determine which type of search to do */
        if (again && last_find) {
-               /* no popup panel - previous + user wanted to search for next after previous */         
+               /* no popup panel - previous + user wanted to search for next after previous */
                BLI_strncpy(name, soops->search_string, sizeof(name));
                flags = soops->search_flags;
                
@@ -742,7 +750,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
                /* pop up panel - no previous, or user didn't want search after previous */
                name[0] = '\0';
 // XXX         if (sbutton(name, 0, sizeof(name)-1, "Find: ") && name[0]) {
-//                     te= outliner_find_name(soops, &soops->tree, name, flags, NULL, &prevFound);
+//                     te = outliner_find_name(soops, &soops->tree, name, flags, NULL, &prevFound);
 //             }
 //             else return; /* XXX RETURN! XXX */
        }
@@ -760,10 +768,10 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
                        tselem->flag |= TSE_SELECTED;
                        
                        /* make te->ys center of view */
-                       ytop = (int)(te->ys + (ar->v2d.mask.ymax - ar->v2d.mask.ymin) / 2);
+                       ytop = (int)(te->ys + BLI_rctf_size_y(&ar->v2d.mask) / 2);
                        if (ytop > 0) ytop = 0;
                        ar->v2d.cur.ymax = (float)ytop;
-                       ar->v2d.cur.ymin = (float)(ytop - (ar->v2d.mask.ymax - ar->v2d.mask.ymin));
+                       ar->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(&ar->v2d.mask));
                        
                        /* make te->xs ==> te->xend center of view */
                        xdelta = (int)(te->xs - ar->v2d.cur.xmin);
@@ -782,7 +790,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
        }
        else {
                /* no tree-element found */
-               BKE_report(reports, RPT_WARNING, "Not found: %s", name);
+               BKE_reportf(reports, RPT_WARNING, "Not found: %s", name);
        }
 }
 #endif
@@ -832,6 +840,8 @@ static int outliner_one_level_exec(bContext *C, wmOperator *op)
 
 void OUTLINER_OT_show_one_level(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+
        /* identifiers */
        ot->name = "Show/Hide One Level";
        ot->idname = "OUTLINER_OT_show_one_level";
@@ -844,7 +854,8 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot)
        /* no undo or registry, UI option */
        
        /* properties */
-       RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep");
+       prop = RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep");
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
 /* Show Hierarchy ----------------------------------------------- */
@@ -883,9 +894,13 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase
                                else tselem->flag |= TSE_CLOSED;
                        }
                }
-               else tselem->flag |= TSE_CLOSED;
-               
-               if (TSELEM_OPEN(tselem, soops)) tree_element_show_hierarchy(scene, soops, &te->subtree);
+               else {
+                       tselem->flag |= TSE_CLOSED;
+               }
+
+               if (TSELEM_OPEN(tselem, soops)) {
+                       tree_element_show_hierarchy(scene, soops, &te->subtree);
+               }
        }
 }
 
@@ -994,7 +1009,7 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle
                                        char buf[128], *name;
                                        
                                        temnext = (TreeElement *)(ld->next->data);
-                                       /* tsenext= TREESTORE(temnext); */ /* UNUSED */
+                                       /* tsenext = TREESTORE(temnext); */ /* UNUSED */
                                        
                                        nextptr = &temnext->rnaptr;
                                        name = RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf), NULL);
@@ -1302,8 +1317,8 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
                                                 * for now, we don't supply one, and just let this use the KeyingSet name */
                                                BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode);
                                                ks->active_path = BLI_countlist(&ks->paths);
+                                               break;
                                        }
-                                       break;
                                        case KEYINGSET_EDITMODE_REMOVE:
                                        {
                                                /* find the relevant path, then remove it from the KeyingSet */
@@ -1315,8 +1330,8 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
 
                                                        ks->active_path = 0;
                                                }
+                                               break;
                                        }
-                                       break;
                                }
                                
                                /* free path, since it had to be generated */
@@ -1340,7 +1355,7 @@ static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
        
        /* check for invalid states */
        if (ks == NULL) {
-               BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Keying Set");
+               BKE_report(op->reports, RPT_ERROR, "Operation requires an active keying set");
                return OPERATOR_CANCELLED;
        }
        if (soutliner == NULL)
@@ -1423,10 +1438,9 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
        RNA_string_get(op->ptr, "child", childname);
        ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
 
-       ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE);
+       ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE);
 
-       DAG_scene_sort(bmain, scene);
-       DAG_ids_flush_update(bmain, 0);
+       DAG_relations_tag_update(bmain);
        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
        WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
 
@@ -1514,9 +1528,8 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
                }
 
                if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
-                       if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE)) {
-                               DAG_scene_sort(bmain, scene);
-                               DAG_ids_flush_update(bmain, 0);
+                       if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE)) {
+                               DAG_relations_tag_update(bmain);
                                WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
                                WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
                        }
@@ -1630,7 +1643,7 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
        ot->poll = ED_operator_outliner_active;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
 
        /* properties */
        RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
@@ -1699,8 +1712,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
 
        ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type"));
 
-       DAG_scene_sort(bmain, scene);
-       DAG_ids_flush_update(bmain, 0);
+       DAG_relations_tag_update(bmain);
        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
        WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
        return OPERATOR_FINISHED;
@@ -1719,7 +1731,7 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
        ot->poll = ED_operator_outliner_active;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
 
        /* properties */
        RNA_def_string(ot->srna, "dragged_obj", "Object", MAX_ID_NAME, "Child", "Child Object");
@@ -1788,8 +1800,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
                        ED_base_object_select(base, BA_SELECT);
                }
 
-               DAG_scene_sort(bmain, scene);
-               DAG_ids_flush_update(bmain, 0);
+               DAG_relations_tag_update(bmain);
 
                WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
 
@@ -1812,7 +1823,7 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot)
        ot->poll = ED_operator_outliner_active;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
 
        /* properties */
        RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
@@ -1821,7 +1832,6 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot)
 
 static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       Main *bmain = CTX_data_main(C);
        Material *ma = NULL;
        Object *ob = NULL;
        SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1853,9 +1863,8 @@ static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
                assign_material(ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
 
-               DAG_ids_flush_update(bmain, 0);
-               WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));         
-               WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, ma);
+               WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+               WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
 
                return OPERATOR_FINISHED;
        }
@@ -1876,7 +1885,7 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
        ot->poll = ED_operator_outliner_active;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
 
        /* properties */
        RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");