diff options
author | Joshua Leung <aligorith@gmail.com> | 2007-01-10 01:27:27 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2007-01-10 01:27:27 +0300 |
commit | 970dbb2e7926a871ef4eb70074e1909198fee032 (patch) | |
tree | 9788ab163153509a37146ce714ff8d35bad8110a /source | |
parent | 9b3862b4c040eabcb5d3fc82b0ed9774170c0fbe (diff) |
== Action Editor -> Auto-Snap ==
There's a new selection-box on the header of the action editor, which
sets the mode of auto-snapping for transforms. By default auto-snapping
is off.
There are 3 modes of auto-snap:
* Off - transforms per normal
* Frame Step - grid-step transform (may have errors with scaled actions)
* Nearest Frame - true snap-to-frame (takes into account nla-scaling)
These translate to the following hotkeys when transforming:
* Off - no keys press/held (as it's always been)
* Frame Step - Ctrl (as it's always been)
* Nearest Frame - Shift (replaces old shift-key behaviour which was not useful)
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 7 | ||||
-rw-r--r-- | source/blender/src/editaction.c | 96 | ||||
-rw-r--r-- | source/blender/src/header_action.c | 13 |
3 files changed, 104 insertions, 12 deletions
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 08546dc4984..7d221d34d6e 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -116,7 +116,7 @@ typedef struct SpaceAction { View2D v2d; bAction *action; - int flag; + short flag, autosnap; short pin, actnr, lock, actwidth; float timeslide; } SpaceAction; @@ -132,6 +132,11 @@ typedef struct SpaceAction { #define SACTION_MOVING 1 /* during transform */ #define SACTION_SLIDERS 2 /* show sliders (if relevant) - limited to shape keys for now */ +/* SpaceAction AutoSnap Settings */ +#define SACTSNAP_OFF 0 /* no auto-snap */ +#define SACTSNAP_STEP 1 /* snap to 1.0 frame intervals */ +#define SACTSNAP_FRAME 2 /* snap to actual frames (nla-action time) */ + /* Pose->flag */ #define POSE_RECALC 1 #define POSE_LOCKED 2 diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 683e5e3c216..4b2f0d175c6 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -1092,6 +1092,27 @@ void transform_actionchannel_keys(int mode, int dummy) if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) { PIL_sleep_ms(1); } else { + short autosnap= 0; + + /* determine mode of keyframe snapping/autosnap */ + if (mode != 't') { + switch (G.saction->autosnap) { + case SACTSNAP_OFF: + if (G.qual == LR_CTRLKEY) + autosnap= SACTSNAP_STEP; + else if (G.qual == LR_SHIFTKEY) + autosnap= SACTSNAP_FRAME; + else + autosnap= SACTSNAP_OFF; + break; + case SACTSNAP_STEP: + autosnap= (G.qual==LR_CTRLKEY)? SACTSNAP_OFF: SACTSNAP_STEP; + break; + case SACTSNAP_FRAME: + autosnap= (G.qual==LR_SHIFTKEY)? SACTSNAP_OFF: SACTSNAP_FRAME; + break; + } + } for (i=0; i<tvtot; i++){ tv[i].loc[0]=tv[i].oldloc[0]; @@ -1113,11 +1134,14 @@ void transform_actionchannel_keys(int mode, int dummy) } break; case 'g': - deltax = cval[0]-sval[0]; + deltax = cval[0] - sval[0]; fac= deltax; - apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID); - + if (autosnap == SACTSNAP_STEP) { + /* NOTE: this doesn't take into account NLA scaling */ + fac= 1.0f*floor(fac/1.0f + 0.5f); + } + tv[i].loc[0]+=fac; break; case 's': @@ -1125,8 +1149,11 @@ void transform_actionchannel_keys(int mode, int dummy) deltax=mvalc[0]-(ACTWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2); fac= fabs(deltax/startx); - apply_keyb_grid(&fac, 0.0, 0.2, 0.1, U.flag & USER_AUTOSIZEGRID); - + if (autosnap == SACTSNAP_STEP) { + /* NOTE: this doesn't take into account NLA scaling */ + fac= 1.0f*floor(fac/1.0f + 0.5f); + } + if (invert){ if (i % 03 == 0){ memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i+2].oldloc)); @@ -1147,6 +1174,26 @@ void transform_actionchannel_keys(int mode, int dummy) break; } + + /* snap key to nearest frame? */ + if (autosnap == SACTSNAP_FRAME) { + float snapval; + + /* convert frame to nla-action time (if needed) */ + if (G.saction->pin==0 && OBACT) + snapval= get_action_frame_inv(OBACT, tv[i].loc[0]); + else + snapval= tv[i].loc[0]; + + /* snap to nearest frame */ + snapval= (float)(floor(snapval+0.5)); + + /* convert frame out of nla-action time */ + if (G.saction->pin==0 && OBACT) + tv[i].loc[0]= get_action_frame(OBACT, snapval); + else + tv[i].loc[0]= snapval; + } } if (mode=='s'){ @@ -1308,6 +1355,28 @@ void transform_meshchannel_keys(char mode, Key *key) if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) { PIL_sleep_ms(1); } else { + short autosnap= 0; + + /* determine mode of keyframe snapping/autosnap */ + if (mode != 't') { + switch (G.saction->autosnap) { + case SACTSNAP_OFF: + if (G.qual == LR_CTRLKEY) + autosnap= SACTSNAP_STEP; + else if (G.qual == LR_SHIFTKEY) + autosnap= SACTSNAP_FRAME; + else + autosnap= SACTSNAP_OFF; + break; + case SACTSNAP_STEP: + autosnap= (G.qual==LR_CTRLKEY)? SACTSNAP_OFF: SACTSNAP_FRAME; + break; + case SACTSNAP_FRAME: + autosnap= (G.qual==LR_SHIFTKEY)? SACTSNAP_OFF: SACTSNAP_FRAME; + break; + } + } + for (i=0; i<tvtot; i++){ tv[i].loc[0]=tv[i].oldloc[0]; @@ -1316,8 +1385,10 @@ void transform_meshchannel_keys(char mode, Key *key) deltax = cval[0]-sval[0]; fac= deltax; - apply_keyb_grid(&fac, 0.0, 1.0, 0.1, - U.flag & USER_AUTOGRABGRID); + if (autosnap == SACTSNAP_STEP) { + /* NOTE: this doesn't take into account NLA scaling */ + fac= 1.0f*floor(fac/1.0f + 0.5f); + } tv[i].loc[0]+=fac; break; @@ -1328,8 +1399,10 @@ void transform_meshchannel_keys(char mode, Key *key) -curarea->winrct.xmin)/2); fac= fabs(deltax/startx); - apply_keyb_grid(&fac, 0.0, 0.2, 0.1, - U.flag & USER_AUTOSIZEGRID); + if (autosnap == SACTSNAP_FRAME) { + /* NOTE: this doesn't take into account NLA scaling */ + fac= 1.0f*floor(fac/1.0f + 0.5f); + } if (invert){ if (i % 03 == 0){ @@ -1351,6 +1424,11 @@ void transform_meshchannel_keys(char mode, Key *key) break; } + + /* auto-snap key to nearest frame? */ + if (autosnap == SACTSNAP_FRAME) { + tv[i].loc[0]= (float)(floor(tv[i].loc[0]+0.5)); + } } } /* Display a message showing the magnitude of diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index 97c328f0b4f..11ff4820643 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -1270,14 +1270,23 @@ void action_buttons(void) uiClearButLock(); - /* draw LOCK */ + /* draw AUTOSNAP */ xco+= 8; + + uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_PROP_OFF, + "Auto-Snap Keys %t|Off %x0|Frame Step %x1|Nearest Frame %x2", + xco,0,XIC+10,YIC, &(G.saction->autosnap), 0, 1, 0, 0, + "Auto-snapping mode for keys when transforming"); + + xco+= (XIC + 18); + + /* draw LOCK*/ + uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco, 0, XIC, YIC, &(G.saction->lock), 0, 0, 0, 0, "Updates other affected window spaces automatically " "to reflect changes in real time"); - /* always as last */ curarea->headbutlen = xco + 2*XIC; |