diff options
author | Joshua Leung <aligorith@gmail.com> | 2011-04-01 16:21:41 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2011-04-01 16:21:41 +0400 |
commit | 2bd22ec559114ac4c2c55cffb207f4661f58e59c (patch) | |
tree | d35d247bb1da3e85079ea0af3188daea09c92fd8 | |
parent | 94ec34fb044a4f66da3cda7af9e98930e9cfc999 (diff) |
Animation Editors: Name-based filtering
I'm finally yielding to months of feature requesting, and adding
support for filtering F-Curves by name, where the "name" here is the
text which is displayed for each F-Curve in the Animation Editor
channel lists.
To use, just enable the magnifying-glass toggle on the DopeSheet
filtering settings, and enter a snippet of text to find within the
names of channels you wish to filter. This is case insensitive, and
currently doesn't support any wildcard/regrex fanciness.
Some examples:
loc <--- location curves only
x loc <--- x location curves only
x eul <--- x rotation curves only
rot <--- rotation curves only
etc.
-rw-r--r-- | release/scripts/startup/bl_ui/space_dopesheet.py | 82 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_filter.c | 45 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_action.c | 12 |
4 files changed, 100 insertions, 43 deletions
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 1ba9a628c1a..1de30ffdea8 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -33,48 +33,52 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): row.prop(dopesheet, "show_only_selected", text="") row.prop(dopesheet, "show_hidden", text="") - if genericFiltersOnly: - return - - row = layout.row(align=True) - row.prop(dopesheet, "show_transforms", text="") + if not genericFiltersOnly: + row = layout.row(align=True) + row.prop(dopesheet, "show_transforms", text="") - if is_nla: - row.prop(dopesheet, "show_missing_nla", text="") + if is_nla: + row.prop(dopesheet, "show_missing_nla", text="") - row = layout.row(align=True) - row.prop(dopesheet, "show_scenes", text="") - row.prop(dopesheet, "show_worlds", text="") - row.prop(dopesheet, "show_nodes", text="") - - if bpy.data.meshes: - row.prop(dopesheet, "show_meshes", text="") - if bpy.data.shape_keys: - row.prop(dopesheet, "show_shapekeys", text="") - if bpy.data.materials: - row.prop(dopesheet, "show_materials", text="") - if bpy.data.lamps: - row.prop(dopesheet, "show_lamps", text="") - if bpy.data.textures: - row.prop(dopesheet, "show_textures", text="") - if bpy.data.cameras: - row.prop(dopesheet, "show_cameras", text="") - if bpy.data.curves: - row.prop(dopesheet, "show_curves", text="") - if bpy.data.metaballs: - row.prop(dopesheet, "show_metaballs", text="") - if bpy.data.lattices: - row.prop(dopesheet, "show_lattices", text="") - if bpy.data.armatures: - row.prop(dopesheet, "show_armatures", text="") - if bpy.data.particles: - row.prop(dopesheet, "show_particles", text="") - - if bpy.data.groups: row = layout.row(align=True) - row.prop(dopesheet, "show_only_group_objects", text="") - if dopesheet.show_only_group_objects: - row.prop(dopesheet, "filter_group", text="") + row.prop(dopesheet, "show_scenes", text="") + row.prop(dopesheet, "show_worlds", text="") + row.prop(dopesheet, "show_nodes", text="") + + if bpy.data.meshes: + row.prop(dopesheet, "show_meshes", text="") + if bpy.data.shape_keys: + row.prop(dopesheet, "show_shapekeys", text="") + if bpy.data.materials: + row.prop(dopesheet, "show_materials", text="") + if bpy.data.lamps: + row.prop(dopesheet, "show_lamps", text="") + if bpy.data.textures: + row.prop(dopesheet, "show_textures", text="") + if bpy.data.cameras: + row.prop(dopesheet, "show_cameras", text="") + if bpy.data.curves: + row.prop(dopesheet, "show_curves", text="") + if bpy.data.metaballs: + row.prop(dopesheet, "show_metaballs", text="") + if bpy.data.lattices: + row.prop(dopesheet, "show_lattices", text="") + if bpy.data.armatures: + row.prop(dopesheet, "show_armatures", text="") + if bpy.data.particles: + row.prop(dopesheet, "show_particles", text="") + + if bpy.data.groups: + row = layout.row(align=True) + row.prop(dopesheet, "show_only_group_objects", text="") + if dopesheet.show_only_group_objects: + row.prop(dopesheet, "filter_group", text="") + + if not is_nla: + row = layout.row(align=True) + row.prop(dopesheet, "show_only_matching_fcurves", text="") + if dopesheet.show_only_matching_fcurves: + row.prop(dopesheet, "filter_fcurve_name", text="") ####################################### diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 89f3aa9d337..cca4fdbe331 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -804,7 +804,9 @@ static bAnimListElem *make_new_animlistelem (void *data, short datatype, void *o /* ----------------------------------------- */ -/* NOTE: when this function returns true, the F-Curve is to be skipped */ +/* 'Only Selected' selected data filtering + * NOTE: when this function returns true, the F-Curve is to be skipped + */ static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode) { if (GS(owner_id->name) == ID_OB) { @@ -876,6 +878,37 @@ static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id return 0; } +/* (Display-)Name-based F-Curve filtering + * NOTE: when this function returns true, the F-Curve is to be skipped + */ +static short skip_fcurve_with_name (bDopeSheet *ads, FCurve *fcu, ID *owner_id) +{ + bAnimListElem ale_dummy = {0}; + bAnimChannelType *acf; + + /* create a dummy wrapper for the F-Curve */ + ale_dummy.type = ANIMTYPE_FCURVE; + ale_dummy.id = owner_id; + ale_dummy.data = fcu; + + /* get type info for channel */ + acf = ANIM_channel_get_typeinfo(&ale_dummy); + if (acf && acf->name) { + char name[256]; /* hopefully this will be enough! */ + + /* get name */ + acf->name(&ale_dummy, name); + + /* check for partial match with the match string, assuming case insensitive filtering + * if match, this channel shouldn't be ignored! + */ + return BLI_strcasestr(name, ads->searchstr) == NULL; + } + + /* just let this go... */ + return 1; +} + /* find the next F-Curve that is usable for inclusion */ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id) { @@ -885,7 +918,7 @@ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bAct * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too... */ for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) { - /* special exception for Pose-Channel Based F-Curves: + /* special exception for Pose-Channel/Sequence-Strip/Node Based F-Curves: * - the 'Only Selected' data filter should be applied to Pose-Channel data too, but those are * represented as F-Curves. The way the filter for objects worked was to be the first check * after 'normal' visibility, so this is done first here too... @@ -897,7 +930,7 @@ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bAct if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode)) continue; } - + /* only include if visible (Graph Editor check, not channels check) */ if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) { /* only work with this channel and its subchannels if it is editable */ @@ -906,6 +939,12 @@ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bAct if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu)) ) { /* only include if this curve is active */ if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) { + /* name based filtering... */ + if ( ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id) ) { + if (skip_fcurve_with_name(ads, fcu, owner_id)) + continue; + } + /* this F-Curve can be used, so return it */ return fcu; } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 863d49a40b0..412b9bc56f6 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -511,7 +511,8 @@ typedef struct bDopeSheet { ID *source; /* currently ID_SCE (for Dopesheet), and ID_SC (for Grease Pencil) */ ListBase chanbase; /* cache for channels (only initialised when pinned) */ // XXX not used! - struct Group *filter_grp; /* object group for ADS_FILTER_ONLYOBGROUP filtering option */ + struct Group *filter_grp; /* object group for ADS_FILTER_ONLYOBGROUP filtering option */ + char searchstr[64]; /* string to search for in displayed names of F-Curves for ADS_FILTER_BY_FCU_NAME filtering option */ int filterflag; /* flags to use for filtering data */ int flag; /* standard flags */ @@ -554,6 +555,7 @@ typedef enum eDopeSheet_FilterFlag { /* general filtering 3 */ ADS_FILTER_INCL_HIDDEN = (1<<26), /* include 'hidden' channels too (i.e. those from hidden Objects/Bones) */ + ADS_FILTER_BY_FCU_NAME = (1<<27), /* for F-Curves, filter by the displayed name (i.e. to isolate all Location curves only) */ /* combination filters (some only used at runtime) */ ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM|ADS_FILTER_NOMAT|ADS_FILTER_NOLAM|ADS_FILTER_NOCUR|ADS_FILTER_NOPART|ADS_FILTER_NOARM) diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 43f5a0c3ab9..418451801ca 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -236,6 +236,18 @@ static void rna_def_dopesheet(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Filtering Group", "Group that included Object should be a member of"); RNA_def_property_update(prop, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); + /* FCurve Display Name Search Settings */ + prop= RNA_def_property(srna, "show_only_matching_fcurves", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_BY_FCU_NAME); + RNA_def_property_ui_text(prop, "Only Matching F-Curves", "Only include F-Curves with names containing search text"); + RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0); + RNA_def_property_update(prop, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); + + prop= RNA_def_property(srna, "filter_fcurve_name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "searchstr"); + RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string"); + RNA_def_property_update(prop, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); + /* NLA Specific Settings */ prop= RNA_def_property(srna, "show_missing_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NLA_NOACT); |