2.5
authorTon Roosendaal <ton@blender.org>
Thu, 21 May 2009 13:33:04 +0000 (13:33 +0000)
committerTon Roosendaal <ton@blender.org>
Thu, 21 May 2009 13:33:04 +0000 (13:33 +0000)
Animation playback back in control. And non-blocking still!

- Play follows the "Playback" options in TimeLine menu.
  Only the region 'windows' are drawn, not headers, toolbars,
  channel views, etc.
  The option "Buttons Window" also redraws property regions.
- The Timeline header always redraws, this to denote at least
  progressing frame numbers
- For now: if you choose to play 3D views, it also redraws
  the TimeLine. Seems to be good convention, but probably
  better to add menu option for it?

- Fun test: while playback, change Playback options, works OK!

- New: top header button shows animation play status, and allows
  to stop playback

- New: Animation stop/start operator. Assigned to ALT+A. It has
  no options yet; just plays active region + all 3D windows now.
  Options will follow, based on reviews.
  Also ESC won't work for now, just press ALT+A again.

source/blender/editors/include/ED_screen.h
source/blender/editors/include/ED_screen_types.h
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_info/info_header.c
source/blender/editors/space_info/space_info.c
source/blender/editors/space_time/space_time.c
source/blender/editors/space_time/time_header.c
source/blender/makesdna/DNA_space_types.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_window.c

index 2484b558b0465a80b47d72302de2c3e6ce3f7c4a..c2beb34e7b5e704f0545584731ae4a66c16535e7 100644 (file)
@@ -89,7 +89,7 @@ void  ED_screen_set(struct bContext *C, struct bScreen *sc);
 void   ED_screen_set_scene(struct bContext *C, struct Scene *scene);
 void   ED_screen_set_subwinactive(struct wmWindow *win, struct wmEvent *event);
 void   ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
-void   ED_screen_animation_timer(struct bContext *C, int enable);
+void   ED_screen_animation_timer(struct bContext *C, int redraws, int enable);
 int            ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
 void   ED_screen_full_prevspace(struct bContext *C);
 
index 7910351f318fe5384079344a04c9b0fed9455372..5a13e944d5c3a371b31d912421ea63026cd23ca9 100644 (file)
 #ifndef ED_SCREEN_TYPES_H__
 #define ED_SCREEN_TYPES_H__
 
+/* for animplayer */
+typedef struct ScreenAnimData {
+       ARegion *ar;    /* do not read from this, only for comparing if region exists */
+       int redraws;
+} ScreenAnimData;
+
+
 typedef struct AZone {
        struct AZone *next, *prev;
        int type;
index 51515f1862343903a27821b054b82fccadc267e6..a5950b97f61f4ccfdaa19d518ad4ee2d0d0dc99c 100644 (file)
@@ -1430,7 +1430,8 @@ void ED_screen_full_prevspace(bContext *C)
                ed_screen_fullarea(C, sa);
 }
 
-void ED_screen_animation_timer(bContext *C, int enable)
+/* redraws: uses defines from stime->redraws */
+void ED_screen_animation_timer(bContext *C, int redraws, int enable)
 {
        bScreen *screen= CTX_wm_screen(C);
        wmWindow *win= CTX_wm_window(C);
@@ -1440,8 +1441,17 @@ void ED_screen_animation_timer(bContext *C, int enable)
                WM_event_remove_window_timer(win, screen->animtimer);
        screen->animtimer= NULL;
        
-       if(enable)
+       if(enable) {
+               struct ScreenAnimData *sad= MEM_mallocN(sizeof(ScreenAnimData), "ScreenAnimData");
+               
                screen->animtimer= WM_event_add_window_timer(win, TIMER0, (1.0/FPS));
+               sad->ar= CTX_wm_region(C);
+               sad->redraws= redraws;
+               screen->animtimer->customdata= sad;
+               
+       }
+       /* notifier catched by top header, for button */
+       WM_event_add_notifier(C, NC_SCREEN|ND_ANIMPLAY, screen);
 }
 
 unsigned int ED_screen_view3d_layers(bScreen *screen)
index 7ada548927ff652813aebe399ede071f07b1a995..c991a63e762c4786c91deb67b52079e6c009e99b 100644 (file)
@@ -1859,17 +1859,65 @@ void SCREEN_OT_region_flip(wmOperatorType *ot)
 
 }
 
-/* ****************** anim player, typically with timer ***************** */
+/* ****************** anim player, with timer ***************** */
 
