diff options
author | Joshua Leung <aligorith@gmail.com> | 2006-12-02 09:00:31 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2006-12-02 09:00:31 +0300 |
commit | ac43fe5afdb4eb2d5684c686c31b087495e350d9 (patch) | |
tree | ac8f751c58f7e2dfec18b3c0d7186b557f87b3d0 | |
parent | 28bbf2d61616f7b8b3c59b54b46af7ee4dbf1e11 (diff) |
== 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).
-rw-r--r-- | source/blender/include/BIF_editaction.h | 2 | ||||
-rw-r--r-- | source/blender/include/BSE_editipo.h | 1 | ||||
-rw-r--r-- | source/blender/src/editaction.c | 156 | ||||
-rw-r--r-- | source/blender/src/editipo_mods.c | 39 | ||||
-rw-r--r-- | source/blender/src/header_action.c | 52 |
5 files changed, 202 insertions, 48 deletions
diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index e6cd5765360..ca4f7944460 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -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); diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index b7da37bb2e2..b4f53979121 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -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); diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 54f5d041c2b..c7d5223f702 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -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: diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index 822b085e734..fd9a60edf3e 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -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; diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index 3c06078b467..194d4976f51 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -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, ""); |