diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2015-03-27 17:23:39 +0300 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2015-03-31 17:45:30 +0300 |
commit | 66a028a5761c44fa37963443c78bd7baf04ff551 (patch) | |
tree | 0431b7d81d6ac74fd3e44d637ef000a8c311f453 /source/blender | |
parent | 41f9cdc955d82bcf25abc86942f7bb9c98084db4 (diff) |
Proportional editing for IPO editor - version ready for feedback by artists.
This works by using the distance in the x axis only (usually artists want to influence nearby
keyframes based on timing, not value). Tweaking handles is the same as tweaking
the central handle. It's a bit ambiguous if proportional editing is really meaningful
for handles but will leave that for artists to decide.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 5 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_ops.c | 6 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 6 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_constraints.c | 15 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 228 |
5 files changed, 195 insertions, 65 deletions
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 8cf42dfce6c..7fd0d35d514 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -114,8 +114,9 @@ typedef struct bAnimListElem { int flag; /* copy of elem's flags for quick access */ int index; /* for un-named data, the index of the data in its collection */ - short update; /* (eAnim_Update_Flags) tag the element for updating */ - + char update; /* (eAnim_Update_Flags) tag the element for updating */ + char tag; /* tag the included data. Temporary always */ + short datatype; /* (eAnim_KeyType) type of motion data to expect */ void *key_data; /* motion data - mostly F-Curves, but can be other types too */ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index b52945297b9..33e8b522335 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -562,7 +562,6 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_easing_type", EKEY, KM_PRESS, KM_CTRL, 0); /* destructive */ - WM_keymap_add_item(keymap, "GRAPH_OT_clean", OKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0); @@ -608,6 +607,11 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_IPO); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", OKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.proportional_edit"); + RNA_string_set(kmi->ptr, "value_1", "DISABLED"); + RNA_string_set(kmi->ptr, "value_2", "ENABLED"); + /* pivot point settings */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 586c9d62589..c8d81383d79 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2089,6 +2089,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); } + else if (t->spacetype == SPACE_IPO) { + unit_m3(t->spacemtx); + t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + } else unit_m3(t->spacemtx); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index ccb81c7342b..bcd66f56c53 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -46,6 +46,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" +#include "BLI_rect.h" #include "BKE_context.h" @@ -757,12 +758,22 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy); } else if (t->options & CTX_PAINT_CURVE) { - aspx = aspy = 1.0; + aspx = aspy = 1.0f; } else { ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); } - glScalef(1.0f / aspx, 1.0f / aspy, 1.0); + glScalef(1.0f / aspx, 1.0f / aspy, 1.0f); + } + else if (t->spacetype == SPACE_IPO) { + /* only scale y */ + rcti *mask = &t->ar->v2d.mask; + rctf *datamask = &t->ar->v2d.cur; + float xsize = BLI_rctf_size_x(datamask); + float ysize = BLI_rctf_size_y(datamask); + float xmask = BLI_rcti_size_x(mask); + float ymask = BLI_rcti_size_y(mask); + glScalef(1.0f, (ysize / xsize) * (xmask / ymask), 1.0f); } depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index a74de31491a..e34439945ca 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3786,6 +3786,27 @@ static bool graph_edit_use_local_center(TransInfo *t) return (t->around == V3D_LOCAL) && !graph_edit_is_translation_mode(t); } + +static void graph_key_shortest_dist(FCurve *fcu, TransData *td_start, TransData *td, bool use_handle) +{ + int j = 0; + TransData *td_iter = td_start; + + 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 (sel1 || sel2 || sel3) { + td->dist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); + } + + td_iter += 3; + } +} + static void createTransGraphEditData(bContext *C, TransInfo *t) { SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; @@ -3808,6 +3829,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool is_translation_mode = graph_edit_is_translation_mode(t); const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); const bool use_local_center = graph_edit_use_local_center(t); + const bool propedit = (t->flag & T_PROP_EDIT) != 0; short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; /* determine what type of data we are operating on */ @@ -3839,6 +3861,8 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; float cfra; + int curvecount = 0; + bool selected = false; /* F-Curve may not have any keyframes */ if (fcu->bezt == NULL) @@ -3859,20 +3883,34 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; - if (!is_translation_mode || !(sel2)) { - if (sel1) { - count++; + if (propedit) { + curvecount += 3; + if (sel2 || sel1 || sel3) + selected = true; + } + else { + if (!is_translation_mode || !(sel2)) { + if (sel1) { + count++; + } + + if (sel3) { + count++; + } } - if (sel3) { + /* only include main vert if selected */ + if (sel2 && !use_local_center) { count++; } } + } + } - /* only include main vert if selected */ - if (sel2 && !use_local_center) { - count++; - } + if (propedit) { + if (selected) { + count += curvecount; + ale->tag = true; } } } @@ -3925,7 +3963,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) float cfra; /* F-Curve may not have any keyframes */ - if (fcu->bezt == NULL) + if (fcu->bezt == NULL || (propedit && ale->tag == 0)) continue; /* convert current-frame to action-time (slightly less accurate, especially under @@ -3948,66 +3986,135 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) TransDataCurveHandleFlags *hdata = NULL; /* short h1=1, h2=1; */ /* UNUSED */ - /* only include handles if selected, irrespective of the interpolation modes. - * also, only treat handles specially if the center point isn't selected. - */ - if (!is_translation_mode || !(sel2)) { - if (sel1) { - hdata = initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale); + if (propedit) { + bool is_sel = (sel2 || sel1 || sel3); + /* we always select all handles for proportional editing if central handle is selected */ + initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale); + initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale); + initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale); + } + else { + /* only include handles if selected, irrespective of the interpolation modes. + * also, only treat handles specially if the center point isn't selected. + */ + if (!is_translation_mode || !(sel2)) { + if (sel1) { + hdata = initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale); + } + else { + /* h1 = 0; */ /* UNUSED */ + } + + if (sel3) { + if (hdata == NULL) + hdata = initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale); + } + else { + /* h2 = 0; */ /* UNUSED */ + } } - else { - /* h1 = 0; */ /* UNUSED */ + + /* only include main vert if selected */ + if (sel2 && !use_local_center) { + /* move handles relative to center */ + if (is_translation_mode) { + if (sel1) td->flag |= TD_MOVEHANDLE1; + if (sel3) td->flag |= TD_MOVEHANDLE2; + } + + /* if handles were not selected, store their selection status */ + if (!(sel1) || !(sel3)) { + if (hdata == NULL) + hdata = initTransDataCurveHandles(td, bezt); + } + + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale); + } - - if (sel3) { - if (hdata == NULL) - hdata = initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale); + /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...): + * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, + * then check if we're using auto-handles. + * - If so, change them auto-handles to aligned handles so that handles get affected too + */ + if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && + ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && + ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) + { + if (hdata && (sel1) && (sel3)) { + bezt->h1 = HD_ALIGN; + bezt->h2 = HD_ALIGN; + } + } + } + } + } + + /* Sets handles based on the selection */ + testhandles_fcurve(fcu, use_handle); + } + + if (propedit) { + /* loop 2: build transdata arrays */ + td = t->data; + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(&ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + TransData *td_start = td; + float cfra; + + /* F-Curve may not have any keyframes */ + if (fcu->bezt == NULL || (ale->tag == 0)) + continue; + + /* 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; + + /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + 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) { + td->dist = 0.0f; } else { - /* h2 = 0; */ /* UNUSED */ + graph_key_shortest_dist(fcu, td_start, td, use_handle); } - } - - /* only include main vert if selected */ - if (sel2 && !use_local_center) { - /* move handles relative to center */ - if (is_translation_mode) { - if (sel1) td->flag |= TD_MOVEHANDLE1; - if (sel3) td->flag |= TD_MOVEHANDLE2; + td++; + + if (sel2) { + td->dist = 0.0f; } - - /* if handles were not selected, store their selection status */ - if (!(sel1) || !(sel3)) { - if (hdata == NULL) - hdata = initTransDataCurveHandles(td, bezt); + else { + graph_key_shortest_dist(fcu, td_start, td, use_handle); } - - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale); - - } - /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...): - * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, - * then check if we're using auto-handles. - * - If so, change them auto-handles to aligned handles so that handles get affected too - */ - if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && - ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && - ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) - { - if (hdata && (sel1) && (sel3)) { - bezt->h1 = HD_ALIGN; - bezt->h2 = HD_ALIGN; + td++; + + if (sel3 || sel2) { + td->dist = 0.0f; } + else { + graph_key_shortest_dist(fcu, td_start, td, use_handle); + } + td++; } } } - - /* Sets handles based on the selection */ - testhandles_fcurve(fcu, use_handle); } - + /* cleanup temp list */ ANIM_animdata_freelist(&anim_data); } @@ -7631,13 +7738,14 @@ void createTransData(bContext *C, TransInfo *t) else if (t->spacetype == SPACE_IPO) { t->flag |= T_POINTS | T_2D_EDIT; createTransGraphEditData(C, t); -#if 0 + if (t->data && (t->flag & T_PROP_EDIT)) { + t->flag |= T_PROP_CONNECTED; + t->flag &= ~T_PROP_PROJECTED; sort_trans_data(t); // makes selected become first in array - set_prop_dist(t, 1); + set_prop_dist(t, false); sort_trans_data_dist(t); } -#endif } else if (t->spacetype == SPACE_NODE) { t->flag |= T_POINTS | T_2D_EDIT; |