-static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
+static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
+{
+       if(regiontype==RGN_TYPE_WINDOW) {
+
+               switch (spacetype) {
+                       case SPACE_VIEW3D:
+                               if(redraws & TIME_ALL_3D_WIN)
+                                       return 1;
+                               break;
+                       case SPACE_IPO:
+                       case SPACE_ACTION:
+                       case SPACE_NLA:
+                               if(redraws & TIME_ALL_ANIM_WIN)
+                                       return 1;
+                               break;
+                       case SPACE_TIME:
+                               /* if only 1 window or 3d windows, we do timeline too */
+                               if(redraws & (TIME_ALL_ANIM_WIN|TIME_REGION|TIME_ALL_3D_WIN))
+                                       return 1;
+                               break;
+                       case SPACE_BUTS:
+                               if(redraws & TIME_ALL_BUTS_WIN)
+                                       return 1;
+                               break;
+                       case SPACE_SEQ:
+                               if(redraws & (TIME_SEQ|TIME_ALL_ANIM_WIN))
+                                       return 1;
+                               break;
+                       case SPACE_IMAGE:
+                               if(redraws & TIME_ALL_IMAGE_WIN)
+                                       return 1;
+                               break;
+                               
+               }
+       }
+       else if(regiontype==RGN_TYPE_UI) {
+               if(redraws & TIME_ALL_BUTS_WIN)
+                       return 1;
+       }
+       else if(regiontype==RGN_TYPE_HEADER) {
+               if(spacetype==SPACE_TIME)
+                       return 1;
+       }
+       return 0;
+}
+
+static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
 {
        bScreen *screen= CTX_wm_screen(C);
        
        if(screen->animtimer==event->customdata) {
                Scene *scene= CTX_data_scene(C);
+               wmTimer *wt= screen->animtimer;
+               ScreenAnimData *sad= wt->customdata;
+               ScrArea *sa;
                
                if(scene->audio.flag & AUDIO_SYNC) {
-                       wmTimer *wt= screen->animtimer;
                        int step = floor(wt->duration * FPS);
                        scene->r.cfra += step;
                        wt->duration -= ((float)step)/FPS;
@@ -1886,13 +1934,65 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
                                scene->r.cfra= scene->r.sfra;
                }
 
-               WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+               /* since we follow drawflags, we can't send notifier but tag regions ourselves */
+               ED_update_for_newframe(C, 1);
+               
+               for(sa= screen->areabase.first; sa; sa= sa->next) {
+                       ARegion *ar;
+                       for(ar= sa->regionbase.first; ar; ar= ar->next) {
+                               if(ar==sad->ar)
+                                       ED_region_tag_redraw(ar);
+                               else
+                                       if(match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws))
+                                               ED_region_tag_redraw(ar);
+                       }
+               }
+               
+               //WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
                
                return OPERATOR_FINISHED;
        }
        return OPERATOR_PASS_THROUGH;
 }
 
+static void SCREEN_OT_animation_step(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Animation Step";
+       ot->idname= "SCREEN_OT_animation_step";
+       
+       /* api callbacks */
+       ot->invoke= screen_animation_step;
+       
+       ot->poll= ED_operator_screenactive;
+       
+}
+
+/* ****************** anim player, starts or ends timer ***************** */
+
+/* toggle operator */
+static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
+{
+       bScreen *screen= CTX_wm_screen(C);
+       
+       if(screen->animtimer) {
+               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);
+               
+               if(screen->animtimer) {
+                       wmTimer *wt= screen->animtimer;
+                       ScreenAnimData *sad= wt->customdata;
+                       
+                       sad->ar= CTX_wm_region(C);
+               }
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
 void SCREEN_OT_animation_play(wmOperatorType *ot)
 {
        /* identifiers */
@@ -1904,6 +2004,7 @@ void SCREEN_OT_animation_play(wmOperatorType *ot)
        
        ot->poll= ED_operator_screenactive;
        
+       
 }
 
 /* ************** border select operator (template) ***************************** */
@@ -2400,6 +2501,7 @@ void ED_operatortypes_screen(void)
        
        /*frame changes*/
        WM_operatortype_append(SCREEN_OT_frame_offset);
+       WM_operatortype_append(SCREEN_OT_animation_step);
        WM_operatortype_append(SCREEN_OT_animation_play);
        
        /* render */
@@ -2418,7 +2520,7 @@ void ED_keymap_screen(wmWindowManager *wm)
        ListBase *keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
        
        /* standard timers */
-       WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", TIMER0, KM_ANY, KM_ANY, 0);
+       WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0);
        
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1);
@@ -2464,12 +2566,13 @@ void ED_keymap_screen(wmWindowManager *wm)
        WM_keymap_add_item(keymap, "SCREEN_OT_render", F12KEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_render_view_cancel", ESCKEY, KM_PRESS, 0, 0);
        
-       /* frame offsets */
+       /* frame offsets & play */
        keymap= WM_keymap_listbase(wm, "Frames", 0, 0);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -10);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
