Auto Save
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 20 Oct 2009 13:58:53 +0000 (13:58 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 20 Oct 2009 13:58:53 +0000 (13:58 +0000)
Auto save is now working again in 2.5. It will also remember now what
the location of the original file was when recovering it, so that
library links still work and saving the restored file does not save to
the temp directory. There is also a new Recover Auto Save operator
which will open the filebrowser in the temp directory and show the
auto saved .blends.

Implemenation Notes:

* Timer storage was moved from window to windowmanager, so we can have
  windowmanager level timers too now, doesn't make sense to have
  autosave timer attached to a particular window.
* FileGlobal now has a filename field storing where the file was saved.
  Note that this is only used when loading a file through the recover
  operators, regular file read doesn't use it, so copying the quit.blend
  manually over the original file will still work as expected.
* Jobs timer no longer uses operator now, this seems more like an
  internal thing, changing keymaps should not make it possible to break
  the jobs manager.
* Autosave is postponed by 10 seconds when a modal operator is running,
  e.g. transform or file browsing.
* Moved setting G.sce in setup_app_data before depsgraph updates, these
  can use the filename for pointcaches.

33 files changed:
intern/ghost/intern/GHOST_WindowX11.cpp
release/scripts/ui/space_info.py
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/intern/blender.c
source/blender/blenloader/BLO_readfile.h
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_panel.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_stroke.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/uvedit/uvedit_unwrap_ops.c
source/blender/makesdna/DNA_fileglobal_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/intern/rna_userdef.c
source/blender/makesrna/intern/rna_wm.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_draw.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_jobs.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm.h
source/blender/windowmanager/wm_event_types.h
source/blender/windowmanager/wm_window.h

index d40ce4145f50762141a7c2006d12c50b43ce49bc..5e6bb93d9ba582ce395f85d27498837ff3d624c4 100644 (file)
@@ -1412,7 +1412,7 @@ setWindowCursorGrab(
                                setWindowCursorVisibility(false);
 
                }
-               XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+               //XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
        }
        else {
                if (m_cursorGrab==GHOST_kGrabHide) {
@@ -1430,7 +1430,7 @@ setWindowCursorGrab(
                /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
                setCursorGrabAccum(0, 0);
                m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
-               XUngrabPointer(m_display, CurrentTime);
+               //XUngrabPointer(m_display, CurrentTime);
        }
 
        XFlush(m_display);
index f9feef6f023ca737ea990e8b7551d827d1c70be3..d1e4ac13ab7b5191b7cf4570b6b7bd1367ae36c2 100644 (file)
@@ -54,6 +54,7 @@ class INFO_MT_file(bpy.types.Menu):
                layout.itemO("wm.open_mainfile", text="Open...", icon='ICON_FILE_FOLDER')
                layout.item_menu_enumO("wm.open_recentfile", "file", text="Open Recent")
                layout.itemO("wm.recover_last_session")
+               layout.itemO("wm.recover_auto_save", text="Recover Auto Save...")
 
                layout.itemS()
 
index 5d0b89220d5123542257a7d5da420325980a85d8..ccd21603c49879c4cadc54bcd8172d2c22d7b2f7 100644 (file)
@@ -145,6 +145,7 @@ typedef struct Global {
 #define G_FILE_GLSL_NO_NODES    (1 << 20)                              /* deprecated */
 #define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21)                             /* deprecated */
 #define G_FILE_IGNORE_DEPRECATION_WARNINGS     (1 << 22)       /* deprecated */
+#define G_FILE_RECOVER                  (1 << 23)
 
 /* G.windowstate */
 #define G_WINDOWSTATE_USERDEF          0
index 2df5b7c173c64fa47e5d1f2176cce1aadd1b686d..7570369827ba21145a1962a6fb5745cafe8aee77 100644 (file)
@@ -281,12 +281,15 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
        Object *ob;
        bScreen *curscreen= NULL;
        Scene *curscene= NULL;
+       int recover;
        char mode;
-       
+
        /* 'u' = undo save, 'n' = no UI load */
        if(bfd->main->screen.first==NULL) mode= 'u';
        else if(G.fileflags & G_FILE_NO_UI) mode= 'n';
        else mode= 0;
+
+       recover= (G.fileflags & G_FILE_RECOVER);
        
        clean_paths(bfd->main);
        
@@ -371,6 +374,16 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
        if(G.main->versionfile < 250)
                do_versions_ipos_to_animato(G.main); // XXX fixme... complicated versionpatching
        
+       /* in case of autosave or quit.blend, use original filename instead */
+       if(recover && bfd->filename[0])
+               filename= bfd->filename;
+       
+       /* these are the same at times, should never copy to the same location */
+       if(G.sce != filename)
+               BLI_strncpy(G.sce, filename, FILE_MAX);
+       
+       BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
+
        /* baseflags, groups, make depsgraph, etc */
        set_scene_bg(CTX_data_scene(C));
 
@@ -383,11 +396,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
        /* now tag update flags, to ensure deformers get calculated on redraw */
        DAG_scene_update_flags(CTX_data_scene(C), CTX_data_scene(C)->lay);
        
-       if (G.sce != filename) /* these are the same at times, should never copy to the same location */
-               strcpy(G.sce, filename);
-       
-       BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
-       
        MEM_freeN(bfd);
 }
 
index 52295dc3092368f146b514bf0f1da6de6fa72dae..408d07b965c45dcaa2ee8528e4406f038c633699 100644 (file)
@@ -62,6 +62,7 @@ typedef struct BlendFileData {
        int fileflags;
        int displaymode;
        int globalf;
+       char filename[240];     /* 240 = FILE_MAX */
        
        struct bScreen* curscreen;
        struct Scene*   curscene;
index 761fc8b079a3d7024d229c47fbd4d8b84f5ec955..ca2e5f4de756691085bee45371d90957a47abafa 100644 (file)
@@ -4432,7 +4432,6 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
                win->curswin= NULL;
                win->tweak= NULL;
 
-               win->timers.first= win->timers.last= NULL;
                win->queue.first= win->queue.last= NULL;
                win->handlers.first= win->handlers.last= NULL;
                win->modalhandlers.first= win->modalhandlers.last= NULL;
@@ -4444,6 +4443,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
                win->drawfail= 0;
        }
        
+       wm->timers.first= wm->timers.last= NULL;
        wm->operators.first= wm->operators.last= NULL;
        wm->paintcursors.first= wm->paintcursors.last= NULL;
        wm->queue.first= wm->queue.last= NULL;
@@ -5468,6 +5468,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
        bfd->fileflags= fg->fileflags;
        bfd->displaymode= fg->displaymode;
        bfd->globalf= fg->globalf;
+       BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
        
        bfd->curscreen= fg->curscreen;
        bfd->curscene= fg->curscene;
index e3d061d8e4bab4e5516b45473e7ff7edeb44f560..f0c584b626736ef80899d50c0865025868f7eb9f 100644 (file)
@@ -2308,7 +2308,7 @@ static void write_scripts(WriteData *wd, ListBase *idbase)
 /* context is usually defined by WM, two cases where no WM is available:
  * - for forward compatibility, curscreen has to be saved
  * - for undofile, curscene needs to be saved */
-static void write_global(WriteData *wd, Main *mainvar)
+static void write_global(WriteData *wd, int fileflags, Main *mainvar)
 {
        FileGlobal fg;
        bScreen *screen;
@@ -2321,8 +2321,9 @@ static void write_global(WriteData *wd, Main *mainvar)
        fg.curscene= screen->scene;
        fg.displaymode= G.displaymode;
        fg.winpos= G.winpos;
-       fg.fileflags= (G.fileflags & ~G_FILE_NO_UI);    // prevent to save this, is not good convention, and feature with concerns...
+       fg.fileflags= (fileflags & ~G_FILE_NO_UI);      // prevent to save this, is not good convention, and feature with concerns...
        fg.globalf= G.f;
+       BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
 
        sprintf(subvstr, "%4d", BLENDER_SUBVERSION);
        memcpy(fg.subvstr, subvstr, 4);
@@ -2351,7 +2352,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
        mywrite(wd, buf, 12);
 
        write_renderinfo(wd, mainvar);
-       write_global(wd, mainvar);
+       write_global(wd, write_flags, mainvar);
 
        /* no UI save in undo */
        if(current==NULL) {
index 29d840765330a4804ee83b3479dc416229bb0872..554e729e0e21ea1a84f197cf17faa3b6fc12ea64 100644 (file)
@@ -92,6 +92,7 @@ typedef enum uiHandleButtonState {
 } uiHandleButtonState;
 
 typedef struct uiHandleButtonData {
+       wmWindowManager *wm;
        wmWindow *window;
        ARegion *region;
 
@@ -3677,7 +3678,7 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but)
        data= but->active;
 
        if(data->tooltiptimer) {
-               WM_event_remove_window_timer(data->window, data->tooltiptimer);
+               WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
                data->tooltiptimer= NULL;
        }
        if(data->tooltip) {
@@ -3686,7 +3687,7 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but)
        }
 
        if(data->autoopentimer) {
-               WM_event_remove_window_timer(data->window, data->autoopentimer);
+               WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
                data->autoopentimer= NULL;
        }
 }
@@ -3698,13 +3699,13 @@ static void button_tooltip_timer_reset(uiBut *but)
        data= but->active;
 
        if(data->tooltiptimer) {
-               WM_event_remove_window_timer(data->window, data->tooltiptimer);
+               WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
                data->tooltiptimer= NULL;
        }
 
        if(U.flag & USER_TOOLTIPS)
                if(!but->block->tooltipdisabled)
-                       data->tooltiptimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_TOOLTIP_DELAY);
+                       data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
 }
 
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
@@ -3732,7 +3733,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                                else time= -1;
 
                                if(time >= 0)
