== Action Editor - Snap Current-Frame Marker to Keys ==

This little feature snaps the current frame marker to the average frame of all the selected keyframes. Use the hotkey Ctrl-Shift-S to use it.
This commit is contained in:
Joshua Leung
2007-12-06 09:41:46 +00:00
parent df1db20737
commit ac6efff0d7
5 changed files with 112 additions and 6 deletions

View File

@@ -104,6 +104,7 @@ struct ListBase;
/* Key operations */ /* Key operations */
void transform_action_keys(int mode, int dummy); void transform_action_keys(int mode, int dummy);
void duplicate_action_keys(void); void duplicate_action_keys(void);
void snap_cfra_action(void);
void snap_action_keys(short mode); void snap_action_keys(short mode);
void mirror_action_keys(short mode); void mirror_action_keys(short mode);
void insertkey_action(void); void insertkey_action(void);

View File

@@ -151,6 +151,7 @@ void transform_ipo(int mode);
void actstrip_map_ipo_keys(struct Object *ob, struct Ipo *ipo, short restore, short only_keys); void actstrip_map_ipo_keys(struct Object *ob, struct Ipo *ipo, short restore, short only_keys);
void sethandles_ipo_keys(struct Ipo *ipo, int code); void sethandles_ipo_keys(struct Ipo *ipo, int code);
void snap_cfra_ipo_keys(struct Ipo *ipo, short mode);
void snap_ipo_keys(struct Ipo *ipo, short snaptype); void snap_ipo_keys(struct Ipo *ipo, short snaptype);
void mirror_ipo_keys(struct Ipo *ipo, short mirror_mode); void mirror_ipo_keys(struct Ipo *ipo, short mirror_mode);
void setipotype_ipo(struct Ipo *ipo, int code); void setipotype_ipo(struct Ipo *ipo, int code);

View File

@@ -779,6 +779,45 @@ void duplicate_action_keys (void)
transform_action_keys('g', 0); transform_action_keys('g', 0);
} }
/* this function is responsible for snapping the current frame to selected data */
void snap_cfra_action()
{
ListBase act_data = {NULL, NULL};
bActListElem *ale;
int filter;
void *data;
short datatype;
/* get data */
data= get_action_context(&datatype);
if (data == NULL) return;
/* filter data */
filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
actdata_filter(&act_data, filter, data, datatype);
/* snap current frame to selected data */
snap_cfra_ipo_keys(NULL, -1);
for (ale= act_data.first; ale; ale= ale->next) {
if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
snap_cfra_ipo_keys(ale->key_data, 0);
actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
}
else
snap_cfra_ipo_keys(ale->key_data, 0);
}
BLI_freelistN(&act_data);
snap_cfra_ipo_keys(NULL, 1);
BIF_undo_push("Snap Current Frame to Keys");
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWNLA, 0);
}
/* this function is responsible for snapping keyframes to frame-times */ /* this function is responsible for snapping keyframes to frame-times */
void snap_action_keys(short mode) void snap_action_keys(short mode)
{ {
@@ -2793,7 +2832,12 @@ 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|LR_CTRLKEY)) {
if (data) {
snap_cfra_action();
}
}
else if (G.qual & LR_SHIFTKEY) {
if (data) { if (data) {
if (G.saction->flag & SACTION_DRAWTIME) if (G.saction->flag & SACTION_DRAWTIME)
val = pupmenu("Snap Keys To%t|Nearest Second%x4|Current Time%x2|Nearest Marker %x3"); val = pupmenu("Snap Keys To%t|Nearest Second%x4|Current Time%x2|Nearest Marker %x3");

View File

@@ -723,6 +723,53 @@ void mirror_ipo_keys(Ipo *ipo, short mirror_type)
} }
} }
/* This function is called to calculate the average location of the
* selected keyframes, and place the current frame at that location.
*
* It must be called like so:
* snap_cfra_ipo_keys(NULL, -1); // initialise the static vars first
* for (ipo...) snap_cfra_ipo_keys(ipo, 0); // sum up keyframe times
* snap_cfra_ipo_keys(NULL, 1); // set current frame after taking average
*/
void snap_cfra_ipo_keys(Ipo *ipo, short mode)
{
static int cfra;
static int tot;
IpoCurve *icu;
BezTriple *bezt;
int a;
if (mode == -1) {
/* initialise a new snap-operation */
cfra= 0;
tot= 0;
}
else if (mode == 1) {
/* set current frame - using average frame */
if (tot != 0)
CFRA = cfra / tot;
}
else {
/* loop through keys in ipo, summing the frame
* numbers of those that are selected
*/
if (ipo == NULL)
return;
for (icu= ipo->curve.first; icu; icu= icu->next) {
for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
if (BEZSELECTED(bezt)) {
cfra += bezt->vec[1][0];
tot++;
}
}
}
}
}
/* currently only used by some action editor tools, but may soon get used by ipo editor */ /* currently only used by some action editor tools, but may soon get used by ipo editor */
/* restore = whether to map points back to ipo-time /* restore = whether to map points back to ipo-time
* only_keys = whether to only adjust the location of the center point of beztriples * only_keys = whether to only adjust the location of the center point of beztriples

View File

@@ -158,6 +158,7 @@ enum {
ACTMENU_KEY_SNAP_CURFRAME, ACTMENU_KEY_SNAP_CURFRAME,
ACTMENU_KEY_SNAP_NEARMARK, ACTMENU_KEY_SNAP_NEARMARK,
ACTMENU_KEY_SNAP_NEARTIME, ACTMENU_KEY_SNAP_NEARTIME,
ACTMENU_KEY_SNAP_CFRA2KEY,
}; };
enum { enum {
@@ -872,6 +873,10 @@ static void do_action_keymenu_snapmenu(void *arg, int event)
case ACTMENU_KEY_SNAP_NEARTIME: case ACTMENU_KEY_SNAP_NEARTIME:
snap_action_keys(event); snap_action_keys(event);
break; break;
case ACTMENU_KEY_SNAP_CFRA2KEY:
snap_cfra_action();
break;
} }
scrarea_queue_winredraw(curarea); scrarea_queue_winredraw(curarea);
@@ -888,27 +893,35 @@ static uiBlock *action_keymenu_snapmenu(void *arg_unused)
if (G.saction->flag & SACTION_DRAWTIME) { if (G.saction->flag & SACTION_DRAWTIME) {
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Nearest Second|Shift S, 1", 0, yco-=20, "Key -> Nearest Second|Shift S, 1", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0, menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_SNAP_NEARTIME, ""); ACTMENU_KEY_SNAP_NEARTIME, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Current Time|Shift S, 2", 0, yco-=20, "Key -> Current Time|Shift S, 2", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0, menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_SNAP_CURFRAME, ""); ACTMENU_KEY_SNAP_CURFRAME, "");
} }
else { else {
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Nearest Frame|Shift S, 1", 0, yco-=20, "Key -> Nearest Frame|Shift S, 1", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0, menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_SNAP_NEARFRAME, ""); ACTMENU_KEY_SNAP_NEARFRAME, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Current Frame|Shift S, 2", 0, yco-=20, "Key -> Current Frame|Shift S, 2", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0, menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_SNAP_CURFRAME, ""); ACTMENU_KEY_SNAP_CURFRAME, "");
} }
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Nearest Marker|Shift S, 3", 0, yco-=20, "Key -> Nearest Marker|Shift S, 3", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_SNAP_NEARMARK, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Current Frame -> Key|Ctrl Shift S", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0, menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_SNAP_NEARMARK, ""); ACTMENU_KEY_SNAP_NEARMARK, "");