Patch #5028. by Joshua Leung (aligorith)

Key snapping in Action Window, cleanup and added option to snap to
current frame.
This commit is contained in:
Ton Roosendaal 2006-11-07 18:34:32 +00:00
parent a221ddcf9b
commit 2e93510a6b
5 changed files with 94 additions and 26 deletions

@ -77,7 +77,9 @@ void transform_actionchannel_keys(int mode, int dummy);
void transform_meshchannel_keys(char mode, struct Key *key); void transform_meshchannel_keys(char mode, struct Key *key);
struct Key *get_action_mesh_key(void); struct Key *get_action_mesh_key(void);
int get_nearest_key_num(struct Key *key, short *mval, float *x); 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 up_sel_action(void);
void down_sel_action(void); void down_sel_action(void);
void top_sel_action(void); void top_sel_action(void);

@ -135,7 +135,7 @@ void sampledata_to_ipocurve(float *data, int sfra, int efra, struct IpoCurve *ic
void ipo_record(void); void ipo_record(void);
void sethandles_ipo_keys(struct Ipo *ipo, int code); 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 setipotype_ipo(struct Ipo *ipo, int code);
void set_ipo_key_selection(struct Ipo *ipo, int sel); void set_ipo_key_selection(struct Ipo *ipo, int sel);
int is_ipo_key_selected(struct Ipo *ipo); int is_ipo_key_selected(struct Ipo *ipo);

@ -1997,41 +1997,91 @@ void set_extendtype_actionchannels(int extendtype)
allqueue(REDRAWNLA, 0); allqueue(REDRAWNLA, 0);
} }
void set_snap_actionchannels(void) static void set_snap_actionchannels(bAction *act, short snaptype)
{ {
/* snapping function for action channels*/
bAction *act;
bActionChannel *chan; bActionChannel *chan;
bConstraintChannel *conchan; bConstraintChannel *conchan;
/* Get the selected action, exit if none are selected
*/
act = G.saction->action;
if (!act)
return;
/* Loop through the channels */ /* Loop through the channels */
for (chan = act->chanbase.first; chan; chan=chan->next){ for (chan = act->chanbase.first; chan; chan=chan->next){
if((chan->flag & ACHAN_HIDDEN)==0) { if((chan->flag & ACHAN_HIDDEN)==0) {
if (chan->ipo) { if (chan->ipo) {
snap_ipo_keys(chan->ipo); snap_ipo_keys(chan->ipo, snaptype);
} }
/* constraint channels */ /* constraint channels */
for (conchan=chan->constraintChannels.first; conchan; conchan= conchan->next) { for (conchan=chan->constraintChannels.first; conchan; conchan= conchan->next) {
if (conchan->ipo) { 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();
/* 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 */ /* Clean up and redraw stuff */
remake_action_ipos (act); remake_action_ipos (act);
BIF_undo_push("Snap Ipo Action channel"); BIF_undo_push("Snap To Nearest Frame");
allspace(REMAKEIPO, 0); allspace(REMAKEIPO, 0);
allqueue(REDRAWACTION, 0); allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0); allqueue(REDRAWIPO, 0);
allqueue(REDRAWNLA, 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: case SKEY:
if (mval[0]>=ACTWIDTH) { if (mval[0]>=ACTWIDTH) {
if(G.qual & LR_SHIFTKEY) { if(G.qual & LR_SHIFTKEY) {
if(okee("Snap to frame")) snap_keys_to_frame();
set_snap_actionchannels();
} }
else { else {
if (key) if (key)

@ -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) if(bezt->f2 & SELECT)
bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5)); bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
return 0; 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) static void ipo_curves_auto_horiz(void)

@ -778,7 +778,7 @@ static void do_action_keymenu(void *arg, int event)
bake_action_with_client (G.saction->action, OBACT, 0.01); bake_action_with_client (G.saction->action, OBACT, 0.01);
break; break;
case ACTMENU_KEY_SNAP: case ACTMENU_KEY_SNAP:
set_snap_actionchannels(); snap_keys_to_frame();
break; break;
} }
} }