-                                       data->autoopentimer= WM_event_add_window_timer(data->window, TIMER, 0.02*(double)time);
+                                       data->autoopentimer= WM_event_add_timer(data->wm, data->window, TIMER, 0.02*(double)time);
                        }
                }
        }
@@ -3765,10 +3766,10 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
 
        /* add a short delay before exiting, to ensure there is some feedback */
        if(state == BUTTON_STATE_WAIT_FLASH) {
-               data->flashtimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_FLASH_DELAY);
+               data->flashtimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_FLASH_DELAY);
        }
        else if(data->flashtimer) {
-               WM_event_remove_window_timer(data->window, data->flashtimer);
+               WM_event_remove_timer(data->wm, data->window, data->flashtimer);
                data->flashtimer= NULL;
        }
 
@@ -3799,6 +3800,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
 
        /* setup struct */
        data= MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
+       data->wm= CTX_wm_manager(C);
        data->window= CTX_wm_window(C);
        data->region= ar;
        if( ELEM(but->type, BUT_CURVE, SEARCH_MENU) );  // XXX curve is temp
@@ -4036,7 +4038,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                        case TIMER: {
                                /* handle tooltip timer */
                                if(event->customdata == data->tooltiptimer) {
-                                       WM_event_remove_window_timer(data->window, data->tooltiptimer);
+                                       WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
                                        data->tooltiptimer= NULL;
 
                                        if(!data->tooltip)
@@ -4044,7 +4046,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                                }
                                /* handle menu auto open timer */
                                else if(event->customdata == data->autoopentimer) {
-                                       WM_event_remove_window_timer(data->window, data->autoopentimer);
+                                       WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
                                        data->autoopentimer= NULL;
 
                                        if(ui_mouse_inside_button(ar, but, event->x, event->y))
@@ -4058,7 +4060,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                        case MIDDLEMOUSE:
                                /* XXX hardcoded keymap check... but anyway, while view changes, tooltips should be removed */
                                if(data->tooltiptimer) {
-                                       WM_event_remove_window_timer(data->window, data->tooltiptimer);
+                                       WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
                                        data->tooltiptimer= NULL;
                                }
                                /* pass on purposedly */
index 2123b412d615f71f862ec794d361d10bfd825bae..20cd6ebf971fbe55c939c1f6dd49f9895d3c1f5d 100644 (file)
@@ -1189,7 +1189,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
                pa->flag |= PNL_SELECT;
 
        if(data && data->animtimer) {
-               WM_event_remove_window_timer(win, data->animtimer);
+               WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer);
                data->animtimer= NULL;
        }
 
@@ -1208,7 +1208,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
                }
 
                if(ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
-                       data->animtimer= WM_event_add_window_timer(win, TIMER, ANIMATION_INTERVAL);
+                       data->animtimer= WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL);
 
                data->state= state;
                data->startx= win->eventstate->x;
index 2cc5500c3ef1e09bddfe07c2bbf8a928d09a0acc..6b71ccaba1043c2721946e1d61549c2244da94a4 100644 (file)
@@ -1040,7 +1040,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
 
        /* wake up animtimer */
        if(win->screen->animtimer)
-               WM_event_window_timer_sleep(win, win->screen->animtimer, 0);
+               WM_event_timer_sleep(wm, win, win->screen->animtimer, 0);
        
        if(G.f & G_DEBUG) printf("set screen\n");
        win->screen->do_refresh= 0;
