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 | |
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.
6 files changed, 211 insertions, 53 deletions
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index bb08a7c392e..843cf41b07c 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -105,6 +105,7 @@ class DOPESHEET_HT_header(Header): layout = self.layout st = context.space_data + toolsettings = context.tool_settings row = layout.row(align=True) row.template_header() @@ -133,6 +134,11 @@ class DOPESHEET_HT_header(Header): # filters which will work here and are useful (especially for character animation) dopesheet_filter(layout, context, genericFiltersOnly=True) + row = layout.row(align=True) + row.prop(toolsettings, "proportional_edit", icon_only=True) + if toolsettings.proportional_edit != 'DISABLED': + row.prop(toolsettings, "proportional_edit_falloff", icon_only=True) + # Grease Pencil mode doesn't need snapping, as it's frame-aligned only if st.mode != 'GPENCIL': layout.prop(st, "auto_snap", text="") diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 9ad0931a957..0f21446cc3d 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -202,7 +202,6 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0); /* destructive */ - WM_keymap_add_item(keymap, "ACTION_OT_clean", OKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ACTION_OT_delete", XKEY, KM_PRESS, 0, 0); @@ -241,6 +240,11 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_ACTION); + 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"); + /* special markers hotkeys for anim editors: see note in definition of this function */ ED_marker_keymap_animedit_conflictfree(keymap); } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 44063335dbe..17f1d6112b2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2095,6 +2095,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve //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 if (t->spacetype == SPACE_ACTION) { + 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); @@ -7518,6 +7524,7 @@ static void initTimeTranslate(TransInfo *t) static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN]) { char tvec[NUM_STR_REP_LEN * 3]; + int ofs = 0; /* if numeric input is active, use results from that, otherwise apply snapping to result */ if (hasNumInput(&t->num)) { @@ -7553,7 +7560,11 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN]) BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); } - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]); + ofs += BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]); + + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } } static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval)) @@ -7590,7 +7601,7 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval)) } val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); - val += deltax; + val += deltax * td->factor; *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); } else { diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index bcd66f56c53..03d626fe179 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -765,7 +765,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) } glScalef(1.0f / aspx, 1.0f / aspy, 1.0f); } - else if (t->spacetype == SPACE_IPO) { + else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) { /* only scale y */ rcti *mask = &t->ar->v2d.mask; rctf *datamask = &t->ar->v2d.cur; 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); } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 0571fc399a6..27a072c301b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1320,7 +1320,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* use settings from scene only if modal */ if (t->flag & T_MODAL) { if ((t->options & CTX_NO_PET) == 0) { - if (t->spacetype == SPACE_IPO) { + if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) { t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional); } else if (t->obedit) { |