== 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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, "");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user