@@ -1097,6 +1097,7 @@ void ED_area_exit(bContext *C, ScrArea *sa)
 
 void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
 {
+       wmWindowManager *wm= CTX_wm_manager(C);
        wmWindow *prevwin= CTX_wm_window(C);
        ScrArea *sa;
        ARegion *ar;
@@ -1104,7 +1105,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
        CTX_wm_window_set(C, window);
        
        if(screen->animtimer)
-               WM_event_remove_window_timer(window, screen->animtimer);
+               WM_event_remove_timer(wm, window, screen->animtimer);
        screen->animtimer= NULL;
        
        if(screen->mainwin)
@@ -1232,6 +1233,7 @@ int ED_screen_area_active(const bContext *C)
 /* Do NOT call in area/region queues! */
 void ED_screen_set(bContext *C, bScreen *sc)
 {
+       wmWindowManager *wm= CTX_wm_manager(C);
        wmWindow *win= CTX_wm_window(C);
        bScreen *oldscreen= CTX_wm_screen(C);
        ID *id;
@@ -1264,7 +1266,7 @@ void ED_screen_set(bContext *C, bScreen *sc)
                /* we put timer to sleep, so screen_exit has to think there's no timer */
                oldscreen->animtimer= NULL;
                if(wt)
-                       WM_event_window_timer_sleep(win, wt, 1);
+                       WM_event_timer_sleep(wm, win, wt, 1);
                
                ED_screen_exit(C, win, oldscreen);
                oldscreen->animtimer= wt;
@@ -1519,17 +1521,18 @@ void ED_screen_full_prevspace(bContext *C)
 void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
 {
        bScreen *screen= CTX_wm_screen(C);
+       wmWindowManager *wm= CTX_wm_manager(C);
        wmWindow *win= CTX_wm_window(C);
        Scene *scene= CTX_data_scene(C);
        
        if(screen->animtimer)
-               WM_event_remove_window_timer(win, screen->animtimer);
+               WM_event_remove_timer(wm, win, screen->animtimer);
        screen->animtimer= NULL;
        
        if(enable) {
                struct ScreenAnimData *sad= MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData");
                
-               screen->animtimer= WM_event_add_window_timer(win, TIMER0, (1.0/FPS));
+               screen->animtimer= WM_event_add_timer(wm, win, TIMER0, (1.0/FPS));
                sad->ar= CTX_wm_region(C);
                sad->redraws= redraws;
                sad->flag |= (enable < 0)? ANIMPLAY_FLAG_REVERSE: 0;
index 7596191e781d5a2f7e988bd4481fc45d7da47482..21651afe4176f7c08e41b62a6da2942679637811 100644 (file)
@@ -4645,7 +4645,7 @@ static void paint_exit(bContext *C, wmOperator *op)
        PaintOperation *pop= op->customdata;
 
        if(pop->timer)
-               WM_event_remove_window_timer(CTX_wm_window(C), pop->timer);
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
 
        settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
        imapaint_canvas_free(&pop->s);
@@ -4757,7 +4757,7 @@ static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event)
        WM_event_add_modal_handler(C, op);
 
        if(pop->s.brush->flag & BRUSH_AIRBRUSH)
-               pop->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
+               pop->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
 
        return OPERATOR_RUNNING_MODAL;
 }
index b83352ae70cc1155230ca21221a5a0962539492b..6e256bee7f27d285b11f40d896253cc673fc42c4 100644 (file)
@@ -243,7 +243,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
                                WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
 
                        if(stroke->brush->flag & BRUSH_AIRBRUSH)
-                               stroke->timer = WM_event_add_window_timer(CTX_wm_window(C), TIMER, stroke->brush->rate);
+                               stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
                }
 
                ED_region_tag_redraw(ar);
@@ -270,7 +270,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
                        WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
 
                if(stroke->timer)
-                       WM_event_remove_window_timer(CTX_wm_window(C), stroke->timer);
+                       WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), stroke->timer);
 
                stroke->done(C, stroke);
                MEM_freeN(stroke);
index 77a1b6710540728ca33cd5dd90a2afa1aa82615b..2a1bb8b4add69d723defdadf9aa4b494c1140aca 100644 (file)
@@ -610,7 +610,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
        }
 
        if (!sfile->loadimage_timer)
-               sfile->loadimage_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0);  /* max 30 frames/sec. */
+               sfile->loadimage_timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/30.0);      /* max 30 frames/sec. */
 }
 
 
index 482750e5b2e022045d84020b535158db525d344c..ffc737eb9af144ee367842ebe654e446dfb0f6b2 100644 (file)
@@ -1680,7 +1680,7 @@ static void record_composite_exit(bContext *C, wmOperator *op)
        WM_cursor_restore(CTX_wm_window(C));
 
        if(rcd->timer)
-               WM_event_remove_window_timer(CTX_wm_window(C), rcd->timer);
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rcd->timer);
 
        WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image);
 
@@ -1711,7 +1711,7 @@ static int record_composite_invoke(bContext *C, wmOperator *op, wmEvent *event)
                return OPERATOR_CANCELLED;
 
        rcd= op->customdata;
-       rcd->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.0f);
+       rcd->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.0f);
        WM_event_add_modal_handler(C, op);
 
        if(!record_composite_apply(C, op))
index ae496158a46472e6609a3bb0308b4752dbc76af8..12654bdac145b6a30c43171ad855b571ee44f7d7 100644 (file)
@@ -292,9 +292,9 @@ void smooth_view(bContext *C, Object *oldcamera, Object *camera, float *ofs, flo
                                rv3d->sms= MEM_mallocN(sizeof(struct SmoothViewStore), "smoothview v3d");
                        *rv3d->sms= sms;
                        if(rv3d->smooth_timer)
-                               WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
+                               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
                        /* TIMER1 is hardcoded in keymap */
-                       rv3d->smooth_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0);      /* max 30 frs/sec */
+                       rv3d->smooth_timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/30.0);  /* max 30 frs/sec */
                        
                        return;
                }
@@ -346,7 +346,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *op, wmEvent *event)
                MEM_freeN(rv3d->sms);
                rv3d->sms= NULL;
                
-               WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
                rv3d->smooth_timer= NULL;
        }
        else {
@@ -1798,7 +1798,7 @@ int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event)
 
        fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f;
 
-       fly->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
+       fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
 
 
        /* we have to rely on events to give proper mousecoords after a warp_pointer */
@@ -1867,7 +1867,7 @@ static int flyEnd(bContext *C, FlyInfo *fly)
        if(fly->state == FLY_RUNNING)
                return OPERATOR_RUNNING_MODAL;
 
-       WM_event_remove_window_timer(CTX_wm_window(C), fly->timer);
+       WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer);
 
        rv3d->dist= fly->dist_backup;
 
index c7258e616fa2fceb0adbc5474e5247d79abe675d..019ac33dfd0878188e96bda063f5a20607a16db9 100644 (file)
@@ -303,7 +303,7 @@ static void minimize_stretch_exit(bContext *C, wmOperator *op, int cancel)
        if(sa)
                ED_area_headerprint(sa, NULL);
        if(ms->timer)
-               WM_event_remove_window_timer(CTX_wm_window(C), ms->timer);
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ms->timer);
 
        if(cancel)
                param_flush_restore(ms->handle);
@@ -343,7 +343,7 @@ static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
        ms= op->customdata;
        WM_event_add_modal_handler(C, op);
-       ms->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
+       ms->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
 
        return OPERATOR_RUNNING_MODAL;
 }
