diff --git a/source/blender/editors/animation/keyframes_edit.cc b/source/blender/editors/animation/keyframes_edit.cc index 651954f691a..7d3436da95b 100644 --- a/source/blender/editors/animation/keyframes_edit.cc +++ b/source/blender/editors/animation/keyframes_edit.cc @@ -561,6 +561,18 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac) /* ------------------------ */ +static bool handles_visible(KeyframeEditData *ked, BezTriple *bezt) +{ + const bool handles_shown = (ked->iterflags & KEYFRAME_ITER_HANDLES_INVISIBLE) == 0; + if (!handles_shown) { + return false; + } + const bool handles_shown_only_selected = ked->iterflags & + KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE; + + return handles_shown_only_selected ? BEZT_ISSEL_ANY(bezt) : true; +} + static short keyframe_ok_checks( KeyframeEditData *ked, BezTriple *bezt, @@ -572,10 +584,7 @@ static short keyframe_ok_checks( } if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { /* Only act on visible items, so check handle visibility state. */ - const bool handles_visible = ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ? - BEZT_ISSEL_ANY(bezt) : - true); - if (handles_visible) { + if (handles_visible(ked, bezt)) { if (check(ked, bezt, 0)) { ok |= KEYFRAME_OK_H1; } @@ -1594,12 +1603,8 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode) static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt) { /* Only act on visible items, so check handle visibility state. */ - const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ? - BEZT_ISSEL_ANY(bezt) : - true); - /* if we've got info on what to select, use it, otherwise select all */ - if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES) && handles_visible) { + if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES) && handles_visible(ked, bezt)) { if (ked->curflags & KEYFRAME_OK_KEY) { bezt->f2 |= SELECT; } @@ -1620,12 +1625,8 @@ static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt) static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt) { /* Only act on visible items, so check handle visibility state. */ - const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ? - BEZT_ISSEL_ANY(bezt) : - true); - /* if we've got info on what to deselect, use it, otherwise deselect all */ - if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES) && handles_visible) { + if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES) && handles_visible(ked, bezt)) { if (ked->curflags & KEYFRAME_OK_KEY) { bezt->f2 &= ~SELECT; } diff --git a/source/blender/editors/include/ED_keyframes_edit.hh b/source/blender/editors/include/ED_keyframes_edit.hh index 1611a435620..c78ebde533b 100644 --- a/source/blender/editors/include/ED_keyframes_edit.hh +++ b/source/blender/editors/include/ED_keyframes_edit.hh @@ -137,7 +137,11 @@ enum eKeyframeVertOk { /* Flags for use during iteration */ enum eKeyframeIterFlags { - /* consider handles in addition to key itself */ + /* Consider handles in addition to key itself. Used in #keyframe_ok_checks, #select_bezier_add, + * #select_bezier_subtract. If set, treat key and handles separately (e.g (de)select them + * individually, and do additional visibility checks on the handles if necessary), otherwise + * always treat key and handles the same (e.g. (de)select all of them). + */ KEYFRAME_ITER_INCL_HANDLES = (1 << 0), /* Perform NLA time remapping (global -> strip) for the "f1" parameter @@ -152,7 +156,11 @@ enum eKeyframeIterFlags { * get the actual visibility state. E.g. in some cases handles are only drawn if either a handle * or their control point is selected. The selection state will have to be checked in the * iterator callbacks then. */ + /* Represents "Only Selected Keyframes" option (SIPO_SELVHANDLESONLY). */ KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE = (1 << 3), + + /* Represents "Show Handles" option (SIPO_NOHANDLES). */ + KEYFRAME_ITER_HANDLES_INVISIBLE = (1 << 4), }; ENUM_OPERATORS(eKeyframeIterFlags, KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) diff --git a/source/blender/editors/space_graph/graph_select.cc b/source/blender/editors/space_graph/graph_select.cc index 689ad305f57..037697128b5 100644 --- a/source/blender/editors/space_graph/graph_select.cc +++ b/source/blender/editors/space_graph/graph_select.cc @@ -560,12 +560,18 @@ static void initialize_box_select_key_editing_data(const bool incl_handles, r_ked->data = scaled_rectf; break; } - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - if (sipo->flag & SIPO_SELVHANDLESONLY) { + SpaceGraph *sgraph = (SpaceGraph *)ac->sl; + + if (sgraph->flag & SIPO_NOHANDLES) { + r_ked->iterflags |= KEYFRAME_ITER_HANDLES_INVISIBLE; + } + + if (sgraph->flag & SIPO_SELVHANDLESONLY) { r_ked->iterflags |= KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE; } - /* Enable handles selection. (used in keyframes_edit.cc > keyframe_ok_checks function) */ + /* Consider handles selection. Used in #keyframe_ok_checks, #select_bezier_add, + * #select_bezier_subtract. */ if (incl_handles) { r_ked->iterflags |= KEYFRAME_ITER_INCL_HANDLES; *r_mapping_flag = 0; @@ -580,7 +586,7 @@ static void initialize_box_select_key_editing_data(const bool incl_handles, /** * Box Select only selects keyframes, as overshooting handles often get caught too, * which means that they may be inadvertently moved as well. However, incl_handles overrides - * this, and allow handles to be considered independently too. + * this, and allow handles to be considered independently too (default since b037ba2665f4). * Also, for convenience, handles should get same status as keyframe (if it was within bounds). * * This function returns true if there was any change in the selection of a key (selecting or @@ -620,7 +626,7 @@ static bool box_select_graphkeys(bAnimContext *ac, * guess when a callback might use something different. */ ANIM_nla_mapping_apply_if_needed_fcurve( - ale, static_cast(ale->key_data), false, incl_handles == 0); + ale, static_cast(ale->key_data), false, (mapping_flag & ANIM_UNITCONV_ONLYKEYS)); scaled_rectf.xmin = rectf.xmin; scaled_rectf.xmax = rectf.xmax; @@ -657,7 +663,7 @@ static bool box_select_graphkeys(bAnimContext *ac, /* Un-apply NLA mapping from all the keyframes. */ ANIM_nla_mapping_apply_if_needed_fcurve( - ale, static_cast(ale->key_data), true, incl_handles == 0); + ale, static_cast(ale->key_data), true, (mapping_flag & ANIM_UNITCONV_ONLYKEYS)); } /* Cleanup. */ @@ -858,7 +864,7 @@ static wmOperatorStatus graphkeys_box_select_exec(bContext *C, wmOperator *op) } /* 'include_handles' from the operator specifies whether to include handles in the selection. */ - const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles"); + bool incl_handles = RNA_boolean_get(op->ptr, "include_handles"); /* Get settings from operator. */ WM_operator_properties_border_to_rcti(op, &rect); @@ -921,11 +927,13 @@ void GRAPH_OT_select_box(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, - "include_handles", - true, - "Include Handles", - "Are handles tested individually against the selection criteria"); + prop = RNA_def_boolean( + ot->srna, + "include_handles", + true, + "Include Handles", + "Are handles tested individually against the selection criteria, independently from their " + "keys. When unchecked, handles are (de)selected in unison with their keys"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean( @@ -975,9 +983,10 @@ static wmOperatorStatus graphkeys_lassoselect_exec(bContext *C, wmOperator *op) BLI_lasso_boundbox(&rect, data_lasso.mcoords); BLI_rctf_rcti_copy(&rect_fl, &rect); + /* 'include_handles' from the operator specifies whether to consider handles in the selection. */ + const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles"); + /* Apply box_select action. */ - SpaceGraph *sgraph = reinterpret_cast(ac.sl); - const bool incl_handles = (sgraph->flag & SIPO_NOHANDLES) == 0; const bool any_key_selection_changed = box_select_graphkeys( &ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); const bool use_curve_selection = RNA_boolean_get(op->ptr, "use_curve_selection"); @@ -1012,7 +1021,18 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot) /* Properties. */ WM_operator_properties_gesture_lasso(ot); WM_operator_properties_select_operation_simple(ot); - PropertyRNA *prop = RNA_def_boolean( + + PropertyRNA *prop; + prop = RNA_def_boolean( + ot->srna, + "include_handles", + true, + "Include Handles", + "Are handles tested individually against the selection criteria, independently from their " + "keys. When unchecked, handles are (de)selected in unison with their keys"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_boolean( ot->srna, "use_curve_selection", true, @@ -1057,9 +1077,10 @@ static wmOperatorStatus graph_circle_select_exec(bContext *C, wmOperator *op) rect_fl.ymin = y - radius; rect_fl.ymax = y + radius; + /* 'include_handles' from the operator specifies whether to consider handles in the selection. */ + const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles"); + /* Apply box_select action. */ - SpaceGraph *sgraph = reinterpret_cast(ac.sl); - const bool incl_handles = (sgraph->flag & SIPO_NOHANDLES) == 0; const bool any_key_selection_changed = box_select_graphkeys( &ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); if (any_key_selection_changed) { @@ -1098,7 +1119,18 @@ void GRAPH_OT_select_circle(wmOperatorType *ot) /* properties */ WM_operator_properties_gesture_circle(ot); WM_operator_properties_select_operation_simple(ot); - PropertyRNA *prop = RNA_def_boolean( + + PropertyRNA *prop; + prop = RNA_def_boolean( + ot->srna, + "include_handles", + true, + "Include Handles", + "Are handles tested individually against the selection criteria, independently from their " + "keys. When unchecked, handles are (de)selected in unison with their keys"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_boolean( ot->srna, "use_curve_selection", true,