== Action Editor ==

Now it is possible to mirror selected keyframes in the action editor;
either over the current frame or the vertical axis.

Hotkey is: SHIFT M       (like in ipo editor).
This commit is contained in:
Joshua Leung
2006-12-02 06:00:31 +00:00
parent 28bbf2d616
commit ac43fe5afd
5 changed files with 202 additions and 48 deletions

View File

@@ -80,9 +80,11 @@ 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 snap_keys_to_frame(int snap_mode);
void mirror_action_keys(short mirror_mode);
void clean_shapekeys(struct Key *key);
void clean_actionchannels(struct bAction *act);
/* Marker Operations */
void get_minmax_saction_markers(float *first, float *last);
void selectkeys_columns_markers(void);

View File

@@ -140,6 +140,7 @@ void ipo_record(void);
void sethandles_ipo_keys(struct Ipo *ipo, int code);
void snap_ipo_keys(struct Ipo *ipo, short snaptype);
void mirror_ipo_keys(struct Ipo *ipo, short mirror_mode);
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);

View File

@@ -2083,48 +2083,113 @@ void snap_keys_to_frame(int snap_mode)
SpaceAction *saction;
bAction *act;
Key *key;
char str[32];
/* get data */
saction= curarea->spacedata.first;
if (!saction) return;
act = saction->action;
key = get_action_mesh_key();
/* handle events */
/* determine mode */
switch (snap_mode) {
case 1: /* snap to nearest frame */
if (act)
set_snap_actionchannels(act, snap_mode);
else
set_snap_meshchannels(key, snap_mode);
/* 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);
case 1:
strcpy(str, "Snap Keys To Nearest Frame");
break;
case 2: /* snap to current frame */
if (act)
set_snap_actionchannels(act, snap_mode);
else
set_snap_meshchannels(key, snap_mode);
/* 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);
case 2:
strcpy(str, "Snap Keys To Current Frame");
break;
default:
return;
}
/* snap to frame */
if (key)
set_snap_meshchannels(key, snap_mode);
else
set_snap_actionchannels(act, snap_mode);
remake_action_ipos (act);
BIF_undo_push(str);
allspace(REMAKEIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWNLA, 0);
}
static void mirror_actionchannels(bAction *act, short mirror_mode)
{
/* mirror function for action channels */
bActionChannel *chan;
bConstraintChannel *conchan;
/* Loop through the channels */
for (chan = act->chanbase.first; chan; chan=chan->next){
if((chan->flag & ACHAN_HIDDEN)==0) {
if (chan->ipo) {
mirror_ipo_keys(chan->ipo, mirror_mode);
}
/* constraint channels */
for (conchan=chan->constraintChannels.first; conchan; conchan= conchan->next) {
if (conchan->ipo) {
mirror_ipo_keys(conchan->ipo, mirror_mode);
}
}
}
}
}
static void mirror_meshchannels(Key *key, short mirror_mode)
{
/* mirror function for mesh channels */
if(key->ipo) {
mirror_ipo_keys(key->ipo, mirror_mode);
}
}
void mirror_action_keys(short mirror_mode)
{
/* This function is the generic entry-point for mirroring keyframes
* to over a frame. It passes the work off to sub-functions for the
* different types in the action editor.
*/
SpaceAction *saction;
bAction *act;
Key *key;
char str[32];
/* get data */
saction= curarea->spacedata.first;
if (!saction) return;
act = saction->action;
key = get_action_mesh_key();
/* determine mode */
switch (mirror_mode) {
case 1:
strcpy(str, "Mirror Keys Over Current Frame");
break;
case 2:
strcpy(str, "Mirror Keys Over Y-Axis");
break;
default:
return;
}
/* mirror */
if (key)
mirror_meshchannels(key, mirror_mode);
else
mirror_actionchannels(act, mirror_mode);
remake_action_ipos (act);
BIF_undo_push(str);
allspace(REMAKEIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWNLA, 0);
}
static void select_all_keys_frames(bAction *act, short *mval,
short *mvalo, int selectmode) {
@@ -2627,18 +2692,25 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case MKEY:
/* marker operations */
if (G.qual == 0)
add_marker(CFRA);
else if (G.qual == LR_CTRLKEY)
rename_marker();
else
break;
allqueue(REDRAWTIME, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue(REDRAWSOUND, 0);
if (G.qual & LR_SHIFTKEY) {
/* mirror keyframes */
val = pupmenu("Mirror Keys Over%t|Current Frame%x1|Vertical Axis%x2");
mirror_action_keys(val);
}
else {
/* marker operations */
if (G.qual == 0)
add_marker(CFRA);
else if (G.qual == LR_CTRLKEY)
rename_marker();
else
break;
allqueue(REDRAWTIME, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue(REDRAWSOUND, 0);
}
break;
case NKEY:

View File

@@ -585,6 +585,45 @@ void snap_ipo_keys(Ipo *ipo, short snaptype)
}
}
static int mirror_bezier_cframe(BezTriple *bezt)
{
float diff;
if(bezt->f2 & SELECT) {
diff= ((float)CFRA - bezt->vec[1][0]);
bezt->vec[1][0]= ((float)CFRA + diff);
}
return 0;
}
static int mirror_bezier_yaxis(BezTriple *bezt)
{
float diff;
if(bezt->f2 & SELECT) {
diff= (0.0f - bezt->vec[1][0]);
bezt->vec[1][0]= (0.0f + diff);
}
return 0;
}
void mirror_ipo_keys(Ipo *ipo, short mirror_type)
{
switch (mirror_type) {
case 1: /* mirror over current frame */
ipo_keys_bezier_loop(ipo, mirror_bezier_cframe, calchandles_ipocurve);
break;
case 2: /* snap over frame 0 */
ipo_keys_bezier_loop(ipo, mirror_bezier_yaxis, calchandles_ipocurve);
break;
default: /* just in case */
ipo_keys_bezier_loop(ipo, mirror_bezier_yaxis, calchandles_ipocurve);
break;
}
}
static void ipo_curves_auto_horiz(void)
{
EditIpo *ei;

View File

@@ -101,7 +101,6 @@
#define ACTMENU_KEY_DELETE 1
#define ACTMENU_KEY_BAKE 2
#define ACTMENU_KEY_CLEAN 3
#define ACTMENU_KEY_MIRROR 4
#define ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_UP 0
#define ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_DOWN 1
@@ -126,8 +125,11 @@
#define ACTMENU_KEY_EXTEND_CYCLIC 2
#define ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION 3
#define ACTMENU_KEY_SNAP_NEARFRAME 0
#define ACTMENU_KEY_SNAP_CURFRAME 1
#define ACTMENU_KEY_SNAP_NEARFRAME 1
#define ACTMENU_KEY_SNAP_CURFRAME 2
#define ACTMENU_KEY_MIRROR_CURFRAME 1
#define ACTMENU_KEY_MIRROR_YAXIS 2
#define ACTMENU_MARKERS_ADD 0
#define ACTMENU_MARKERS_DUPLICATE 1
@@ -832,10 +834,8 @@ static void do_action_keymenu_snapmenu(void *arg, int event)
switch(event)
{
case ACTMENU_KEY_SNAP_NEARFRAME:
snap_keys_to_frame(1);
break;
case ACTMENU_KEY_SNAP_CURFRAME:
snap_keys_to_frame(2);
snap_keys_to_frame(event);
break;
}
@@ -866,6 +866,43 @@ static uiBlock *action_keymenu_snapmenu(void *arg_unused)
return block;
}
static void do_action_keymenu_mirrormenu(void *arg, int event)
{
switch(event)
{
case ACTMENU_KEY_MIRROR_CURFRAME:
case ACTMENU_KEY_MIRROR_YAXIS:
mirror_action_keys(event);
break;
}
scrarea_queue_winredraw(curarea);
}
static uiBlock *action_keymenu_mirrormenu(void *arg_unused)
{
uiBlock *block;
short yco= 0, menuwidth=120;
block= uiNewBlock(&curarea->uiblocks, "action_keymenu_mirrormenu",
UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
uiBlockSetButmFunc(block, do_action_keymenu_mirrormenu, NULL);
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Current Frame|Shift M, 1", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_MIRROR_CURFRAME, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Vertical Axis|Shift M, 2", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_MIRROR_YAXIS, "");
uiBlockSetDirection(block, UI_RIGHT);
uiTextBoundsBlock(block, 60);
return block;
}
static void do_action_keymenu(void *arg, int event)
{
SpaceAction *saction;
@@ -926,6 +963,9 @@ static uiBlock *action_keymenu(void *arg_unused)
uiDefIconTextBlockBut(block, action_keymenu_snapmenu,
NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, "");
uiDefIconTextBlockBut(block, action_keymenu_mirrormenu,
NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 20, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");