index 43ab895b398ccda67434de0ee87a7f70985208b7..271c8d2a33eb910e684f7d4ba13ec49ab17a12ba 100644 (file)
@@ -47,6 +47,9 @@ typedef struct FileGlobal {
        struct Scene *curscene;
        int fileflags;
        int globalf;
+       
+       /* file path where this was saved, for recover */
+       char filename[240]; /* 240 = FILE_MAX */
 } FileGlobal;
 
 
index 7a024e35ff08b7a7525a39b8db617dc40ae7277b..5cdd74c826276bd413e85f34ea67cbcd91872511 100644 (file)
@@ -124,6 +124,9 @@ typedef struct wmWindowManager {
        ListBase keyconfigs;                            /* known key configurations */
        struct wmKeyConfig *defaultconf;        /* default configuration, not saved */
        int defaultactmap, pad2;                        /* active keymap from default for editing */
+
+       ListBase timers;                                        /* active timers */
+       struct wmTimer *autosavetimer;          /* timer for auto save */
 } wmWindowManager;
 
 /* wmWindowManager.initialized */
@@ -160,8 +163,6 @@ typedef struct wmWindow {
        int drawmethod, drawfail;       /* internal for wm_draw.c only */
        void *drawdata;                         /* internal for wm_draw.c only */
        
-       ListBase timers;
-       
        ListBase queue;                         /* all events (ghost level events were handled) */
        ListBase handlers;                      /* window+screen handlers, handled last */
        ListBase modalhandlers;         /* priority handlers, handled first */
index 1acf3c8effa81eec1aab323dd21fff4c75c30b94..f9192a9473e0d8374d90996cfa0ab60f47e7f5e4 100644 (file)
@@ -146,7 +146,11 @@ static void rna_UserDef_weight_color_update(bContext *C, PointerRNA *ptr)
        rna_userdef_update(C, ptr);
 }
 
-
+static void rna_userdef_autosave_update(bContext *C, PointerRNA *ptr)
+{
+       WM_autosave_init(C);
+       rna_userdef_update(C, ptr);
+}
 
 #else
 
@@ -2344,11 +2348,13 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
        prop= RNA_def_property(srna, "auto_save_temporary_files", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOSAVE);
        RNA_def_property_ui_text(prop, "Auto Save Temporary Files", "Automatic saving of temporary files.");
+       RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
 
        prop= RNA_def_property(srna, "auto_save_time", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "savetime");
        RNA_def_property_range(prop, 1, 60);
        RNA_def_property_ui_text(prop, "Auto Save Time", "The time (in minutes) to wait between automatic temporary saves.");
+       RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
 
        prop= RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE);
        RNA_def_property_range(prop, 0, 30);
index 2189412783ac203399f11ae67201ece6f815147d..e2e50b695fd1a521bd5df8639e882e81a50b4eda 100644 (file)
@@ -93,7 +93,6 @@ EnumPropertyItem event_timer_type_items[]= {
        {TIMER0, "TIMER0", 0, "Timer 0", ""},
        {TIMER1, "TIMER1", 0, "Timer 1", ""},
        {TIMER2, "TIMER2", 0, "Timer 2", ""},
-       {TIMERJOBS, "JOBS_TIMER", 0, "Jobs Timer", ""},
        {0, NULL, 0, NULL, NULL}};
 
 /* not returned: CAPSLOCKKEY, UNKNOWNKEY, GRLESSKEY */
@@ -229,7 +228,6 @@ EnumPropertyItem event_type_items[] = {
        {TIMER0, "TIMER0", 0, "Timer 0", ""},
        {TIMER1, "TIMER1", 0, "Timer 1", ""},
        {TIMER2, "TIMER2", 0, "Timer 2", ""},
-       {TIMERJOBS, "JOBS_TIMER", 0, "Jobs Timer", ""},
        {0, NULL, 0, NULL, NULL}};      
 
 #define KMI_TYPE_KEYBOARD      0
index 59f3bcd4edcab16ae2b5d984fea74be9bf1ee692..224338e557a10a2049d0e70045345c4bdbd3de27 100644 (file)
@@ -67,9 +67,9 @@ void          WM_window_open_temp     (struct bContext *C, struct rcti *position, int type);
 int                    WM_read_homefile        (struct bContext *C, struct wmOperator *op);
 int                    WM_write_homefile       (struct bContext *C, struct wmOperator *op);
 void           WM_read_file            (struct bContext *C, char *name, struct ReportList *reports);
-void           WM_write_file           (struct bContext *C, char *target, int compress, struct ReportList *reports);
+void           WM_write_file           (struct bContext *C, char *target, int fileflags, struct ReportList *reports);
 void           WM_read_autosavefile(struct bContext *C);
-void           WM_write_autosave       (struct bContext *C);
+void           WM_autosave_init        (struct bContext *C);
 
                        /* mouse cursors */
 void           WM_cursor_set           (struct wmWindow *win, int curs);
@@ -141,9 +141,9 @@ void                WM_main_add_notifier(unsigned int type, void *reference);
 void           wm_event_add            (struct wmWindow *win, struct wmEvent *event_to_add); /* XXX only for warning */
 
                        /* at maximum, every timestep seconds it triggers event_type events */
-struct wmTimer *WM_event_add_window_timer(struct wmWindow *win, int event_type, double timestep);
-void           WM_event_remove_window_timer(struct wmWindow *win, struct wmTimer *timer);
-void           WM_event_window_timer_sleep(struct wmWindow *win, struct wmTimer *timer, int dosleep);
+struct wmTimer *WM_event_add_timer(struct wmWindowManager *wm, struct wmWindow *win, int event_type, double timestep);
+void           WM_event_remove_timer(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer);
+void           WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer, int dosleep);
 
                /* operator api, default callbacks */
                        /* invoke callback, uses enum property named "type" */
