NLA SoC: Quick hack - Reversed playback
Animations can now be played back in reverse, by clicking on the reversed-playback button in the TimeLine header beside the play button (NEW ICON NEEDED HERE). I'm not sure how well this works with sound, but from what I gather, this can be quite useful for animators to use.
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
typedef struct ScreenAnimData {
|
||||
ARegion *ar; /* do not read from this, only for comparing if region exists */
|
||||
int redraws;
|
||||
int reverse;
|
||||
} ScreenAnimData;
|
||||
|
||||
|
||||
|
||||
@@ -1460,7 +1460,9 @@ void ED_screen_full_prevspace(bContext *C)
|
||||
ed_screen_fullarea(C, sa);
|
||||
}
|
||||
|
||||
/* redraws: uses defines from stime->redraws */
|
||||
/* redraws: uses defines from stime->redraws
|
||||
* enable: 1 - forward on, -1 - backwards on, 0 - off
|
||||
*/
|
||||
void ED_screen_animation_timer(bContext *C, int redraws, int enable)
|
||||
{
|
||||
bScreen *screen= CTX_wm_screen(C);
|
||||
@@ -1477,6 +1479,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int enable)
|
||||
screen->animtimer= WM_event_add_window_timer(win, TIMER0, (1.0/FPS));
|
||||
sad->ar= CTX_wm_region(C);
|
||||
sad->redraws= redraws;
|
||||
sad->reverse= (enable < 0);
|
||||
screen->animtimer->customdata= sad;
|
||||
|
||||
}
|
||||
|
||||
@@ -2067,19 +2067,40 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
if(scene->audio.flag & AUDIO_SYNC) {
|
||||
int step = floor(wt->duration * FPS);
|
||||
scene->r.cfra += step;
|
||||
if (sad->reverse) // XXX does this option work with audio?
|
||||
scene->r.cfra -= step;
|
||||
else
|
||||
scene->r.cfra += step;
|
||||
wt->duration -= ((float)step)/FPS;
|
||||
}
|
||||
else
|
||||
scene->r.cfra++;
|
||||
else {
|
||||
if (sad->reverse)
|
||||
scene->r.cfra--;
|
||||
else
|
||||
scene->r.cfra++;
|
||||
}
|
||||
|
||||
if (scene->r.psfra) {
|
||||
if(scene->r.cfra > scene->r.pefra)
|
||||
scene->r.cfra= scene->r.psfra;
|
||||
if (sad->reverse) {
|
||||
/* jump back to end */
|
||||
if (scene->r.psfra) {
|
||||
if(scene->r.cfra < scene->r.psfra)
|
||||
scene->r.cfra= scene->r.pefra;
|
||||
}
|
||||
else {
|
||||
if(scene->r.cfra < scene->r.sfra)
|
||||
scene->r.cfra= scene->r.efra;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(scene->r.cfra > scene->r.efra)
|
||||
scene->r.cfra= scene->r.sfra;
|
||||
/* jump back to start */
|
||||
if (scene->r.psfra) {
|
||||
if(scene->r.cfra > scene->r.pefra)
|
||||
scene->r.cfra= scene->r.psfra;
|
||||
}
|
||||
else {
|
||||
if(scene->r.cfra > scene->r.efra)
|
||||
scene->r.cfra= scene->r.sfra;
|
||||
}
|
||||
}
|
||||
|
||||
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
|
||||
@@ -2127,8 +2148,9 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
|
||||
ED_screen_animation_timer(C, 0, 0);
|
||||
}
|
||||
else {
|
||||
/* todo: RNA properties to define play types */
|
||||
ED_screen_animation_timer(C, TIME_REGION|TIME_ALL_3D_WIN, 1);
|
||||
int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
|
||||
|
||||
ED_screen_animation_timer(C, TIME_REGION|TIME_ALL_3D_WIN, mode);
|
||||
|
||||
if(screen->animtimer) {
|
||||
wmTimer *wt= screen->animtimer;
|
||||
@@ -2152,7 +2174,7 @@ void SCREEN_OT_animation_play(wmOperatorType *ot)
|
||||
|
||||
ot->poll= ED_operator_screenactive;
|
||||
|
||||
|
||||
RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards");
|
||||
}
|
||||
|
||||
/* ************** border select operator (template) ***************************** */
|
||||
|
||||
@@ -373,6 +373,7 @@ static uiBlock *time_framemenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
#define B_REDRAWALL 750
|
||||
#define B_TL_REW 751
|
||||
#define B_TL_PLAY 752
|
||||
#define B_TL_RPLAY 760
|
||||
#define B_TL_FF 753
|
||||
#define B_TL_PREVKEY 754
|
||||
#define B_TL_NEXTKEY 755
|
||||
@@ -415,6 +416,18 @@ void do_time_buttons(bContext *C, void *arg, int event)
|
||||
sad->ar= time_top_left_3dwindow(screen);
|
||||
}
|
||||
|
||||
break;
|
||||
case B_TL_RPLAY:
|
||||
ED_screen_animation_timer(C, stime->redraws, -1);
|
||||
|
||||
/* update region if TIME_REGION was set, to leftmost 3d window */
|
||||
if(screen->animtimer && (stime->redraws & TIME_REGION)) {
|
||||
wmTimer *wt= screen->animtimer;
|
||||
ScreenAnimData *sad= wt->customdata;
|
||||
|
||||
sad->ar= time_top_left_3dwindow(screen);
|
||||
}
|
||||
|
||||
break;
|
||||
case B_TL_STOP:
|
||||
ED_screen_animation_timer(C, 0, 0);
|
||||
@@ -553,14 +566,27 @@ void time_header_buttons(const bContext *C, ARegion *ar)
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to previous keyframe (Ctrl PageDown)");
|
||||
xco+= XIC+4;
|
||||
|
||||
if(CTX_wm_screen(C)->animtimer)
|
||||
if(CTX_wm_screen(C)->animtimer) {
|
||||
/* pause button is drawn centered between the two other buttons for now (saves drawing 2 buttons, or having position changes) */
|
||||
xco+= XIC/2 + 2;
|
||||
|
||||
uiDefIconBut(block, BUT, B_TL_STOP, ICON_PAUSE,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Stop Playing Timeline");
|
||||
else
|
||||
|
||||
xco+= XIC/2 + 2;
|
||||
}
|
||||
else {
|
||||
// FIXME: the icon for this is crap
|
||||
uiDefIconBut(block, BUT, B_TL_RPLAY, ICON_REW/*ICON_PLAY*/,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Play Timeline in Reverse");
|
||||
|
||||
xco+= XIC+4;
|
||||
|
||||
uiDefIconBut(block, BUT, B_TL_PLAY, ICON_PLAY,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Play Timeline ");
|
||||
|
||||
}
|
||||
xco+= XIC+4;
|
||||
|
||||
uiDefIconBut(block, BUT, B_TL_NEXTKEY, ICON_NEXT_KEYFRAME,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to next keyframe (Ctrl PageUp)");
|
||||
xco+= XIC+4;
|
||||
|
||||
Reference in New Issue
Block a user