diff options
Diffstat (limited to 'source/blender/editors/space_graph/graph_select.c')
-rw-r--r-- | source/blender/editors/space_graph/graph_select.c | 145 |
1 files changed, 116 insertions, 29 deletions
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 378139accbc..67274100312 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -198,7 +198,7 @@ void GRAPH_OT_select_all_toggle(wmOperatorType *ot) ot->poll = graphop_visible_keyframes_poll; /* flags */ - ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", ""); @@ -219,7 +219,7 @@ void GRAPH_OT_select_all_toggle(wmOperatorType *ot) */ static void borderselect_graphkeys( bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles, - struct KeyframeEdit_LassoData *data_lasso) + void *data) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; @@ -244,10 +244,16 @@ static void borderselect_graphkeys( /* init editing data */ memset(&ked, 0, sizeof(KeyframeEditData)); - if (data_lasso) { + if (mode == BEZT_OK_REGION_LASSO) { + struct KeyframeEdit_LassoData *data_lasso = data; data_lasso->rectf_scaled = &scaled_rectf; ked.data = data_lasso; } + else if (mode == BEZT_OK_REGION_CIRCLE) { + struct KeyframeEdit_CircleData *data_circle = data; + data_circle->rectf_scaled = &scaled_rectf; + ked.data = data; + } else { ked.data = &scaled_rectf; } @@ -266,7 +272,8 @@ static void borderselect_graphkeys( for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); FCurve *fcu = (FCurve *)ale->key_data; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); /* apply NLA mapping to all the keyframes, since it's easier than trying to * guess when a callback might use something different @@ -276,8 +283,8 @@ static void borderselect_graphkeys( scaled_rectf.xmin = rectf.xmin; scaled_rectf.xmax = rectf.xmax; - scaled_rectf.ymin = rectf.ymin / unit_scale; - scaled_rectf.ymax = rectf.ymax / unit_scale; + scaled_rectf.ymin = rectf.ymin / unit_scale - offset; + scaled_rectf.ymax = rectf.ymax / unit_scale - offset; /* set horizontal range (if applicable) * NOTE: these values are only used for x-range and y-range but not region @@ -390,7 +397,7 @@ void GRAPH_OT_select_border(wmOperatorType *ot) ot->poll = graphop_visible_keyframes_poll; /* flags */ - ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* rna */ WM_operator_properties_gesture_border(ot, true); @@ -485,6 +492,81 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first"); } +static int graph_circle_select_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode"); + short selectmode; + bool incl_handles; + rctf rect_fl; + struct KeyframeEdit_CircleData data; + float x = RNA_int_get(op->ptr, "x"); + float y = RNA_int_get(op->ptr, "y"); + float radius = RNA_int_get(op->ptr, "radius"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + data.mval[0] = x; + data.mval[1] = y; + data.radius_squared = radius * radius; + data.rectf_view = &rect_fl; + + if (gesture_mode == GESTURE_MODAL_SELECT) + selectmode = SELECT_ADD; + else + selectmode = SELECT_SUBTRACT; + + rect_fl.xmin = x - radius; + rect_fl.xmax = x + radius; + rect_fl.ymin = y - radius; + rect_fl.ymax = y + radius; + + if (ac.spacetype == SPACE_IPO) { + SpaceIpo *sipo = (SpaceIpo *)ac.sl; + if (selectmode == SELECT_ADD) { + incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || + (sipo->flag & SIPO_NOHANDLES)) == 0; + } + else { + incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0; + } + } + else { + incl_handles = false; + } + + /* apply borderselect action */ + borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); + + /* send notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_select_circle(wmOperatorType *ot) +{ + ot->name = "Circle Select"; + ot->description = "Select keyframe points using circle selection"; + ot->idname = "GRAPH_OT_select_circle"; + + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->exec = graph_circle_select_exec; + ot->poll = graphop_visible_keyframes_poll; + ot->cancel = WM_gesture_circle_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "radius", 1, 1, INT_MAX, "Radius", "", 1, INT_MAX); + RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); +} + /* ******************** Column Select Operator **************************** */ /* This operator works in one of four ways: * - 1) select all keyframes in the same frame as a selected one (KKEY) @@ -662,7 +744,7 @@ void GRAPH_OT_select_column(wmOperatorType *ot) ot->poll = graphop_visible_keyframes_poll; /* flags */ - ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", ""); @@ -720,7 +802,7 @@ void GRAPH_OT_select_linked(wmOperatorType *ot) ot->poll = graphop_visible_keyframes_poll; /* flags */ - ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Select More/Less Operators *********************** */ @@ -798,7 +880,7 @@ void GRAPH_OT_select_more(wmOperatorType *ot) ot->poll = graphop_visible_keyframes_poll; /* flags */ - ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ----------------- */ @@ -832,7 +914,7 @@ void GRAPH_OT_select_less(wmOperatorType *ot) ot->poll = graphop_visible_keyframes_poll; /* flags */ - ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Select Left/Right Operator ************************* */ @@ -1008,6 +1090,8 @@ typedef struct tNearestVertInfo { short hpoint; /* the handle index that we hit (eHandleIndex) */ short sel; /* whether the handle is selected or not */ int dist; /* distance from mouse to vert */ + + eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */ } tNearestVertInfo; /* Tags for the type of graph vert that we have */ @@ -1028,15 +1112,15 @@ typedef enum eGraphVertIndex { static bool fcurve_handle_sel_check(SpaceIpo *sipo, BezTriple *bezt) { if (sipo->flag & SIPO_NOHANDLES) return 0; - if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZSELECTED(bezt) == 0) return 0; + if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0) return 0; return 1; } /* check if the given vertex is within bounds or not */ // TODO: should we return if we hit something? static void nearest_fcurve_vert_store( - ListBase *matches, View2D *v2d, FCurve *fcu, - BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale) + ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype, + BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale, float offset) { /* Keyframes or Samples? */ if (bezt) { @@ -1048,7 +1132,7 @@ static void nearest_fcurve_vert_store( * 'vec' matrix */ if (UI_view2d_view_to_region_clip(v2d, - bezt->vec[hpoint + 1][0], bezt->vec[hpoint + 1][1] * unit_scale, + bezt->vec[hpoint + 1][0], (bezt->vec[hpoint + 1][1] + offset) * unit_scale, &screen_co[0], &screen_co[1]) && /* check if distance from mouse cursor to vert in screen space is within tolerance */ ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL)) @@ -1059,7 +1143,7 @@ static void nearest_fcurve_vert_store( /* if there is already a point for the F-Curve, check if this point is closer than that was */ if ((nvi) && (nvi->fcu == fcu)) { /* replace if we are closer, or if equal and that one wasn't selected but we are... */ - if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZSELECTED(bezt))) + if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt))) replace = 1; } /* add new if not replacing... */ @@ -1068,11 +1152,13 @@ static void nearest_fcurve_vert_store( /* store values */ nvi->fcu = fcu; + nvi->ctype = ctype; + nvi->bezt = bezt; nvi->hpoint = hpoint; nvi->dist = dist; - nvi->sel = BEZSELECTED(bezt); // XXX... should this use the individual verts instead? + nvi->sel = BEZT_ISSEL_ANY(bezt); // XXX... should this use the individual verts instead? /* add to list of matches if appropriate... */ if (replace == 0) @@ -1108,30 +1194,31 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L for (ale = anim_data.first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->key_data; AnimData *adt = ANIM_nla_mapping_get(ac, ale); - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); - + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); + /* apply NLA mapping to all the keyframes */ if (adt) ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); - + if (fcu->bezt) { BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL; int i; for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) { /* keyframe */ - nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale, offset); /* handles - only do them if they're visible */ if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) { /* first handle only visible if previous segment had handles */ if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { - nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale, offset); } /* second handle only visible if this segment is bezier */ if (bezt1->ipo == BEZT_IPO_BEZ) { - nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale, offset); } } } @@ -1251,11 +1338,11 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m if (select_mode == SELECT_INVERT) { /* keyframe - invert select of all */ if (nvi->hpoint == NEAREST_HANDLE_KEY) { - if (BEZSELECTED(bezt)) { - BEZ_DESEL(bezt); + if (BEZT_ISSEL_ANY(bezt)) { + BEZT_DESEL_ALL(bezt); } else { - BEZ_SEL(bezt); + BEZT_SEL_ALL(bezt); } } @@ -1272,7 +1359,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m else { /* if the keyframe was clicked on, select all verts of given beztriple */ if (nvi->hpoint == NEAREST_HANDLE_KEY) { - BEZ_SEL(bezt); + BEZT_SEL_ALL(bezt); } /* otherwise, select the handle that applied */ else if (nvi->hpoint == NEAREST_HANDLE_LEFT) @@ -1306,7 +1393,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m /* take selection status from item that got hit, to prevent flip/flop on channel * selection status when shift-selecting (i.e. "SELECT_INVERT") points */ - if (BEZSELECTED(bezt)) + if (BEZT_ISSEL_ANY(bezt)) nvi->fcu->flag |= FCURVE_SELECTED; else nvi->fcu->flag &= ~FCURVE_SELECTED; @@ -1324,7 +1411,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m /* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) otherwise the active flag won't be set [#26452] */ if (nvi->fcu->flag & FCURVE_SELECTED) { int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype); } /* free temp sample data for filtering */ |