diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 2644ad01092..2e882942d02 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -77,7 +77,9 @@ void transform_actionchannel_keys(int mode, int dummy); void transform_meshchannel_keys(char mode, struct Key *key); struct Key *get_action_mesh_key(void); int get_nearest_key_num(struct Key *key, short *mval, float *x); -void set_snap_actionchannels(void); +void snap_keys_to_frame(void); + +/* channel/strip operations */ void up_sel_action(void); void down_sel_action(void); void top_sel_action(void); diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index 2f98c047dc9..b60cd98b80c 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -135,7 +135,7 @@ void sampledata_to_ipocurve(float *data, int sfra, int efra, struct IpoCurve *ic void ipo_record(void); void sethandles_ipo_keys(struct Ipo *ipo, int code); -void snap_ipo_keys(struct Ipo *ipo); +void snap_ipo_keys(struct Ipo *ipo, short snaptype); void setipotype_ipo(struct Ipo *ipo, int code); void set_ipo_key_selection(struct Ipo *ipo, int sel); int is_ipo_key_selected(struct Ipo *ipo); diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 6858d2329bd..3561300f72f 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -1997,41 +1997,91 @@ void set_extendtype_actionchannels(int extendtype) allqueue(REDRAWNLA, 0); } -void set_snap_actionchannels(void) +static void set_snap_actionchannels(bAction *act, short snaptype) { - - bAction *act; + /* snapping function for action channels*/ bActionChannel *chan; bConstraintChannel *conchan; - /* Get the selected action, exit if none are selected - */ - act = G.saction->action; - if (!act) - return; - /* Loop through the channels */ for (chan = act->chanbase.first; chan; chan=chan->next){ if((chan->flag & ACHAN_HIDDEN)==0) { if (chan->ipo) { - snap_ipo_keys(chan->ipo); + snap_ipo_keys(chan->ipo, snaptype); } /* constraint channels */ for (conchan=chan->constraintChannels.first; conchan; conchan= conchan->next) { if (conchan->ipo) { - snap_ipo_keys(conchan->ipo); + snap_ipo_keys(conchan->ipo, snaptype); } } } } +} + +static void set_snap_meshchannels(Key *key, short snaptype) +{ + /* snapping function for mesh channels */ + if(key->ipo) { + snap_ipo_keys(key->ipo, snaptype); + } +} + + +void snap_keys_to_frame() +{ + /* This function is the generic entry-point for snapping keyframes + * to a frame(s). It passes the work off to sub-functions for the + * different types in the action editor. + */ + + SpaceAction *saction; + bAction *act; + Key *key; + short event; + + /* get data */ + saction= curarea->spacedata.first; + if (!saction) return; + act = saction->action; + key = get_action_mesh_key(); - /* Clean up and redraw stuff */ - remake_action_ipos (act); - BIF_undo_push("Snap Ipo Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); + /* find the type of snapping to do */ + event = pupmenu("Snap Frames To%t|Nearest Frame%x1|Current Frame%x2"); + + /* handle events */ + switch (event) { + case 1: /* snap to nearest frame */ + if (act) + set_snap_actionchannels(act, event); + else + set_snap_meshchannels(key, event); + + /* Clean up and redraw stuff */ + remake_action_ipos (act); + BIF_undo_push("Snap To Nearest Frame"); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); + + break; + case 2: /* snap to current frame */ + if (act) + set_snap_actionchannels(act, event); + else + set_snap_meshchannels(key, event); + + /* Clean up and redraw stuff */ + remake_action_ipos (act); + BIF_undo_push("Snap To Current Frame"); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); + + break; + } } @@ -2517,8 +2567,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case SKEY: if (mval[0]>=ACTWIDTH) { if(G.qual & LR_SHIFTKEY) { - if(okee("Snap to frame")) - set_snap_actionchannels(); + snap_keys_to_frame(); } else { if (key) diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index 39a05573145..581d293b079 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -555,16 +555,33 @@ void sethandles_ipo_keys(Ipo *ipo, int code) } } -static int snap_bezier(BezTriple *bezt) +static int snap_bezier_nearest(BezTriple *bezt) { if(bezt->f2 & SELECT) bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5)); return 0; } -void snap_ipo_keys(Ipo *ipo) +static int snap_bezier_cframe(BezTriple *bezt) { - ipo_keys_bezier_loop(ipo, snap_bezier, calchandles_ipocurve); + if(bezt->f2 & SELECT) + bezt->vec[1][0]= (float)CFRA; + return 0; +} + +void snap_ipo_keys(Ipo *ipo, short snaptype) +{ + switch (snaptype) { + case 1: /* snap to nearest */ + ipo_keys_bezier_loop(ipo, snap_bezier_nearest, calchandles_ipocurve); + break; + case 2: /* snap to current frame */ + ipo_keys_bezier_loop(ipo, snap_bezier_cframe, calchandles_ipocurve); + break; + default: /* just in case */ + ipo_keys_bezier_loop(ipo, snap_bezier_nearest, calchandles_ipocurve); + break; + } } static void ipo_curves_auto_horiz(void) diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index 2109d915cda..5ab3d4d3657 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -778,7 +778,7 @@ static void do_action_keymenu(void *arg, int event) bake_action_with_client (G.saction->action, OBACT, 0.01); break; case ACTMENU_KEY_SNAP: - set_snap_actionchannels(); + snap_keys_to_frame(); break; } }