index 31cb5ee083297486f3aaff838cf7083f6d00df91..0ef7e9670dccdb3ad269128520d569f0a69a8f72 100644 (file)
@@ -289,6 +289,9 @@ typedef struct wmTabletData {
 
 typedef struct wmTimer {
        struct wmTimer *next, *prev;
+       
+       struct wmWindow *win;   /* window this timer is attached to (optional) */
+
        double timestep;                /* 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 */
index f4baa42515ca9a1b15c474cace166abd96ae5005..1d173005d85e47ed9448432b276c0b179f033b63 100644 (file)
@@ -209,8 +209,10 @@ void wm_check(bContext *C)
        if(wm->windows.first==NULL) return;
 
        /* case: fileread */
-       if((wm->initialized & WM_INIT_WINDOW) == 0)
+       if((wm->initialized & WM_INIT_WINDOW) == 0) {
                WM_keymap_init(C);
+               WM_autosave_init(C);
+       }
        
        /* case: no open windows at all, for old file reads */
        wm_window_add_ghostwindows(wm);
@@ -269,12 +271,15 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
        wmWindow *win;
        wmOperator *op;
        wmKeyConfig *keyconf;
-       
+
+       if(wm->autosavetimer)
+               wm_autosave_timer_ended(wm);
+
        while((win= wm->windows.first)) {
                BLI_remlink(&wm->windows, win);
                win->screen= NULL; /* prevent draw clear to use screen */
                wm_draw_window_clear(win);
-               wm_window_free(C, win);
+               wm_window_free(C, wm, win);
        }
        
        while((op= wm->operators.first)) {
index 93ecd4076a3eb013d69c131b97e9c85d7a6b9767..e7c04141ad39b2c44db94ff36889d0c46acee2a6 100644 (file)
@@ -44,6 +44,8 @@
 
 #include "ED_screen.h"
 
+#include "GPU_extensions.h"
+
 #include "WM_api.h"
 #include "WM_types.h"
 #include "wm.h"
index 8eca0a1b416ba5ac93c586d0a9e7ad726e3fbcc0..f301a20a7c16a4197e80b726c31224b793794f86 100644 (file)
@@ -791,7 +791,7 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi)
 static int wm_event_always_pass(wmEvent *event)
 {
        /* some events we always pass on, to ensure proper communication */
-       return ELEM5(event->type, TIMER, TIMER0, TIMER1, TIMER2, TIMERJOBS);
+       return ELEM4(event->type, TIMER, TIMER0, TIMER1, TIMER2);
 }
 
 /* operator exists */
index ff0e69b74d40dde522874bdba02a238be68e7403..b2e55c8532e2291aa06969edf73f394b297bb850 100644 (file)
@@ -95,6 +95,7 @@
 #include "WM_types.h"
 #include "wm.h"
 #include "wm_window.h"
+#include "wm_event_system.h"
 
 static void writeBlog(void);
 
@@ -348,49 +349,6 @@ int WM_read_homefile(bContext *C, wmOperator *op)
 }
 
 
-static void get_autosave_location(char buf[FILE_MAXDIR+FILE_MAXFILE])
-{
-       char pidstr[32];
-#ifdef WIN32
-       char subdir[9];
-       char savedir[FILE_MAXDIR];
-#endif
-
-       sprintf(pidstr, "%d.blend", abs(getpid()));
-       
-#ifdef WIN32
-       if (!BLI_exists(U.tempdir)) {
-               BLI_strncpy(subdir, "autosave", sizeof(subdir));
-               BLI_make_file_string("/", savedir, BLI_gethome(), subdir);
-               
-               /* create a new autosave dir
-                * function already checks for existence or not */
-               BLI_recurdir_fileops(savedir);
-       
-               BLI_make_file_string("/", buf, savedir, pidstr);
-               return;
-       }
-#endif
-       
-       BLI_make_file_string("/", buf, U.tempdir, pidstr);
-}
-
-void WM_read_autosavefile(bContext *C)
-{
-       char tstr[FILE_MAX], scestr[FILE_MAX];
-       int save_over;
-
-       BLI_strncpy(scestr, G.sce, FILE_MAX);   /* temporal store */
-       
-       get_autosave_location(tstr);
-
-       save_over = G.save_over;
-       BKE_read_file(C, tstr, NULL, NULL);
-       G.save_over = save_over;
-       BLI_strncpy(G.sce, scestr, FILE_MAX);
-}
-
-
 void read_Blog(void)
 {
        char name[FILE_MAX];
@@ -496,10 +454,10 @@ static void do_history(char *name, ReportList *reports)
                BKE_report(reports, RPT_ERROR, "Unable to make version backup");
 }
 
-void WM_write_file(bContext *C, char *target, int compress, ReportList *reports)
+void WM_write_file(bContext *C, char *target, int fileflags, ReportList *reports)
 {
        Library *li;
-       int writeflags, len;
+       int len;
        char di[FILE_MAX];
        
        len = strlen(target);
@@ -537,20 +495,14 @@ void WM_write_file(bContext *C, char *target, int compress, ReportList *reports)
 
        do_history(di, reports);
        
-       writeflags= G.fileflags;
-
-       /* set compression flag */
-       if(compress) writeflags |= G_FILE_COMPRESS;
-       else writeflags &= ~G_FILE_COMPRESS;
-       
-       if (BLO_write_file(CTX_data_main(C), di, writeflags, reports)) {
+       if (BLO_write_file(CTX_data_main(C), di, fileflags, reports)) {
                strcpy(G.sce, di);
                G.relbase_valid = 1;
                strcpy(G.main->name, di);       /* is guaranteed current file */
 
                G.save_over = 1; /* disable untitled.blend convention */
 
-               if(compress) G.fileflags |= G_FILE_COMPRESS;
+               if(fileflags & G_FILE_COMPRESS) G.fileflags |= G_FILE_COMPRESS;
                else G.fileflags &= ~G_FILE_COMPRESS;
                
                writeBlog();
@@ -562,56 +514,125 @@ void WM_write_file(bContext *C, char *target, int compress, ReportList *reports)
 /* operator entry */
 int WM_write_homefile(bContext *C, wmOperator *op)
 {
+       wmWindowManager *wm= CTX_wm_manager(C);
        wmWindow *win= CTX_wm_window(C);
        char tstr[FILE_MAXDIR+FILE_MAXFILE];
-       int write_flags;
+       int fileflags;
        
        /* check current window and close it if temp */
-       if(win->screen->full == SCREENTEMP) {
-               wm_window_close(C, win);
-       }
+       if(win->screen->full == SCREENTEMP)
+               wm_window_close(C, wm, win);
        
        BLI_make_file_string("/", tstr, BLI_gethome(), ".B25.blend");
        
        /*  force save as regular blend file */
-       write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
+       fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
 
-       BLO_write_file(CTX_data_main(C), tstr, write_flags, op->reports);
+       BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports);
        
        G.save_over= 0;
        
        return OPERATOR_FINISHED;
 }
 
-void WM_write_autosave(bContext *C)
+/************************ autosave ****************************/
+
+void wm_autosave_location(char *filename)
 {
-       char tstr[FILE_MAXDIR+FILE_MAXFILE];
-       int write_flags;
+       char pidstr[32];
+#ifdef WIN32
+       char subdir[9];
+       char savedir[FILE_MAXDIR];
+#endif
+
+       sprintf(pidstr, "%d.blend", abs(getpid()));
+       
+#ifdef WIN32
+       if (!BLI_exists(U.tempdir)) {
+               BLI_strncpy(subdir, "autosave", sizeof(subdir));
+               BLI_make_file_string("/", savedir, BLI_gethome(), subdir);
+               
+               /* create a new autosave dir
+                * function already checks for existence or not */
+               BLI_recurdir_fileops(savedir);
+       
+               BLI_make_file_string("/", filename, savedir, pidstr);
+               return;
+       }
+#endif
        
-       get_autosave_location(tstr);
+       BLI_make_file_string("/", filename, U.tempdir, pidstr);
+}
 
-               /*  force save as regular blend file */
-       write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
+void WM_autosave_init(bContext *C)
+{
+       wmWindowManager *wm= CTX_wm_manager(C);
+       wm_autosave_timer_ended(wm);
 
-               /* error reporting to console */
-       BLO_write_file(CTX_data_main(C), tstr, write_flags, NULL);
+       if(U.flag & USER_AUTOSAVE)
+               wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime*60.0);
 }
 
-/* if global undo; remove tempsave, otherwise rename */
-void delete_autosave(void)
+void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
 {
-       char tstr[FILE_MAXDIR+FILE_MAXFILE];
+       wmWindow *win;
+       wmEventHandler *handler;
+       char filename[FILE_MAX];
+       int fileflags;
+
+       WM_event_remove_timer(wm, NULL, wm->autosavetimer);
+
+       /* if a modal operator is running, don't autosave, but try again in 10 seconds */
+       for(win=wm->windows.first; win; win=win->next) {
+               for(handler=win->modalhandlers.first; handler; handler=handler->next) {
+                       if(handler->op) {
+                               wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, 10.0);
+                               return;
+                       }
+               }
+       }
        
-       get_autosave_location(tstr);
+       wm_autosave_location(filename);
+
+       /*  force save as regular blend file */
+       fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_LOCK|G_FILE_SIGN);
+
+       /* no error reporting to console */
+       BLO_write_file(CTX_data_main(C), filename, fileflags, NULL);
 
-       if (BLI_exists(tstr)) {
+       /* do timer after file write, just in case file write takes a long time */
+       wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime*60.0);
+}
+
+void wm_autosave_timer_ended(wmWindowManager *wm)
+{
+       if(wm->autosavetimer) {
+               WM_event_remove_timer(wm, NULL, wm->autosavetimer);
+               wm->autosavetimer= NULL;
+       }
+}
+
+void wm_autosave_delete(void)
+{
+       char filename[FILE_MAX];
+       
+       wm_autosave_location(filename);
+
+       if(BLI_exists(filename)) {
                char str[FILE_MAXDIR+FILE_MAXFILE];
                BLI_make_file_string("/", str, U.tempdir, "quit.blend");
 
-               if(U.uiflag & USER_GLOBALUNDO) BLI_delete(tstr, 0, 0);
-               else BLI_rename(tstr, str);
+               /* if global undo; remove tempsave, otherwise rename */
+               if(U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, 0, 0);
+               else BLI_rename(filename, str);
        }
 }
 
