diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_files.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 208 |
1 files changed, 167 insertions, 41 deletions
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 2ab6f78daa5..8a05e6c4916 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1,5 +1,5 @@ /** - * $Id: wm_files.c + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -30,6 +30,7 @@ */ #include <stdio.h> #include <string.h> +#include <errno.h> #ifdef WIN32 #include <windows.h> /* need to include windows.h so _WIN32_IE is defined */ @@ -60,6 +61,7 @@ #include "BKE_blender.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_exotic.h" #include "BKE_font.h" @@ -76,12 +78,16 @@ #include "BLO_writefile.h" #include "RNA_access.h" -#include "RNA_define.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_thumbs.h" #include "ED_datafiles.h" #include "ED_object.h" #include "ED_screen.h" #include "ED_sculpt.h" +#include "ED_view3d.h" #include "ED_util.h" #include "GHOST_C-api.h" @@ -98,7 +104,7 @@ #include "wm_window.h" #include "wm_event_system.h" -static void writeBlog(void); +static void write_history(void); /* To be able to read files without windows closing, opening, moving we try to prepare for worst case: @@ -216,7 +222,9 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) if(win->active) wm->winactive= win; - GHOST_SetWindowUserData(win->ghostwin, win); /* pointer back */ + if(!G.background) /* file loading in background mode still calls this */ + GHOST_SetWindowUserData(win->ghostwin, win); /* pointer back */ + oldwin->ghostwin= NULL; win->eventstate= oldwin->eventstate; @@ -238,19 +246,26 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) /* in case UserDef was read, we re-initialize all, and do versioning */ static void wm_init_userdef(bContext *C) { + extern char btempdir[]; + UI_init_userdef(); MEM_CacheLimiter_set_maximum(U.memcachelimit * 1024 * 1024); sound_init(CTX_data_main(C)); /* set the python auto-execute setting from user prefs */ - if (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) G.f &= ~G_SCRIPT_AUTOEXEC; - else G.f |= G_SCRIPT_AUTOEXEC; + /* disabled by default, unless explicitly enabled in the command line */ + if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) G.f |= G_SCRIPT_AUTOEXEC; + + if(U.tempdir[0]) strncpy(btempdir, U.tempdir, FILE_MAXDIR+FILE_MAXFILE); } void WM_read_file(bContext *C, char *name, ReportList *reports) { int retval; + /* so we can get the error message */ + errno = 0; + /* first try to append data from exotic file formats... */ /* it throws error box when file doesnt exist and returns -1 */ /* note; it should set some error message somewhere... (ton) */ @@ -258,6 +273,7 @@ void WM_read_file(bContext *C, char *name, ReportList *reports) /* we didn't succeed, now try to read Blender file */ if (retval== 0) { + int G_f= G.f; ListBase wmbase; /* put aside screens to match with persistant windows later */ @@ -267,6 +283,11 @@ void WM_read_file(bContext *C, char *name, ReportList *reports) retval= BKE_read_file(C, name, NULL, reports); G.save_over = 1; + /* this flag is initialized by the operator but overwritten on read. + * need to re-enable it here else drivers + registered scripts wont work. */ + if(G_f & G_SCRIPT_AUTOEXEC) G.f |= G_SCRIPT_AUTOEXEC; + else G.f &= ~G_SCRIPT_AUTOEXEC; + /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ @@ -277,7 +298,8 @@ void WM_read_file(bContext *C, char *name, ReportList *reports) if (retval!=0) { G.relbase_valid = 1; - writeBlog(); + if(!G.background) /* assume automated tasks with background, dont write recent file list */ + write_history(); } // XXX undo_editmode_clear(); @@ -287,17 +309,22 @@ void WM_read_file(bContext *C, char *name, ReportList *reports) WM_event_add_notifier(C, NC_WM|ND_FILEREAD, NULL); // refresh_interface_font(); - CTX_wm_window_set(C, NULL); /* exits queues */ + CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); + + ED_editors_init(C); + DAG_on_load_update(); + #ifndef DISABLE_PYTHON /* run any texts that were loaded in and flagged as modules */ BPY_load_user_modules(C); #endif + CTX_wm_window_set(C, NULL); /* exits queues */ } else if(retval==1) BKE_write_undo(C, "Import file"); else if(retval == -1) { if(reports) - BKE_reportf(reports, RPT_ERROR, "Can't read file \"%s\".", name); + BKE_reportf(reports, RPT_ERROR, "Can't read file: \"%s\", %s.", name, errno ? strerror(errno) : "Incompatible file format"); } } @@ -309,17 +336,23 @@ int WM_read_homefile(bContext *C, wmOperator *op) { ListBase wmbase; char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR]; - char *home= BLI_gethome(); int from_memory= op?RNA_boolean_get(op->ptr, "factory"):0; int success; - - BLI_clean(home); free_ttfont(); /* still weird... what does it here? */ G.relbase_valid = 0; if (!from_memory) { - BLI_make_file_string(G.sce, tstr, home, ".B25.blend"); + char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); + if (cfgdir) { + BLI_make_file_string(G.sce, tstr, cfgdir, BLENDER_STARTUP_FILE); + } else { + tstr[0] = '\0'; + from_memory = 1; + if (op) { + BKE_report(op->reports, RPT_INFO, "Config directory with startup.blend file found."); + } + } } strcpy(scestr, G.sce); /* temporary store */ @@ -332,7 +365,7 @@ int WM_read_homefile(bContext *C, wmOperator *op) if (!from_memory && BLI_exists(tstr)) { success = BKE_read_file(C, tstr, NULL, NULL); } else { - success = BKE_read_file_from_memory(C, datatoc_B_blend, datatoc_B_blend_size, NULL, NULL); + success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, NULL); if (wmbase.first == NULL) wm_clear_default_size(C); } @@ -357,6 +390,9 @@ int WM_read_homefile(bContext *C, wmOperator *op) // undo_editmode_clear(); BKE_reset_undo(); BKE_write_undo(C, "original"); /* save current state */ + + ED_editors_init(C); + DAG_on_load_update(); WM_event_add_notifier(C, NC_WM|ND_FILEREAD, NULL); CTX_wm_window_set(C, NULL); /* exits queues */ @@ -365,15 +401,19 @@ int WM_read_homefile(bContext *C, wmOperator *op) } -void read_Blog(void) +void read_history(void) { char name[FILE_MAX]; LinkNode *l, *lines; struct RecentFile *recent; char *line; int num; + char *cfgdir = BLI_get_folder(BLENDER_CONFIG, NULL); + + if (!cfgdir) return; + + BLI_make_file_string("/", name, cfgdir, BLENDER_HISTORY_FILE); - BLI_make_file_string("/", name, BLI_gethome(), ".Blog"); lines= BLI_read_file_as_lines(name); G.recent_files.first = G.recent_files.last = NULL; @@ -387,10 +427,10 @@ void read_Blog(void) recent = (RecentFile*)MEM_mallocN(sizeof(RecentFile),"RecentFile"); BLI_addtail(&(G.recent_files), recent); - recent->filename = (char*)MEM_mallocN(sizeof(char)*(strlen(line)+1), "name of file"); - recent->filename[0] = '\0'; + recent->filepath = (char*)MEM_mallocN(sizeof(char)*(strlen(line)+1), "name of file"); + recent->filepath[0] = '\0'; - strcpy(recent->filename, line); + strcpy(recent->filepath, line); num++; } } @@ -402,40 +442,40 @@ void read_Blog(void) } -static void writeBlog(void) +static void write_history(void) { struct RecentFile *recent, *next_recent; char name[FILE_MAXDIR+FILE_MAXFILE]; FILE *fp; int i; - BLI_make_file_string("/", name, BLI_gethome(), ".Blog"); + BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_HISTORY_FILE); recent = G.recent_files.first; /* refresh .Blog of recent opened files, when current file was changed */ - if(!(recent) || (strcmp(recent->filename, G.sce)!=0)) { + if(!(recent) || (strcmp(recent->filepath, G.sce)!=0)) { fp= fopen(name, "w"); if (fp) { /* add current file to the beginning of list */ recent = (RecentFile*)MEM_mallocN(sizeof(RecentFile),"RecentFile"); - recent->filename = (char*)MEM_mallocN(sizeof(char)*(strlen(G.sce)+1), "name of file"); - recent->filename[0] = '\0'; - strcpy(recent->filename, G.sce); + recent->filepath = (char*)MEM_mallocN(sizeof(char)*(strlen(G.sce)+1), "name of file"); + recent->filepath[0] = '\0'; + strcpy(recent->filepath, G.sce); BLI_addhead(&(G.recent_files), recent); /* write current file to .Blog */ - fprintf(fp, "%s\n", recent->filename); + fprintf(fp, "%s\n", recent->filepath); recent = recent->next; i=1; /* write rest of recent opened files to .Blog */ while((i<U.recent_files) && (recent)){ /* this prevents to have duplicities in list */ - if (strcmp(recent->filename, G.sce)!=0) { - fprintf(fp, "%s\n", recent->filename); + if (strcmp(recent->filepath, G.sce)!=0) { + fprintf(fp, "%s\n", recent->filepath); recent = recent->next; } else { next_recent = recent->next; - MEM_freeN(recent->filename); + MEM_freeN(recent->filepath); BLI_freelinkN(&(G.recent_files), recent); recent = next_recent; } @@ -471,25 +511,90 @@ 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 fileflags, ReportList *reports) +static ImBuf *blend_file_thumb(const char *path, Scene *scene, int **thumb_pt) +{ + /* will be scaled down, but gives some nice oversampling */ + ImBuf *ibuf; + int *thumb; + + *thumb_pt= NULL; + + if(G.background || scene->camera==NULL) + return NULL; + + /* gets scaled to BLEN_THUMB_SIZE */ + ibuf= ED_view3d_draw_offscreen_imbuf_simple(scene, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, OB_SOLID); + + if(ibuf) { + float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp); + + /* dirty oversampling */ + IMB_scaleImBuf(ibuf, BLEN_THUMB_SIZE, BLEN_THUMB_SIZE); + + /* add pretty overlay */ + IMB_overlayblend_thumb(ibuf->rect, ibuf->x, ibuf->y, aspect); + + /* first write into thumb buffer */ + thumb= MEM_mallocN(((2 + (BLEN_THUMB_SIZE * BLEN_THUMB_SIZE))) * sizeof(int), "write_file thumb"); + + thumb[0] = BLEN_THUMB_SIZE; + thumb[1] = BLEN_THUMB_SIZE; + + memcpy(thumb + 2, ibuf->rect, BLEN_THUMB_SIZE * BLEN_THUMB_SIZE * sizeof(int)); + } + else { + /* '*thumb_pt' needs to stay NULL to prevent a bad thumbnail from being handled */ + thumb= NULL; + } + + /* must be freed by caller */ + *thumb_pt= thumb; + + return ibuf; +} + +/* easy access from gdb */ +int write_crash_blend(void) +{ + char path[FILE_MAX]; + BLI_strncpy(path, G.sce, sizeof(path)); + BLI_replace_extension(path, sizeof(path), "_crash.blend"); + if(BLO_write_file(G.main, path, G.fileflags, NULL, NULL)) { + printf("written: %s\n", path); + return 1; + } + else { + printf("failed: %s\n", path); + return 0; + } +} + +int WM_write_file(bContext *C, char *target, int fileflags, ReportList *reports) { Library *li; int len; char di[FILE_MAX]; - + + int *thumb= NULL; + ImBuf *ibuf_thumb= NULL; + len = strlen(target); - if (len == 0) return; + if (len == 0) { + BKE_report(reports, RPT_ERROR, "Path is empty, cannot save"); + return -1; + } + if (len >= FILE_MAX) { BKE_report(reports, RPT_ERROR, "Path too long, cannot save"); - return; + return -1; } /* send the OnSave event */ for (li= G.main->library.first; li; li= li->id.next) { if (BLI_streq(li->name, target)) { BKE_report(reports, RPT_ERROR, "Cannot overwrite used library"); - return; + return -1; } } @@ -513,7 +618,10 @@ void WM_write_file(bContext *C, char *target, int fileflags, ReportList *reports do_history(di, reports); - if (BLO_write_file(CTX_data_main(C), di, fileflags, reports)) { + /* blend file thumbnail */ + ibuf_thumb= blend_file_thumb(di, CTX_data_scene(C), &thumb); + + if (BLO_write_file(CTX_data_main(C), di, fileflags, reports, thumb)) { strcpy(G.sce, di); G.relbase_valid = 1; strcpy(G.main->name, di); /* is guaranteed current file */ @@ -523,10 +631,27 @@ void WM_write_file(bContext *C, char *target, int fileflags, ReportList *reports if(fileflags & G_FILE_COMPRESS) G.fileflags |= G_FILE_COMPRESS; else G.fileflags &= ~G_FILE_COMPRESS; - writeBlog(); + if(fileflags & G_FILE_AUTOPLAY) G.fileflags |= G_FILE_AUTOPLAY; + else G.fileflags &= ~G_FILE_AUTOPLAY; + + write_history(); + + /* run this function after because the file cant be written before the blend is */ + if (ibuf_thumb) { + ibuf_thumb= IMB_thumb_create(di, THB_NORMAL, THB_SOURCE_BLEND, ibuf_thumb); + IMB_freeImBuf(ibuf_thumb); + } + + if(thumb) MEM_freeN(thumb); + } + else { + if(ibuf_thumb) IMB_freeImBuf(ibuf_thumb); + if(thumb) MEM_freeN(thumb); + return -1; } // XXX waitcursor(0); + return 0; } /* operator entry */ @@ -541,12 +666,13 @@ int WM_write_homefile(bContext *C, wmOperator *op) if(win->screen->full == SCREENTEMP) wm_window_close(C, wm, win); - BLI_make_file_string("/", tstr, BLI_gethome(), ".B25.blend"); + BLI_make_file_string("/", tstr, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); + printf("trying to save homefile at %s \n", tstr); /* force save as regular blend file */ - fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN); + fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN); - BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports); + BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports, NULL); G.save_over= 0; @@ -612,10 +738,10 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt) wm_autosave_location(filename); /* force save as regular blend file */ - fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_LOCK|G_FILE_SIGN); + fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN); /* no error reporting to console */ - BLO_write_file(CTX_data_main(C), filename, fileflags, NULL); + BLO_write_file(CTX_data_main(C), filename, fileflags, NULL, NULL); /* 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); |