+       WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT, 0);
        
 }
 
index af792d0b22cff2b7ec13d5b197051f0ddaa87812..aa6aadd00bc088d0ecc3a339119cc417b434928c 100644 (file)
@@ -72,8 +72,9 @@ static int error() {return 0;}
 
 /* ************************ header area region *********************** */
 
-#define B_STOPRENDER 1
-#define B_STOPCAST 2
+#define B_STOPRENDER   1
+#define B_STOPCAST             2
+#define B_STOPANIM             3
 
 static void do_viewmenu(bContext *C, void *arg, int event)
 {
@@ -328,6 +329,9 @@ static void do_info_buttons(bContext *C, void *arg, int event)
                case B_STOPCAST:
                        WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
                        break;
+               case B_STOPANIM:
+                       ED_screen_animation_timer(C, 0, 0);
+                       break;
        }
 }
 
@@ -444,6 +448,10 @@ void info_header_buttons(const bContext *C, ARegion *ar)
                uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", xco+5,yco,85,19, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
                xco+= 90;
        }
+       if(screen->animtimer) {
+               uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_REC, "Anim Player", xco+5,yco,85,19, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
+               xco+= 90;
+       }
        
        /* always as last  */
        UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
index 12f23f03e662ca3df0ad519a0f26e920434bfcf0..d72ecd60da912b187a97a66f327f1052658a4b1e 100644 (file)
@@ -43,6 +43,7 @@
 #include "BKE_context.h"
 #include "BKE_colortools.h"
 #include "BKE_screen.h"
+#include "BKE_utildefines.h"
 
 #include "ED_space_api.h"
 #include "ED_screen.h"