-/***/
+void wm_autosave_read(bContext *C, ReportList *reports)
+{
+       char filename[FILE_MAX];
+
+       wm_autosave_location(filename);
+       WM_read_file(C, filename, reports);
+}
 
index 2e456669cb1fdc73497984107a525579caebc3aa..8097822acbcab16c0e404c662596b23aed5fe6bb 100644 (file)
@@ -283,7 +283,7 @@ void WM_exit(bContext *C)
                printf("Error Totblock: %d\n", MEM_get_memory_blocks_in_use());
                MEM_printmemlist();
        }
-//     delete_autosave();
+       wm_autosave_delete();
        
        printf("\nBlender quit\n");
        
index 498306484e9ae3b7202aca96032a6107e97d800b..c2ecf0c59e7f080bfeb912074b31c277d982a137 100644 (file)
@@ -255,7 +255,7 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *steve)
                        
                        /* restarted job has timer already */
                        if(steve->wt==NULL)
-                               steve->wt= WM_event_add_window_timer(steve->win, TIMERJOBS, steve->timestep);
+                               steve->wt= WM_event_add_timer(wm, steve->win, TIMERJOBS, steve->timestep);
                }
                else printf("job fails, not initialized\n");
        }
@@ -271,7 +271,7 @@ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *steve)
        }
        
        if(steve->wt)
-               WM_event_remove_window_timer(steve->win, steve->wt);
+               WM_event_remove_timer(wm, steve->win, steve->wt);
        if(steve->customdata)
                steve->free(steve->customdata);
        if(steve->run_customdata)
@@ -317,14 +317,13 @@ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt)
 }
 
 /* hardcoded to event TIMERJOBS */
-static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
+void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
 {
-       wmWindowManager *wm= CTX_wm_manager(C);
        wmJob *steve= wm->jobs.first;
        
        for(; steve; steve= steve->next) {
                
-               if(evt->customdata==steve->wt) {
+               if(steve->wt==wt) {
                        
                        /* running threads */
                        if(steve->threads.first) {
@@ -358,7 +357,7 @@ static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
                                                WM_jobs_start(wm, steve);
                                        }
                                        else {
-                                               WM_event_remove_window_timer(steve->win, steve->wt);
+                                               WM_event_remove_timer(wm, steve->win, steve->wt);
                                                steve->wt= NULL;
                                                
                                                /* remove steve */
@@ -370,23 +369,7 @@ static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
                        else if(steve->suspended) {
                                WM_jobs_start(wm, steve);
                        }
-                       
-                       return OPERATOR_FINISHED;
                }
        }
-       return OPERATOR_PASS_THROUGH;
 }
 
-void WM_OT_jobs_timer(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Jobs timer";
-       ot->idname= "WM_OT_jobs_timer";
-       ot->description="Jobs timer operator.";
-       
-       /* api callbacks */
-       ot->invoke= wm_jobs_timer;
-       
-       ot->poll= ED_operator_screenactive;
-       
-}
index cc5967ab23a5d0c8123de7d2aa21bb95e7574895..7a97ebf0de7ccc8726608b2e853c2da4b16ff4f3 100644 (file)
@@ -972,7 +972,7 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op)
 
        WM_read_file(C, path, op->reports);
        
-       return 0;
+       return OPERATOR_FINISHED;
 }
 
 static void WM_OT_open_mainfile(wmOperatorType *ot)
@@ -1154,12 +1154,9 @@ static void WM_OT_link_append(wmOperatorType *ot)
 
 static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
 {
-       char scestr[FILE_MAX], filename[FILE_MAX];
-       int save_over;
+       char filename[FILE_MAX];
 
-       /* back up some values */
-       BLI_strncpy(scestr, G.sce, sizeof(scestr));
-       save_over = G.save_over;
+       G.fileflags |= G_FILE_RECOVER;
 
        // XXX wm in context is not set correctly after WM_read_file -> crash
        // do it before for now, but is this correct with multiple windows?
@@ -1169,11 +1166,9 @@ static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
        BLI_make_file_string("/", filename, btempdir, "quit.blend");
        WM_read_file(C, filename, op->reports);
 
-       /* restore */
-       G.save_over = save_over;
-       BLI_strncpy(G.sce, scestr, sizeof(G.sce));
+       G.fileflags &= ~G_FILE_RECOVER;
 
-       return 0;
+       return OPERATOR_FINISHED;
 }
 
 static void WM_OT_recover_last_session(wmOperatorType *ot)
@@ -1186,6 +1181,52 @@ static void WM_OT_recover_last_session(wmOperatorType *ot)
        ot->poll= WM_operator_winactive;
 }
 
