Animation: Graph Editor Handle Selection #111143
|
@ -221,6 +221,7 @@ class GRAPH_MT_select(Menu):
|
|||
layout.operator("graph.select_handles", text="Select Handles").mode = 'BOTH'
|
||||
layout.operator("graph.select_handles", text="Select Handles Left").mode = 'LEFT'
|
||||
layout.operator("graph.select_handles", text="Select Handles Right").mode = 'RIGHT'
|
||||
layout.operator("graph.select_handles", text="Select Keyframes").mode = 'KEY'
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.select_more")
|
||||
|
|
|
@ -80,10 +80,11 @@ enum eGraphKeys_LeftRightSelect_Mode {
|
|||
};
|
||||
|
||||
/* Defines for handle selection. */
|
||||
enum eGraphKey_HandleSelect_Mode {
|
||||
GRAPHKEYS_HANDLESEL_LR = 0,
|
||||
enum eGraphKey_HandleSelect_Side {
|
||||
GRAPHKEYS_HANDLESEL_BOTH = 0,
|
||||
GRAPHKEYS_HANDLESEL_L,
|
||||
GRAPHKEYS_HANDLESEL_R,
|
||||
GRAPHKEYS_HANDLESEL_KEY,
|
||||
};
|
||||
|
||||
/* defines for column-select mode */
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "BKE_fcurve.h"
|
||||
#include "BKE_nla.h"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_view2d.hh"
|
||||
|
||||
#include "ED_anim_api.hh"
|
||||
|
@ -2068,13 +2070,14 @@ void GRAPH_OT_clickselect(wmOperatorType *ot)
|
|||
|
||||
/* Defines for handle select tool. */
|
||||
static const EnumPropertyItem prop_graphkeys_leftright_handle_select_types[] = {
|
||||
{GRAPHKEYS_HANDLESEL_LR, "BOTH", 0, "Select Both Handles", ""},
|
||||
{GRAPHKEYS_HANDLESEL_BOTH, "BOTH", 0, "Select Both Handles", ""},
|
||||
{GRAPHKEYS_HANDLESEL_L, "LEFT", 0, "Select Left Handles", ""},
|
||||
{GRAPHKEYS_HANDLESEL_R, "RIGHT", 0, "Select Right Handles", ""},
|
||||
{GRAPHKEYS_HANDLESEL_KEY, "KEY", 0, "Select Keyframes", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static short bezt_sel_left_handles(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
|
||||
static short bezt_sel_left_handles(KeyframeEditData * /* ked */, BezTriple *bezt)
|
||||
{
|
||||
if (BEZT_ISSEL_ANY(bezt)) {
|
||||
BEZT_SEL_IDX(bezt, 0);
|
||||
|
@ -2083,7 +2086,7 @@ static short bezt_sel_left_handles(KeyframeEditData *UNUSED(ked), BezTriple *bez
|
|||
return 0;
|
||||
}
|
||||
|
||||
static short bezt_sel_right_handles(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
|
||||
static short bezt_sel_right_handles(KeyframeEditData * /* ked */, BezTriple *bezt)
|
||||
{
|
||||
if (BEZT_ISSEL_ANY(bezt)) {
|
||||
BEZT_DESEL_IDX(bezt, 0);
|
||||
|
@ -2092,7 +2095,7 @@ static short bezt_sel_right_handles(KeyframeEditData *UNUSED(ked), BezTriple *be
|
|||
return 0;
|
||||
}
|
||||
|
||||
static short bezt_sel_both_handles(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
|
||||
static short bezt_sel_both_handles(KeyframeEditData * /* ked */, BezTriple *bezt)
|
||||
{
|
||||
if (BEZT_ISSEL_ANY(bezt)) {
|
||||
BEZT_SEL_IDX(bezt, 0);
|
||||
|
@ -2101,7 +2104,17 @@ static short bezt_sel_both_handles(KeyframeEditData *UNUSED(ked), BezTriple *bez
|
|||
return 0;
|
||||
}
|
||||
|
||||
static short bezt_desel_keys(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
|
||||
static short bezt_sel_keys(KeyframeEditData * /* ked */, BezTriple *bezt)
|
||||
{
|
||||
if (BEZT_ISSEL_ANY(bezt)) {
|
||||
BEZT_DESEL_IDX(bezt, 0);
|
||||
BEZT_SEL_IDX(bezt, 1);
|
||||
BEZT_DESEL_IDX(bezt, 2);
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static short bezt_desel_keys(KeyframeEditData * /*ked */, BezTriple *bezt)
|
||||
{
|
||||
if (BEZT_ISSEL_ANY(bezt)) {
|
||||
BEZT_DESEL_IDX(bezt, 1);
|
||||
|
@ -2109,18 +2122,25 @@ static short bezt_desel_keys(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void graphkeys_de_select_handles(
|
||||
bAnimContext *ac,
|
||||
const short mode, // prop_graphkeys_leftright_handle_select_types
|
||||
const bool deselect_keyframe)
|
||||
/*
|
||||
* Select keyframe handles left/right/both or keys based on the given selection.
|
||||
*
|
||||
* mode: Determines which handles to select - left, right, or both.
|
||||
* deselect_keyframe: Specifies whether keyframes should be deselected (true) or if the current
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
Suggestion: "whether keyframes should" → "whether the keys themselves should". Suggestion: "whether keyframes should" → "whether the keys themselves should".
|
||||
* selection should be preserved (false).
|
||||
*/
|
||||
static void graph_keys_select_handles(bAnimContext *ac,
|
||||
const enum eGraphKey_HandleSelect_Side mode,
|
||||
const bool deselect_keyframe)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
|
||||
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
|
||||
ANIMFILTER_NODUPLIS);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
const eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE |
|
||||
ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
|
||||
ANIM_animdata_filter(
|
||||
ac, &anim_data, filter, ac->data, static_cast<eAnimCont_Types>(ac->datatype));
|
||||
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
|
||||
BLI_assert(ale->type & ANIMTYPE_FCURVE);
|
||||
FCurve *fcu = (FCurve *)ale->key_data;
|
||||
|
||||
/* Only continue if F-Curve has keyframes. */
|
||||
|
@ -2128,7 +2148,7 @@ static void graphkeys_de_select_handles(
|
|||
continue;
|
||||
}
|
||||
switch (mode) {
|
||||
case GRAPHKEYS_HANDLESEL_LR: {
|
||||
case GRAPHKEYS_HANDLESEL_BOTH: {
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
Remove the curly braces, they are only necessary when introducing new variables inside the Remove the curly braces, they are only necessary when introducing new variables inside the `case`.
|
||||
ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, bezt_sel_both_handles, NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -2140,8 +2160,11 @@ static void graphkeys_de_select_handles(
|
|||
ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, bezt_sel_left_handles, NULL);
|
||||
break;
|
||||
}
|
||||
case GRAPHKEYS_HANDLESEL_KEY: {
|
||||
ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, bezt_sel_keys, NULL);
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
Missing Missing `break`
|
||||
}
|
||||
}
|
||||
if (deselect_keyframe) {
|
||||
if (deselect_keyframe && (mode != GRAPHKEYS_HANDLESEL_KEY)) {
|
||||
ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, bezt_desel_keys, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -2159,10 +2182,11 @@ static int graphkeys_select_handles_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
short leftright = RNA_enum_get(op->ptr, "mode");
|
||||
bool deselect_keyframe = RNA_boolean_get(op->ptr, "deselect_keyframe");
|
||||
const eGraphKey_HandleSelect_Side leftright = static_cast<eGraphKey_HandleSelect_Side>(
|
||||
RNA_enum_get(op->ptr, "mode"));
|
||||
const bool deselect_keyframe = RNA_boolean_get(op->ptr, "deselect_keyframe");
|
||||
/* Perform selection changes. */
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
You don't need to explain what the function does at the call site of the function. If it needs explanation, choose a better function name. You don't need to explain what the function does at the call site of the function. If it needs explanation, choose a better function name.
|
||||
graphkeys_de_select_handles(&ac, leftright, deselect_keyframe);
|
||||
graph_keys_select_handles(&ac, leftright, deselect_keyframe);
|
||||
|
||||
/* Set notifier that keyframe selection has changed. */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
|
||||
|
@ -2170,25 +2194,46 @@ static int graphkeys_select_handles_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void graphkeys_select_handles_ui(bContext * /* C */, wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
uiLayout *row;
|
||||
|
||||
bool keyframe_selection = RNA_enum_get(op->ptr, "mode") == GRAPHKEYS_HANDLESEL_KEY;
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
`const`, and move this line down to where `keyframe_selection` is actually used.
|
||||
row = uiLayoutRow(layout, false);
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
Declare Declare `row` here, and not at the start of the function. The days of AncientC are over.
|
||||
uiItemR(row, op->ptr, "mode", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
|
||||
if (!keyframe_selection) {
|
||||
uiItemR(layout, op->ptr, "deselect_keyframe", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void GRAPH_OT_select_handles(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Select Handles";
|
||||
ot->idname = "GRAPH_OT_select_handles";
|
||||
ot->description = "(De)Select handles of based on the active selection";
|
||||
ot->description = "Select keyframe handles left/right/both or keys based on the given selection";
|
||||
|
||||
/* callbacks */
|
||||
ot->poll = graphop_visible_keyframes_poll;
|
||||
ot->exec = graphkeys_select_handles_exec;
|
||||
ot->ui = graphkeys_select_handles_ui;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
|
||||
|
||||
ot->prop = RNA_def_enum(ot->srna,
|
||||
"mode",
|
||||
prop_graphkeys_leftright_handle_select_types,
|
||||
GRAPHKEYS_HANDLESEL_LR,
|
||||
"Mode",
|
||||
"(De)Select handles based on selection");
|
||||
ot->prop = RNA_def_boolean(ot->srna, "deselect_keyframe", 1, "Deselect Keyframes", "");
|
||||
RNA_def_enum(
|
||||
ot->srna,
|
||||
"mode",
|
||||
prop_graphkeys_leftright_handle_select_types,
|
||||
GRAPHKEYS_HANDLESEL_BOTH,
|
||||
"Mode",
|
||||
"Selects corresponding keyframe handles (left, right, both or keys) based on the given "
|
||||
"selection");
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
"Selects ... based on the given selection" is not the clearest explanation. Suggestion:
"Selects ... based on the given selection" is not the clearest explanation. Suggestion:
> Of the selected keys & handles, change the selection to only the handles (left/right/both) or just the keys themselves.
Nathan Vegdahl
commented
Since the functionality has become a bit more flexible, I changed the description. Would love to have your eyes on it again. Since the functionality has become a bit more flexible, I changed the description. Would love to have your eyes on it again.
|
||||
RNA_def_boolean(ot->srna,
|
||||
"deselect_keyframe",
|
||||
1,
|
||||
"Deselect Keyframes",
|
||||
"Deselect keyframes or preserve the given keyframe selection");
|
||||
}
|
Personally I am not a fan of pointer incrementing. But I will leave this up to you
Ah, fair point. I basically just copy-pasted this from elsewhere. I agree that just using the index directly makes more sense here. Thanks for the catch!