@@ -196,7 +197,7 @@ static void info_header_listener(ARegion *ar, wmNotifier *wmn)
        /* context changes */
        switch(wmn->category) {
                case NC_SCREEN:
-                       if(wmn->data==ND_SCREENCAST)
+                       if(ELEM(wmn->data, ND_SCREENCAST, ND_ANIMPLAY))
                                ED_region_tag_redraw(ar);
                        break;
                case NC_SCENE:
index 3df57208bbd49c61b767ef99a2acbb05d1e10c2b..c4ca4d8522fafe151d14fb019e5015f6a57b677b 100644 (file)
@@ -207,6 +207,10 @@ static void time_header_area_listener(ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch(wmn->category) {
+               case NC_SCREEN:
+                       if(wmn->data==ND_ANIMPLAY)
+                               ED_region_tag_redraw(ar);
+                       break;
                case NC_SCENE:
                        switch (wmn->data) {
                                case ND_FRAME:
index f26e632eb872e9ad3685309ba5893549f3ada18b..cf9c12f3dff9278e4235cdb99b3ae43ebe8c3168 100644 (file)
@@ -46,6 +46,7 @@
 
 #include "ED_keyframing.h"
 #include "ED_screen.h"
+#include "ED_screen_types.h"
 #include "ED_types.h"
 #include "ED_util.h"
 
 
 /* ************************ header time area region *********************** */
 
+static ARegion *time_top_left_3dwindow(bScreen *screen)
+{
+       ARegion *aret= NULL;
+       ScrArea *sa;
+       int min= 10000;
+       
+       for(sa= screen->areabase.first; sa; sa= sa->next) {
+               if(sa->spacetype==SPACE_VIEW3D) {
+                       ARegion *ar;
+                       for(ar= sa->regionbase.first; ar; ar= ar->next) {
+                               if(ar->regiontype==RGN_TYPE_WINDOW) {
+                                       if(ar->winrct.xmin - ar->winrct.ymin < min) {
+                                               aret= ar;
+                                               min= ar->winrct.xmin - ar->winrct.ymin;
+                                       }
+                               }
+                       }
+               }
+       }
+       return aret;
+}
 
 static void do_time_redrawmenu(bContext *C, void *arg, int event)
 {
-       SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
        
        if(event < 1001) {
+               bScreen *screen= CTX_wm_screen(C);
+               SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
                
                stime->redraws ^= event;
-               /* update handler when it's running */
-//             if(has_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM))
-//                     start_animated_screen(stime);
+               
+               if(screen->animtimer) {
+                       wmTimer *wt= screen->animtimer;
+                       ScreenAnimData *sad= wt->customdata;
+                       
+                       sad->redraws= stime->redraws;
+                       sad->ar= NULL;
+                       if(stime->redraws & TIME_REGION)
+                               sad->ar= time_top_left_3dwindow(screen);
+               }
        }
        else {
                if(event==1001) {
@@ -98,9 +128,9 @@ static uiBlock *time_redrawmenu(bContext *C, ARegion *ar, void *arg_unused)
        block= uiBeginBlock(C, ar, "header time_redrawmenu", UI_EMBOSSP);
        uiBlockSetButmFunc(block, do_time_redrawmenu, NULL);
        
-       if(stime->redraws & TIME_LEFTMOST_3D_WIN) icon= ICON_CHECKBOX_HLT;
+       if(stime->redraws & TIME_REGION) icon= ICON_CHECKBOX_HLT;
        else icon= ICON_CHECKBOX_DEHLT;
-       uiDefIconTextBut(block, BUTM, 1, icon, "Top-Left 3D Window",     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_LEFTMOST_3D_WIN, "");
+       uiDefIconTextBut(block, BUTM, 1, icon, "Top-Left 3D Window",     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_REGION, "");
        
        if(stime->redraws & TIME_ALL_3D_WIN) icon= ICON_CHECKBOX_HLT;
        else icon= ICON_CHECKBOX_DEHLT;
@@ -358,7 +388,8 @@ static uiBlock *time_framemenu(bContext *C, ARegion *ar, void *arg_unused)
 
 void do_time_buttons(bContext *C, void *arg, int event)
 {
-//     SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
+       bScreen *screen= CTX_wm_screen(C);
+       SpaceTime *stime= (SpaceTime*)CTX_wm_space_data(C);
        Scene *scene= CTX_data_scene(C);
        
        switch(event) {
@@ -374,10 +405,19 @@ void do_time_buttons(bContext *C, void *arg, int event)
                        //update_for_newframe();
                        break;
                case B_TL_PLAY:
-                       ED_screen_animation_timer(C, 1);
+                       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);
+                       ED_screen_animation_timer(C, 0, 0);
                        break;
                case B_TL_FF:
                        /* end frame */
index 0d88e3eb6e8fd9f43b1951540236e51e389d7eb0..8cdb51bcab0e0051880f677e17fc88c5e30154ea 100644 (file)
@@ -684,7 +684,7 @@ enum {
 #define TIME_ONLYACTSEL                4
 
 /* time->redraws */
-#define TIME_LEFTMOST_3D_WIN   1
+#define TIME_REGION                            1
 #define TIME_ALL_3D_WIN                        2
 #define TIME_ALL_ANIM_WIN              4
 #define TIME_ALL_BUTS_WIN              8
index d3cb60d90fee43a9e8da72d84c9b823fb9a763ca..b96089a05f1f07c7bc3a61e660b9acf7ddc90f09 100644 (file)
@@ -169,7 +169,7 @@ typedef struct wmNotifier {
        /* NC_SCREEN screen */
 #define ND_SCREENBROWSE                (1<<16)
 #define ND_SCREENCAST          (2<<16)
-
+#define ND_ANIMPLAY                    (3<<16)
 
        /* NC_SCENE Scene */
 #define ND_SCENEBROWSE         (1<<16)
@@ -276,7 +276,8 @@ typedef struct wmTabletData {
 typedef struct wmTimer {
        struct wmTimer *next, *prev;
        double timestep;                /* set by timer user */
-       int event_type;                 /* set by timer user */
+       int event_type;                 /* set by timer user, goes to event system */
+       void *customdata;               /* set by timer user, to allow custom values */
        
        double duration;                /* total running time in seconds */
        double delta;                   /* time since previous step in seconds */
index 2675fba729a551cd01ba90b865cd9d4bc8bbc5cf..cb6bcb41366b5202eb29d44e4f8dd19ba14f2ae6 100644 (file)
@@ -93,6 +93,8 @@ static void wm_ghostwindow_destroy(wmWindow *win)
    ED_screen_exit should have been called */
 void wm_window_free(bContext *C, wmWindow *win)
 {
+       wmTimer *wt;
+       
        /* update context */
        if(C) {
                wmWindowManager *wm= CTX_wm_manager(C);
@@ -108,6 +110,10 @@ void wm_window_free(bContext *C, wmWindow *win)
        }       
        
        if(win->eventstate) MEM_freeN(win->eventstate);
+       
+       for(wt= win->timers.first; wt; wt= wt->next)
+               if(wt->customdata)
+                       MEM_freeN(wt->customdata);
        BLI_freelistN(&win->timers);
        
        wm_event_free_all(win);
@@ -657,6 +663,8 @@ void WM_event_remove_window_timer(wmWindow *win, wmTimer *timer)
                        break;
        if(wt) {
                BLI_remlink(&win->timers, wt);
+               if(wt->customdata)
+                       MEM_freeN(wt->customdata);
                MEM_freeN(wt);
        }
 }