+/* *************** recover auto save **************** */
+
+static int wm_recover_auto_save_exec(bContext *C, wmOperator *op)
+{
+       char path[FILE_MAX];
+
+       RNA_string_get(op->ptr, "path", path);
+
+       G.fileflags |= G_FILE_RECOVER;
+
+       // XXX wm in context is not set correctly after WM_read_file -> crash
+       // do it before for now, but is this correct with multiple windows?
+       WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+       /* load file */
+       WM_read_file(C, path, op->reports);
+
+       G.fileflags &= ~G_FILE_RECOVER;
+
+       return OPERATOR_FINISHED;
+}
+
+static int wm_recover_auto_save_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       char filename[FILE_MAX];
+
+       wm_autosave_location(filename);
+       RNA_string_set(op->ptr, "path", filename);
+       WM_event_add_fileselect(C, op);
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static void WM_OT_recover_auto_save(wmOperatorType *ot)
+{
+       ot->name= "Recover Auto Save";
+       ot->idname= "WM_OT_recover_auto_save";
+       ot->description="Open an automatically saved file to recover it.";
+       
+       ot->exec= wm_recover_auto_save_exec;
+       ot->invoke= wm_recover_auto_save_invoke;
+       ot->poll= WM_operator_winactive;
+
+       WM_operator_properties_filesel(ot, BLENDERFILE, FILE_BLENDER);
+}
+
 /* *************** save file as **************** */
 
 static void untitled(char *name)
@@ -1229,10 +1270,9 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *even
 static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
 {
        char path[FILE_MAX];
-       int compress;
+       int fileflags;
 
        save_set_compress(op);
-       compress= RNA_boolean_get(op->ptr, "compress");
        
        if(RNA_property_is_set(op->ptr, "path"))
                RNA_string_get(op->ptr, "path", path);
@@ -1241,7 +1281,15 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
                untitled(path);
        }
 
-       WM_write_file(C, path, compress, op->reports);
+       fileflags= G.fileflags;
+
+       /* set compression flag */
+       if(RNA_boolean_get(op->ptr, "compress"))
+               fileflags |= G_FILE_COMPRESS;
+       else
+               fileflags &= ~G_FILE_COMPRESS;
+
+       WM_write_file(C, path, fileflags, op->reports);
        
        WM_event_add_notifier(C, NC_WM|ND_FILESAVE, NULL);
 
@@ -2173,7 +2221,7 @@ void wm_operatortype_init(void)
        WM_operatortype_append(WM_OT_open_mainfile);
        WM_operatortype_append(WM_OT_link_append);
        WM_operatortype_append(WM_OT_recover_last_session);
-       WM_operatortype_append(WM_OT_jobs_timer);
+       WM_operatortype_append(WM_OT_recover_auto_save);
        WM_operatortype_append(WM_OT_save_as_mainfile);
        WM_operatortype_append(WM_OT_save_mainfile);
        WM_operatortype_append(WM_OT_redraw_timer);
@@ -2188,9 +2236,6 @@ void wm_window_keymap(wmKeyConfig *keyconf)
        wmKeyMap *keymap= WM_keymap_find(keyconf, "Window", 0, 0);
        wmKeyMapItem *km;
        
-       /* items to make WM work */
-       WM_keymap_verify_item(keymap, "WM_OT_jobs_timer", TIMERJOBS, KM_ANY, KM_ANY, 0);
-       
        /* note, this doesn't replace existing keymap items */
        WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", WKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
        #ifdef __APPLE__
index f7116a2bd1f4c41dc98603f03e4800f74d009ec2..70d40df453274e896d13052f13c70390e6017bd1 100644 (file)
@@ -130,37 +130,39 @@ static void wm_ghostwindow_destroy(wmWindow *win)
 
 /* including window itself, C can be NULL. 
    ED_screen_exit should have been called */
-void wm_window_free(bContext *C, wmWindow *win)
+void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
 {
        wmTimer *wt, *wtnext;
        
        /* update context */
        if(C) {
-               wmWindowManager *wm= CTX_wm_manager(C);
-
-               if(wm->windrawable==win)
-                       wm->windrawable= NULL;
-               if(wm->winactive==win)
-                       wm->winactive= NULL;
-               if(CTX_wm_window(C)==win)
-                       CTX_wm_window_set(C, NULL);
-               
                WM_event_remove_handlers(C, &win->handlers);
                WM_event_remove_handlers(C, &win->modalhandlers);
 
-               /* end running jobs, a job end also removes its timer */
-               for(wt= win->timers.first; wt; wt= wtnext) {
-                       wtnext= wt->next;
-                       if(wt->event_type==TIMERJOBS)
-                               wm_jobs_timer_ended(wm, wt);
-               }
+               if(CTX_wm_window(C)==win)
+                       CTX_wm_window_set(C, NULL);
        }       
-       
-       if(win->eventstate) MEM_freeN(win->eventstate);
+
+       if(wm->windrawable==win)
+               wm->windrawable= NULL;
+       if(wm->winactive==win)
+               wm->winactive= NULL;
+
+       /* end running jobs, a job end also removes its timer */
+       for(wt= wm->timers.first; wt; wt= wtnext) {
+               wtnext= wt->next;
+               if(wt->win==win && wt->event_type==TIMERJOBS)
+                       wm_jobs_timer_ended(wm, wt);
+       }
        
        /* timer removing, need to call this api function */
-       while((wt= win->timers.first))
-               WM_event_remove_window_timer(win, wt);
+       for(wt= wm->timers.first; wt; wt=wtnext) {
+               wtnext= wt->next;
+               if(wt->win==win)
+                       WM_event_remove_timer(wm, win, wt);
+       }
+
+       if(win->eventstate) MEM_freeN(win->eventstate);
        
        wm_event_free_all(win);
        wm_subwindows_free(win);
@@ -223,14 +225,13 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
 }
 
 /* this is event from ghost, or exit-blender op */
