diff options
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 15 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_filter.c | 77 |
2 files changed, 74 insertions, 18 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 97c93c6a913..bdaf0bf700a 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -939,7 +939,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *op) /* do groups only first (unless in Drivers mode, where there are none) */ if (ac.datatype != ANIMCONT_DRIVERS) { /* filter data */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CHANNELS | ANIMFILTER_FOREDIT); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CHANNELS | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* delete selected groups and their associated channels */ @@ -978,7 +978,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *op) /* now do F-Curves */ if (ac.datatype != ANIMCONT_GPENCIL) { /* filter data */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* delete selected F-Curves */ @@ -1038,7 +1038,7 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *op) ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype); /* hide all channels not selected */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_UNSEL); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); for (ale= anim_data.first; ale; ale= ale->next) { @@ -1054,7 +1054,7 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* make all the selected channels visible */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); for (ale= anim_data.first; ale; ale= ale->next) { @@ -1113,11 +1113,11 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* get list of all channels that selection may need to be flushed to */ - filter= ANIMFILTER_CHANNELS; + filter= (ANIMFILTER_CHANNELS | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype); /* filter data */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* See if we should be making showing all selected or hiding */ @@ -1215,7 +1215,8 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode, } /* filter data that we're working on */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); + // XXX: noduplis enabled so that results don't cancel, but will be problematic for some channels where only type differs + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS | ANIMFILTER_NODUPLIS); if (onlysel) filter |= ANIMFILTER_SEL; ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 5ac7f6d4119..67f2cb834e0 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -68,6 +68,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -2512,6 +2513,65 @@ static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim return 1; } +/* ----------- Cleanup API --------------- */ + +/* Remove entries with invalid types in animation channel list */ +static int animdata_filter_remove_invalid (ListBase *anim_data) +{ + bAnimListElem *ale, *next; + int items = 0; + + /* only keep entries with valid types */ + for (ale= anim_data->first; ale; ale= next) { + next= ale->next; + + if (ale->type == ANIMTYPE_NONE) + BLI_freelinkN(anim_data, ale); + else + items++; + } + + return items; +} + +/* Remove duplicate entries in animation channel list */ +static int animdata_filter_remove_duplis (ListBase *anim_data) +{ + bAnimListElem *ale, *next; + GHash *gh; + int items = 0; + + /* build new hashtable to efficiently store and retrieve which entries have been + * encountered already while searching + */ + gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "animdata_filter_duplis_remove gh"); + + /* loop through items, removing them from the list if a similar item occurs already */ + for (ale = anim_data->first; ale; ale = next) { + next = ale->next; + + /* check if hash has any record of an entry like this + * - just use ale->data for now, though it would be nicer to involve + * ale->type in combination too to capture corner cases (where same data performs differently) + */ + if (BLI_ghash_haskey(gh, ale->data) == 0) { + /* this entry is 'unique' and can be kept */ + BLI_ghash_insert(gh, ale->data, NULL); + items++; + } + else { + /* this entry isn't needed anymore */ + BLI_freelinkN(anim_data, ale); + } + } + + /* free the hash... */ + BLI_ghash_free(gh, NULL, NULL); + + /* return the number of items still in the list */ + return items; +} + /* ----------- Public API --------------- */ /* This function filters the active data source to leave only animation channels suitable for @@ -2527,7 +2587,6 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode /* only filter data if there's somewhere to put it */ if (data && anim_data) { - bAnimListElem *ale, *next; Object *obact= (ac) ? ac->obact : NULL; /* firstly filter the data */ @@ -2572,16 +2631,12 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode break; } - /* remove any weedy entries */ - // XXX this is weedy code! - for (ale= anim_data->first; ale; ale= next) { - next= ale->next; - - if (ale->type == ANIMTYPE_NONE) { - items--; - BLI_freelinkN(anim_data, ale); - } - } + /* remove any 'weedy' entries */ + items = animdata_filter_remove_invalid(anim_data); + + /* remove duplicates (if required) */ + if (filter_mode & ANIMFILTER_NODUPLIS) + items = animdata_filter_remove_duplis(anim_data); } /* return the number of items in the list */ |