diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2015-04-07 17:45:29 +0300 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2015-04-07 21:49:47 +0300 |
commit | c1e5d966c60876453dc7b66e0c23065088e8b94b (patch) | |
tree | bbb0de803794f6a39765c76f487bc9523b58a90a /source/blender/editors/transform/transform_conversions.c | |
parent | 662c2cd9105c43f2c21c511a68d45cef719ef9c9 (diff) |
Proportional editing support for the action editor.
There are a few things here which are not so nice:
* Position of proportional edit circle is not centered on data
(difficult to predict positions here since those are completely custom,
will probably be positioned at center of area later instead)
* Result is flushed to curve handles only at the end of the transform,
so if people have the graph editor open they will see handles lagging behind.
Diffstat (limited to 'source/blender/editors/transform/transform_conversions.c')
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 233 |
1 files changed, 185 insertions, 48 deletions
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 6124dab343f..23648c242f7 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3328,10 +3328,10 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act) /* ----------------------------- */ /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_fcurve_keys(FCurve *fcu, char side, float cfra) +static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit) { BezTriple *bezt; - int i, count = 0; + int i, count = 0, count_all = 0; if (ELEM(NULL, fcu, fcu->bezt)) return count; @@ -3341,20 +3341,22 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra) if (bezt->f2 & SELECT) { /* no need to adjust the handle selection since they are assumed * selected (like graph editor with SIPO_NOHANDLES) */ - if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { - count += 1; - } + if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) + count++; } + count_all++; } - return count; + if (propedit && count > 0) + return count_all; + else return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) +static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool propedit) { bGPDframe *gpf; - int count = 0; + int count = 0, count_all = 0; if (gpl == NULL) return count; @@ -3365,16 +3367,20 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) count++; } + count_all++; } - return count; + if (propedit && count > 0) + return count_all; + else + return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra) +static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool propedit) { MaskLayerShape *masklayer_shape; - int count = 0; + int count = 0, count_all = 0; if (masklay == NULL) return count; @@ -3385,9 +3391,13 @@ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra) if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) count++; } + count_all++; } - return count; + if (propedit && count > 0) + return count_all; + else + return count; } @@ -3398,6 +3408,8 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt) td->val = time; td->ival = *(time); + td->center[0] = td->ival; + /* store the AnimData where this keyframe exists as a keyframe of the * active action as td->extra. */ @@ -3411,7 +3423,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra) +static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool propedit) { BezTriple *bezt; TransData2D *td2d = *td2dv; @@ -3422,11 +3434,14 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { /* only add selected keyframes (for now, proportional edit is not enabled) */ - if (bezt->f2 & SELECT) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ + if (propedit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ /* only add if on the right 'side' of the current frame */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { TimeToTransData(td, bezt->vec[1], adt); + if (bezt->f2 & SELECT) + td->flag |= TD_SELECTED; + /*set flags to move handles as necessary*/ td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2; td2d->h1 = bezt->vec[0]; @@ -3477,19 +3492,21 @@ void flushTransIntFrameActionData(TransInfo *t) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra) +static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool propedit) { bGPDframe *gpf; int count = 0; /* check for select frames on right side of current frame */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (gpf->flag & GP_FRAME_SELECT) { + if (propedit || (gpf->flag & GP_FRAME_SELECT)) { if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; td->ival = (float)gpf->framenum; + td->center[0] = td->ival; + tfd->val = (float)gpf->framenum; tfd->sdata = &gpf->framenum; @@ -3505,19 +3522,21 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, } /* refer to comment above #GPLayerToTransData, this is the same but for masks */ -static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra) +static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool propedit) { MaskLayerShape *masklay_shape; int count = 0; /* check for select frames on right side of current frame */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { - if (masklay_shape->flag & MASK_SHAPE_SELECT) { + if (propedit || (masklay_shape->flag & MASK_SHAPE_SELECT)) { if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; td->ival = (float)masklay_shape->frame; + td->center[0] = td->ival; + tfd->val = (float)masklay_shape->frame; tfd->sdata = &masklay_shape->frame; @@ -3539,15 +3558,16 @@ static void createTransActionData(bContext *C, TransInfo *t) TransData *td = NULL; TransData2D *td2d = NULL; tGPFtransdata *tfd = NULL; - + bAnimContext ac; ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - + const bool propedit = (t->flag & T_PROP_EDIT) != 0; + int count = 0; float cfra; - + /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) return; @@ -3575,7 +3595,7 @@ static void createTransActionData(bContext *C, TransInfo *t) /* loop 1: fully select ipo-keys and count how many BezTriples are selected */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(&ac, ale); - + int adt_count = 0; /* convert current-frame to action-time (slightly less accurate, especially under * higher scaling ratios, but is faster than converting all points) */ @@ -3585,13 +3605,18 @@ static void createTransActionData(bContext *C, TransInfo *t) cfra = (float)CFRA; if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) - count += count_fcurve_keys(ale->key_data, t->frame_side, cfra); + adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, propedit); else if (ale->type == ANIMTYPE_GPLAYER) - count += count_gplayer_frames(ale->data, t->frame_side, cfra); + adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, propedit); else if (ale->type == ANIMTYPE_MASKLAYER) - count += count_masklayer_frames(ale->data, t->frame_side, cfra); + adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, propedit); else BLI_assert(0); + + if (adt_count > 0) { + count += adt_count; + ale->tag = true; + } } /* stop if trying to build list if nothing selected */ @@ -3628,11 +3653,22 @@ static void createTransActionData(bContext *C, TransInfo *t) /* loop 2: build transdata array */ for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt; + + if (propedit && !ale->tag) + continue; + + adt = ANIM_nla_mapping_get(&ac, ale); + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + else + cfra = (float)CFRA; + if (ale->type == ANIMTYPE_GPLAYER) { bGPDlayer *gpl = (bGPDlayer *)ale->data; int i; - i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra); + i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, propedit); td += i; tfd += i; } @@ -3640,7 +3676,7 @@ static void createTransActionData(bContext *C, TransInfo *t) MaskLayer *masklay = (MaskLayer *)ale->data; int i; - i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra); + i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, propedit); td += i; tfd += i; } @@ -3648,15 +3684,7 @@ static void createTransActionData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; - /* convert current-frame to action-time (slightly less accurate, especially under - * higher scaling ratios, but is faster than converting all points) - */ - if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); - else - cfra = (float)CFRA; - - td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra); + td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, propedit); } } @@ -3685,6 +3713,107 @@ static void createTransActionData(bContext *C, TransInfo *t) *((float *)(t->customData) + 1) = max; } + /* calculate distances for proportional editing */ + if (propedit) { + td = t->data; + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt; + + /* F-Curve may not have any keyframes */ + if (!ale->tag) + continue; + + adt = ANIM_nla_mapping_get(&ac, ale); + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + else + cfra = (float)CFRA; + + if (ale->type == ANIMTYPE_GPLAYER) { + bGPDlayer *gpl = (bGPDlayer *)ale->data; + bGPDframe *gpf; + + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + if (gpf->flag & GP_FRAME_SELECT) { + td->dist = td->rdist = 0.0f; + } + else { + bGPDframe *gpf_iter; + float min = FLT_MAX; + for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) { + if (gpf_iter->flag & GP_FRAME_SELECT) { + if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) { + float val = fabs(gpf->framenum - gpf_iter->framenum); + if (val < min) + min = val; + } + } + } + td->dist = td->rdist = min; + } + td++; + } + } + else if (ale->type == ANIMTYPE_MASKLAYER) { + MaskLayer *masklay = (MaskLayer *)ale->data; + MaskLayerShape *masklay_shape; + + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + if (FrameOnMouseSide(t->frame_side, (float)masklay_shape->frame, cfra)) { + if (masklay_shape->flag & MASK_SHAPE_SELECT) { + td->dist = td->rdist = 0.0f; + } + else { + MaskLayerShape *masklay_iter; + float min = FLT_MAX; + for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) { + if (masklay_iter->flag & MASK_SHAPE_SELECT) { + if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) { + float val = fabs(masklay_shape->frame - masklay_iter->frame); + if (val < min) + min = val; + } + } + } + td->dist = td->rdist = min; + } + td++; + } + } + } + else { + FCurve *fcu = (FCurve *)ale->key_data; + BezTriple *bezt; + int i; + + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { + if (bezt->f2 & SELECT) { + td->dist = td->rdist = 0.0f; + } + else { + BezTriple *bezt_iter; + int j; + float min = FLT_MAX; + for (j = 0, bezt_iter = fcu->bezt; j < fcu->totvert; j++, bezt_iter++) { + if (bezt_iter->f2 & SELECT) { + if (FrameOnMouseSide(t->frame_side, (float)bezt_iter->vec[1][0], cfra)) { + float val = fabs(bezt->vec[1][0] - bezt_iter->vec[1][0]); + if (val < min) + min = val; + } + } + } + td->dist = td->rdist = min; + } + td++; + } + } + } + } + } + /* cleanup temp list */ ANIM_animdata_freelist(&anim_data); } @@ -3787,7 +3916,7 @@ static bool graph_edit_use_local_center(TransInfo *t) } -static void graph_key_shortest_dist(FCurve *fcu, TransData *td_start, TransData *td, bool use_handle) +static void graph_key_shortest_dist(TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle) { int j = 0; TransData *td_iter = td_start; @@ -3795,15 +3924,17 @@ static void graph_key_shortest_dist(FCurve *fcu, TransData *td_start, TransData td->dist = FLT_MAX; for (; j < fcu->totvert; j++) { BezTriple *bezt = fcu->bezt + j; - const bool sel2 = (bezt->f2 & SELECT) != 0; - const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; - const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; + if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { + const bool sel2 = (bezt->f2 & SELECT) != 0; + const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; + const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; - if (sel1 || sel2 || sel3) { - td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); - } + if (sel1 || sel2 || sel3) { + td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); + } - td_iter += 3; + td_iter += 3; + } } } @@ -4091,7 +4222,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td->dist = td->rdist = 0.0f; } else { - graph_key_shortest_dist(fcu, td_start, td, use_handle); + graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); } td++; @@ -4099,7 +4230,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td->dist = td->rdist = 0.0f; } else { - graph_key_shortest_dist(fcu, td_start, td, use_handle); + graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); } td++; @@ -4107,7 +4238,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td->dist = td->rdist = 0.0f; } else { - graph_key_shortest_dist(fcu, td_start, td, use_handle); + graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); } td++; } @@ -7725,6 +7856,12 @@ void createTransData(bContext *C, TransInfo *t) else if (t->spacetype == SPACE_ACTION) { t->flag |= T_POINTS | T_2D_EDIT; createTransActionData(C, t); + + if (t->data && (t->flag & T_PROP_EDIT)) { + sort_trans_data(t); // makes selected become first in array + //set_prop_dist(t, false); /* don't do that, distance has been set in createTransActionData already */ + sort_trans_data_dist(t); + } } else if (t->spacetype == SPACE_NLA) { t->flag |= T_POINTS | T_2D_EDIT; @@ -7741,7 +7878,7 @@ void createTransData(bContext *C, TransInfo *t) if (t->data && (t->flag & T_PROP_EDIT)) { sort_trans_data(t); // makes selected become first in array - //set_prop_dist(t, false); /* don't do that, distance has been set in createTransGraphEditData already */ + set_prop_dist(t, false); /* don't do that, distance has been set in createTransGraphEditData already */ sort_trans_data_dist(t); } } |