-void wm_window_close(bContext *C, wmWindow *win)
+void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
 {
-       wmWindowManager *wm= CTX_wm_manager(C);
        BLI_remlink(&wm->windows, win);
        
        wm_draw_window_clear(win);
        ED_screen_exit(C, win, win->screen);
-       wm_window_free(C, win);
+       wm_window_free(C, wm, win);
        
        /* check remaining windows */
        if(wm->windows.first) {
@@ -544,6 +545,7 @@ void wm_window_make_drawable(bContext *C, wmWindow *win)
 static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) 
 {
        bContext *C= private;
+       wmWindowManager *wm= CTX_wm_manager(C);
        GHOST_TEventType type= GHOST_GetEventType(evt);
        
        if (type == GHOST_kEventQuit) {
@@ -576,7 +578,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
                                GHOST_TEventKeyData kdata;
                                int cx, cy, wx, wy;
                                
-                               CTX_wm_manager(C)->winactive= win; /* no context change! c->wm->windrawable is drawable, or for area queues */
+                               wm->winactive= win; /* no context change! c->wm->windrawable is drawable, or for area queues */
                                
                                win->active= 1;
 //                             window_handle(win, INPUTCHANGE, win->active);
@@ -619,7 +621,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
                                break;
                        }
                        case GHOST_kEventWindowClose: {
-                               wm_window_close(C, win);
+                               wm_window_close(C, wm, win);
                                break;
                        }
                        case GHOST_kEventWindowUpdate: {
@@ -719,22 +721,29 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
 static int wm_window_timer(const bContext *C)
 {
        wmWindowManager *wm= CTX_wm_manager(C);
+       wmTimer *wt, *wtnext;
        wmWindow *win;
        double time= PIL_check_seconds_timer();
        int retval= 0;
        
-       for(win= wm->windows.first; win; win= win->next) {
-               wmTimer *wt;
-               for(wt= win->timers.first; wt; wt= wt->next) {
-                       if(wt->sleep==0) {
-                               if(time > wt->ntime) {
+       for(wt= wm->timers.first; wt; wt= wtnext) {
+               wtnext= wt->next; /* in case timer gets removed */
+               win= wt->win;
+
+               if(wt->sleep==0) {
+                       if(time > wt->ntime) {
+                               wt->delta= time - wt->ltime;
+                               wt->duration += wt->delta;
+                               wt->ltime= time;
+                               wt->ntime= wt->stime + wt->timestep*ceil(wt->duration/wt->timestep);
+
+                               if(wt->event_type == TIMERJOBS)
+                                       wm_jobs_timer(C, wm, wt);
+                               else if(wt->event_type == TIMERAUTOSAVE)
+                                       wm_autosave_timer(C, wm, wt);
+                               else if(win) {
                                        wmEvent event= *(win->eventstate);
                                        
-                                       wt->delta= time - wt->ltime;
-                                       wt->duration += wt->delta;
-                                       wt->ltime= time;
-                                       wt->ntime= wt->stime + wt->timestep*ceil(wt->duration/wt->timestep);
-                                       
                                        event.type= wt->event_type;
                                        event.custom= EVT_DATA_TIMER;
                                        event.customdata= wt;
@@ -810,19 +819,19 @@ void wm_ghost_exit(void)
 /* **************** timer ********************** */
 
 /* to (de)activate running timers temporary */
-void WM_event_window_timer_sleep(wmWindow *win, wmTimer *timer, int dosleep)
+void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *win, wmTimer *timer, int dosleep)
 {
        wmTimer *wt;
        
-       for(wt= win->timers.first; wt; wt= wt->next)
+       for(wt= wm->timers.first; wt; wt= wt->next)
                if(wt==timer)
                        break;
-       if(wt) {
+
+       if(wt)
                wt->sleep= dosleep;
-       }               
 }
 
-wmTimer *WM_event_add_window_timer(wmWindow *win, int event_type, double timestep)
+wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
 {
        wmTimer *wt= MEM_callocN(sizeof(wmTimer), "window timer");
        
@@ -831,23 +840,24 @@ wmTimer *WM_event_add_window_timer(wmWindow *win, int event_type, double timeste
        wt->ntime= wt->ltime + timestep;
        wt->stime= wt->ltime;
        wt->timestep= timestep;
+       wt->win= win;
        
-       BLI_addtail(&win->timers, wt);
+       BLI_addtail(&wm->timers, wt);
        
        return wt;
 }
 
-void WM_event_remove_window_timer(wmWindow *win, wmTimer *timer)
+void WM_event_remove_timer(wmWindowManager *wm, wmWindow *win, wmTimer *timer)
 {
        wmTimer *wt;
        
        /* extra security check */
-       for(wt= win->timers.first; wt; wt= wt->next)
+       for(wt= wm->timers.first; wt; wt= wt->next)
                if(wt==timer)
                        break;
        if(wt) {
                
-               BLI_remlink(&win->timers, wt);
+               BLI_remlink(&wm->timers, wt);
                if(wt->customdata)
                        MEM_freeN(wt->customdata);
                MEM_freeN(wt);
index 832558b961f78dc35140b57a52daf039b6edc5c9..609b614264076f5e7daf2f619dee4882fef0052d 100644 (file)
@@ -29,6 +29,7 @@
 #define WM_H
 
 struct wmWindow;
+struct ReportList;
 
 typedef struct wmPaintCursor {
        struct wmPaintCursor *next, *prev;
@@ -64,9 +65,16 @@ void wm_gesture_draw(struct wmWindow *win);
 int wm_gesture_evaluate(bContext *C, wmGesture *gesture);
 void wm_gesture_tag_redraw(bContext *C);
 
-/* wm_jobs.h */
-void WM_OT_jobs_timer(struct wmOperatorType *ot);
+/* wm_jobs.c */
+void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt);
 void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt);
 
+/* wm_files.c */
+void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt);
+void wm_autosave_timer_ended(wmWindowManager *wm);
+void wm_autosave_delete(void);
+void wm_autosave_read(bContext *C, struct ReportList *reports);
+void wm_autosave_location(char *filename);
+
 #endif /* WM_H */
 
index b33c4bd14e815c6bb856bfbad7a8d67d6ccfe04a..c7588795a15b39df45cf896143d5469b09062745 100644 (file)
@@ -75,6 +75,7 @@
 #define TIMER1                 0x0112  /* timer event, slot for internal use */
 #define TIMER2                 0x0113  /* timer event, slot for internal use */
 #define TIMERJOBS              0x0114  /* timer event, internal use */
+#define TIMERAUTOSAVE  0x0115  /* timer event, internal use */
 
 /* standard keyboard */
 #define AKEY           'a'
 #define ISMOUSE(event) (event >= LEFTMOUSE && event <= WHEELOUTMOUSE)
 
        /* test wether the event is timer event */
-#define ISTIMER(event) (event >= TIMER && event <= TIMERJOBS)
+#define ISTIMER(event) (event >= TIMER && event <= TIMERAUTOSAVE)
 
        /* test wether the event is tweak event */
 #define ISTWEAK(event) (event >= EVT_TWEAK_L && event <= EVT_GESTURE)
index 44c31e7cb691f7ffa1bf2a6291fd26e810bee392..f0a2c0ec9a99873c68234b8e8121737e834e4576 100644 (file)
@@ -36,8 +36,8 @@ void          wm_ghost_init                   (bContext *C);
 void           wm_ghost_exit(void);
 
 wmWindow       *wm_window_new                  (bContext *C);
-void           wm_window_free                  (bContext *C, wmWindow *win);
-void           wm_window_close                 (bContext *C, wmWindow *win);
+void           wm_window_free                  (bContext *C, wmWindowManager *wm, wmWindow *win);
+void           wm_window_close                 (bContext *C, wmWindowManager *wm, wmWindow *win);
 
 void           wm_window_title                         (wmWindowManager *wm, wmWindow *win);
 void           wm_window_add_ghostwindows      (wmWindowManager *wm);