From 67ea3180d902e762b6373fe2cbe2434aceb0f597 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 9 Sep 2011 12:46:07 +0000 Subject: Patch [#23443] Change outliner filter into search Shane Ambler (sambler) for this 12-month vintage! From description: One thing with the outliner filter box is it only filters items that are currently visible. To find what you want you need to manually expand a few levels so that what you want to find is visible. This small patch expands items when filtering is done - effectively turning it into a search. Currently this does not alter the datablocks view as expanding all entries takes waaaay tooooo long. I prevent the expansion of RNA entries for userprefs which prevents infinite recursion but the datablocks list is just too big for this approach. I think it would need a custom outliner_build_tree for a full search. --- .../blender/editors/space_outliner/outliner_draw.c | 46 ++++++++++++++-------- .../blender/editors/space_outliner/outliner_edit.c | 8 ++-- .../editors/space_outliner/outliner_intern.h | 21 ++++++++++ .../editors/space_outliner/outliner_select.c | 2 +- .../editors/space_outliner/outliner_tools.c | 10 ++--- .../blender/editors/space_outliner/outliner_tree.c | 38 +++++++++++++++--- source/blender/makesdna/DNA_outliner_types.h | 2 + source/blender/makesdna/DNA_space_types.h | 1 + 8 files changed, 95 insertions(+), 33 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 95a315272b9..e77bb979d47 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -97,7 +97,7 @@ static void outliner_height(SpaceOops *soops, ListBase *lb, int *h) TreeElement *te= lb->first; while(te) { TreeStoreElem *tselem= TREESTORE(te); - if((tselem->flag & TSE_CLOSED)==0) + if(TSELEM_OPEN(tselem,soops)) outliner_height(soops, &te->subtree, h); (*h) += UI_UNIT_Y; te= te->next; @@ -112,7 +112,7 @@ static void outliner_width(SpaceOops *soops, ListBase *lb, int *w) // TreeStoreElem *tselem= TREESTORE(te); // XXX fixme... te->xend is not set yet - if(tselem->flag & TSE_CLOSED) { + if(!TSELEM_OPEN(tselem,soops)) { if (te->xend > *w) *w = te->xend; } @@ -135,7 +135,7 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start if(startx+100 > *w) *w = startx+100; - if((tselem->flag & TSE_CLOSED)==0) + if(TSELEM_OPEN(tselem,soops)) outliner_rna_width(soops, &te->subtree, w, startx+UI_UNIT_X); te= te->next; } @@ -519,7 +519,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar } } - if((tselem->flag & TSE_CLOSED)==0) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree); + if(TSELEM_OPEN(tselem,soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree); } } @@ -560,7 +560,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa ptr= &te->rnaptr; prop= te->directdata; - if(!(RNA_property_type(prop) == PROP_POINTER && (tselem->flag & TSE_CLOSED)==0)) + if(!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem,soops))) ) uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y-1); } else if(tselem->type == TSE_RNA_ARRAY_ELEM) { @@ -571,7 +571,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa } } - if((tselem->flag & TSE_CLOSED)==0) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree); + if(TSELEM_OPEN(tselem,soops)) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree); } } @@ -828,7 +828,7 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo } } - if((tselem->flag & TSE_CLOSED)==0) outliner_draw_keymapbuts(block, ar, soops, &te->subtree); + if(TSELEM_OPEN(tselem,soops)) outliner_draw_keymapbuts(block, ar, soops, &te->subtree); } } @@ -871,7 +871,7 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa } } - if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(C, block, ar, soops, &te->subtree); + if(TSELEM_OPEN(tselem,soops)) outliner_buttons(C, block, ar, soops, &te->subtree); } } @@ -1237,6 +1237,18 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene glEnable(GL_BLEND); + /* start by highlighting search matches + * we don't expand items when searching in the datablocks but we + * still want to highlight any filter matches. + */ + if ( (SEARCHING_OUTLINER(soops) || (soops->outlinevis==SO_DATABLOCKS && soops->search_string[0]!=0)) && + (tselem->flag & TSE_SEARCHMATCH)) + { + /* TODO - add search highlight colour to theme? */ + glColor4f(0.2f, 0.5f, 0.2f, 0.3f); + glRecti(startx, *starty+1, ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1); + } + /* colors for active/selected data */ if(tselem->type==0) { if(te->idcode==ID_SCE) { @@ -1317,10 +1329,10 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene icon_x = startx+5*ufac; // icons a bit higher - if(tselem->flag & TSE_CLOSED) - UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT); - else + if(TSELEM_OPEN(tselem,soops)) UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_DOWN); + else + UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT); } offsx+= UI_UNIT_X; @@ -1356,7 +1368,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene offsx+= (int)(UI_UNIT_X + UI_GetStringWidth(te->name)); /* closed item, we draw the icons, not when it's a scene, or master-server list though */ - if(tselem->flag & TSE_CLOSED) { + if(!TSELEM_OPEN(tselem,soops)) { if(te->subtree.first) { if(tselem->type==0 && te->idcode==ID_SCE); else if(tselem->type!=TSE_R_LAYER) { /* this tree element always has same amount of branches, so dont draw */ @@ -1382,7 +1394,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene te->ys= (float)*starty; te->xend= startx+offsx; - if((tselem->flag & TSE_CLOSED)==0) { + if(TSELEM_OPEN(tselem,soops)) { *starty-= UI_UNIT_Y; for(ten= te->subtree.first; ten; ten= ten->next) @@ -1415,7 +1427,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, *starty-= UI_UNIT_Y; - if((tselem->flag & TSE_CLOSED)==0) + if(TSELEM_OPEN(tselem,soops)) outliner_draw_hierarchy(soops, &te->subtree, startx+UI_UNIT_X, starty); } @@ -1439,12 +1451,12 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase * tselem= TREESTORE(te); /* selection status */ - if((tselem->flag & TSE_CLOSED)==0) + if(TSELEM_OPEN(tselem,soops)) if(tselem->type == TSE_RNA_STRUCT) glRecti(0, *starty+1, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, *starty+UI_UNIT_Y-1); *starty-= UI_UNIT_Y; - if((tselem->flag & TSE_CLOSED)==0) { + if(TSELEM_OPEN(tselem,soops)) { outliner_draw_struct_marks(ar, soops, &te->subtree, starty); if(tselem->type == TSE_RNA_STRUCT) fdrawline(0, (float)*starty+UI_UNIT_Y, ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, (float)*starty+UI_UNIT_Y); @@ -1465,7 +1477,7 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1); } *starty-= UI_UNIT_Y; - if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(ar, soops, &te->subtree, starty); + if(TSELEM_OPEN(tselem,soops)) outliner_draw_selection(ar, soops, &te->subtree, starty); } } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 2b451a48748..05eace0d4ef 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -687,7 +687,7 @@ static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, te->ys= (float)(*starty); *starty-= UI_UNIT_Y; - if((tselem->flag & TSE_CLOSED)==0) { + if(TSELEM_OPEN(tselem,soops)) { TreeElement *ten; for(ten= te->subtree.first; ten; ten= ten->next) { outliner_set_coordinates_element(soops, ten, startx+UI_UNIT_X, starty); @@ -910,7 +910,7 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase } else tselem->flag |= TSE_CLOSED; - if(tselem->flag & TSE_CLOSED); else tree_element_show_hierarchy(scene, soops, &te->subtree); + if(TSELEM_OPEN(tselem,soops)) tree_element_show_hierarchy(scene, soops, &te->subtree); } } @@ -1175,7 +1175,7 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL } /* go over sub-tree */ - if ((tselem->flag & TSE_CLOSED)==0) + if (TSELEM_OPEN(tselem,soops)) do_outliner_drivers_editop(soops, &te->subtree, reports, mode); } } @@ -1343,7 +1343,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa } /* go over sub-tree */ - if ((tselem->flag & TSE_CLOSED)==0) + if (TSELEM_OPEN(tselem,soops)) do_outliner_keyingset_editop(soops, ks, &te->subtree, mode); } } diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 61507d1ffe5..215ab508ab6 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -126,6 +126,27 @@ typedef struct TreeElement { #define OL_RNA_COL_SPACEX (UI_UNIT_X*2.5f) +/* Outliner Searching -- + + Are we looking for something in the outliner? + If so finding matches in child items makes it more useful + + - We want to flag parents to act as being open to filter child matches + - and also flag matches so we can highlight them + - Flags are stored in TreeStoreElem->flag + - Flag options defined in DNA_outliner_types.h + - SO_SEARCH_RECURSIVE defined in DNA_space_types.h + + - NOT in datablocks view - searching all datablocks takes way too long + to be useful + - not searching into RNA items helps but isn't the complete solution + */ + +#define SEARCHING_OUTLINER(sov) (sov->search_flags & SO_SEARCH_RECURSIVE) + +/* is the currrent element open? if so we also show children */ +#define TSELEM_OPEN(telm,sv) ( (telm->flag & TSE_CLOSED)==0 || (SEARCHING_OUTLINER(sv) && (telm->flag & TSE_CHILDSEARCH)) ) + /* outliner_tree.c ----------------------------------------------- */ void outliner_free_tree(ListBase *lb); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 2c0a8c34747..a88625aad0d 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -134,7 +134,7 @@ static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *se change |= 1; } } - else if ((tselem->flag & TSE_CLOSED)==0) { + else if (TSELEM_OPEN(tselem,soops)) { /* Only try selecting sub-elements if we haven't hit the right element yet * * Hack warning: diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index b3170f9cd1e..b2fdd34aab2 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -145,7 +145,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb, } } } - if((tselem->flag & TSE_CLOSED)==0) { + if(TSELEM_OPEN(tselem,soops)) { set_operation_types(soops, &te->subtree, scenelevel, objectlevel, idlevel, datalevel); } @@ -250,7 +250,7 @@ static void outliner_do_libdata_operation(bContext *C, Scene *scene, SpaceOops * operation_cb(C, scene, te, tsep, tselem); } } - if((tselem->flag & TSE_CLOSED)==0) { + if(TSELEM_OPEN(tselem,soops)) { outliner_do_libdata_operation(C, scene, soops, &te->subtree, operation_cb); } } @@ -397,7 +397,7 @@ void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soop operation_cb(C, scene_owner ? scene_owner : scene_act, te, NULL, tselem); } } - if((tselem->flag & TSE_CLOSED)==0) { + if(TSELEM_OPEN(tselem,soops)) { outliner_do_object_operation(C, scene_act, soops, &te->subtree, operation_cb); } } @@ -504,7 +504,7 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li operation_cb(event, te, tselem); } } - if((tselem->flag & TSE_CLOSED)==0) { + if(TSELEM_OPEN(tselem,soops)) { outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb); } } @@ -857,7 +857,7 @@ static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *l operation_cb(te, tselem, tsep, newid); } } - if ((tselem->flag & TSE_CLOSED)==0) { + if (TSELEM_OPEN(tselem,soops)) { outliner_do_id_set_operation(soops, type, &te->subtree, newid, operation_cb); } } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 8904dcc360f..7e9eabc08db 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -827,6 +827,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i check_persistant(soops, te, id, type, index); tselem= TREESTORE(te); + /* if we are searching for something expand to see child elements */ + if(SEARCHING_OUTLINER(soops)) + tselem->flag |= TSE_CHILDSEARCH; + te->parent= parent; te->index= index; // for data arays if(ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)); @@ -981,6 +985,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i else te->name= (char*)RNA_struct_ui_name(ptr->type); + /* If searching don't expand RNA entries */ + if(SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA",te->name)==0) tselem->flag &= ~TSE_CHILDSEARCH; + iterprop= RNA_struct_iterator_property(ptr->type); tot= RNA_property_collection_length(ptr, iterprop); @@ -989,7 +996,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i if(!tselem->used) tselem->flag &= ~TSE_CLOSED; - if(!(tselem->flag & TSE_CLOSED)) { + if(TSELEM_OPEN(tselem,soops)) { for(a=0; asubtree, (void*)ptr, te, TSE_RNA_PROPERTY, a); } @@ -1010,11 +1017,14 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->directdata= prop; te->rnaptr= *ptr; + /* If searching don't expand RNA entries */ + if(SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA",te->name)==0) tselem->flag &= ~TSE_CHILDSEARCH; + if(proptype == PROP_POINTER) { pptr= RNA_property_pointer_get(ptr, prop); if(pptr.data) { - if(!(tselem->flag & TSE_CLOSED)) + if(TSELEM_OPEN(tselem,soops)) outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, -1); else te->flag |= TE_LAZY_CLOSED; @@ -1023,7 +1033,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i else if(proptype == PROP_COLLECTION) { tot= RNA_property_collection_length(ptr, prop); - if(!(tselem->flag & TSE_CLOSED)) { + if(TSELEM_OPEN(tselem,soops)) { for(a=0; asubtree, (void*)&pptr, te, TSE_RNA_STRUCT, a); @@ -1035,7 +1045,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i else if(ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { tot= RNA_property_array_length(ptr, prop); - if(!(tselem->flag & TSE_CLOSED)) { + if(TSELEM_OPEN(tselem,soops)) { for(a=0; asubtree, (void*)ptr, te, TSE_RNA_ARRAY_ELEM, a); } @@ -1068,7 +1078,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->directdata= idv; te->name= km->idname; - if(!(tselem->flag & TSE_CLOSED)) { + if(TSELEM_OPEN(tselem,soops)) { a= 0; for (kmi= km->items.first; kmi; kmi= kmi->next, a++) { @@ -1368,7 +1378,10 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb) */ tselem= TREESTORE(te); - if ((tselem->flag & TSE_CLOSED) || outliner_filter_tree(soops, &te->subtree)==0) { + /* flag as not a found item */ + tselem->flag &= ~TSE_SEARCHMATCH; + + if ((!TSELEM_OPEN(tselem,soops)) || outliner_filter_tree(soops, &te->subtree)==0) { outliner_free_tree(&te->subtree); BLI_remlink(lb, te); @@ -1377,6 +1390,11 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb) } } else { + tselem= TREESTORE(te); + + /* flag as a found item - we can then highlight it */ + tselem->flag |= TSE_SEARCHMATCH; + /* filter subtree too */ outliner_filter_tree(soops, &te->subtree); } @@ -1399,6 +1417,14 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) TreeStoreElem *tselem; int show_opened= (soops->treestore==NULL); /* on first view, we open scenes */ + /* Are we looking for something - we want to tag parents to filter child matches + - NOT in datablocks view - searching all datablocks takes way too long to be useful + - this variable is only set once per tree build */ + if(soops->search_string[0]!=0 && soops->outlinevis!=SO_DATABLOCKS) + soops->search_flags |= SO_SEARCH_RECURSIVE; + else + soops->search_flags &= ~SO_SEARCH_RECURSIVE; + if(soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW)) return; diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h index c44f10efde8..af19aa490ae 100644 --- a/source/blender/makesdna/DNA_outliner_types.h +++ b/source/blender/makesdna/DNA_outliner_types.h @@ -51,6 +51,8 @@ typedef struct TreeStore { #define TSE_CLOSED 1 #define TSE_SELECTED 2 #define TSE_TEXTBUT 4 +#define TSE_CHILDSEARCH 8 +#define TSE_SEARCHMATCH 16 /* TreeStoreElem types in BIF_outliner.h */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 66b10bcbf21..1627d4d2acb 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -861,6 +861,7 @@ enum { /* outliner search flags (SpaceOops->search_flags) */ #define SO_FIND_CASE_SENSITIVE (1<<0) #define SO_FIND_COMPLETE (1<<1) +#define SO_SEARCH_RECURSIVE (1<<2) /* headerbuttons: 450-499 */ -- cgit v1.2.3