Fix #87160: Clean Keyframes only works if channels are selected

The issue was that the code filtered for selected channels,
while the expectation was that it would only filter for selected keys.

This PR changes the behavior of the operator in the following way:
* when "Clean Channels" is **disabled**, it will clean only selected keyframes, regardless of the channel selection
* when "Clean Channels" is **enabled**, it will clean selected channels regardless of keyframe selection

The same logic was applied to the Graph Editor code.
It only makes a difference in the case when "Clean Channels" is enabled.
That is because channels were automatically selected when a key was selected.

In addition to that I moved the menu entry for "Clean Channels" to the channel menu
to reduce confusion.

Another solution would have been to make the Dope Sheet select channels
when keys are selected. This might still be done in the future, but I think the
only correct fix is to change the actual operator behavior.

Pull Request: https://projects.blender.org/blender/blender/pulls/113335
This commit is contained in:
Christoph Lendenfeld 2023-10-06 13:51:04 +02:00 committed by Christoph Lendenfeld
parent 8d15783a7e
commit d85e7f4577
5 changed files with 27 additions and 8 deletions

View File

@ -495,6 +495,7 @@ class DOPESHEET_MT_channel(Menu):
layout.operator_context = 'INVOKE_REGION_CHANNELS'
layout.operator("anim.channels_delete")
layout.operator("action.clean", text="Clean Channels").channels = True
layout.separator()
layout.operator("anim.channels_group")
@ -555,7 +556,6 @@ class DOPESHEET_MT_key(Menu):
layout.separator()
layout.operator("action.clean").channels = False
layout.operator("action.clean", text="Clean Channels").channels = True
layout.operator("action.bake_keys")
layout.separator()

View File

@ -91,7 +91,11 @@ bool duplicate_fcurve_keys(FCurve *fcu)
/** \name Various Tools
* \{ */
void clean_fcurve(bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
void clean_fcurve(bAnimContext *ac,
bAnimListElem *ale,
float thresh,
bool cleardefault,
const bool only_selected_keys)
{
FCurve *fcu = (FCurve *)ale->key_data;
BezTriple *old_bezts, *bezt, *beztn;
@ -144,7 +148,7 @@ void clean_fcurve(bAnimContext *ac, bAnimListElem *ale, float thresh, bool clear
cur[0] = bezt->vec[1][0];
cur[1] = bezt->vec[1][1];
if (!(bezt->f2 & SELECT)) {
if (only_selected_keys && !(bezt->f2 & SELECT)) {
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
lastb = (fcu->bezt + (fcu->totvert - 1));
lastb->f1 = lastb->f2 = lastb->f3 = 0;

View File

@ -427,7 +427,11 @@ struct FCurveSegment {
* The caller is responsible for freeing the memory.
*/
ListBase find_fcurve_segments(FCurve *fcu);
void clean_fcurve(bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault);
void clean_fcurve(bAnimContext *ac,
bAnimListElem *ale,
float thresh,
bool cleardefault,
bool only_selected_keys);
void blend_to_neighbor_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
void breakdown_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
void scale_average_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);

View File

@ -1182,12 +1182,18 @@ static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_SEL | ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
if (clean_chan) {
filter |= ANIMFILTER_SEL;
}
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, eAnimCont_Types(ac->datatype));
const bool only_selected_keys = !clean_chan;
/* loop through filtered data and clean curves */
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
clean_fcurve(ac, ale, thresh, clean_chan);
clean_fcurve(ac, ale, thresh, clean_chan, only_selected_keys);
ale->update |= ANIM_UPDATE_DEFAULT;
}

View File

@ -830,13 +830,18 @@ static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
if (clean_chan) {
filter |= ANIMFILTER_SEL;
}
ANIM_animdata_filter(
ac, &anim_data, eAnimFilter_Flags(filter), ac->data, eAnimCont_Types(ac->datatype));
const bool only_selected_keys = !clean_chan;
/* Loop through filtered data and clean curves. */
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
clean_fcurve(ac, ale, thresh, clean_chan);
clean_fcurve(ac, ale, thresh, clean_chan, only_selected_keys);
ale->update |= ANIM_UPDATE_DEFAULT;
}