diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-11-07 08:13:03 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-11-07 08:13:03 +0400 |
commit | 8740b6cd88b9dada05a2e49b23e2ced6c184044a (patch) | |
tree | 6883a6d9e573f32c50f28c9ca3110479ccc7a613 /source/blender | |
parent | cdce3e09493c8bf4395de163342760409aad1407 (diff) |
fix [#33108] Running save_as_mainfile breaks relative texture paths
save-as with path remapping left the paths relate to the file written.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_global.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_utildefines.h | 6 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_bpath.h | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/bpath.c | 70 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 16 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 32 |
8 files changed, 116 insertions, 22 deletions
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index f7af534c2c2..f6276a69d57 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -167,6 +167,9 @@ enum { #define G_FILE_RELATIVE_REMAP (1 << 24) #define G_FILE_HISTORY (1 << 25) #define G_FILE_MESH_COMPAT (1 << 26) /* BMesh option to save as older mesh format */ +#define G_FILE_SAVE_COPY (1 << 27) /* restore paths after editing them */ + +#define G_FILE_FLAGS_RUNTIME (G_FILE_NO_UI | G_FILE_RELATIVE_REMAP | G_FILE_MESH_COMPAT | G_FILE_SAVE_COPY) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 06f8b89ec05..7c1e0e97565 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -32,7 +32,11 @@ extern "C" { #endif -/* currently unused but we may want to add macros here for BKE later */ +#define BKE_BIT_TEST_SET(value, test, flag) \ +{ \ + if (test) (value) |= flag; \ + else (value) &= ~flag; \ +} (void)0 #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h index a86b362c271..438bffb2fc5 100644 --- a/source/blender/blenlib/BLI_bpath.h +++ b/source/blender/blenlib/BLI_bpath.h @@ -48,6 +48,11 @@ void BLI_bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVi void BLI_bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata); int BLI_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src); +/* Functions for temp backup/restore of paths, path count must NOT change */ +void *BLI_bpath_list_backup(struct Main *bmain, const int flag); +void BLI_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle); +void BLI_bpath_list_free(void *ls_handle); + #define BLI_BPATH_TRAVERSE_ABS (1 << 0) /* convert paths to absolute */ #define BLI_BPATH_TRAVERSE_SKIP_LIBRARY (1 << 2) /* skip library paths */ #define BLI_BPATH_TRAVERSE_SKIP_PACKED (1 << 3) /* skip packed data */ diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 8ae2b941fa8..be9f5f97a6e 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -618,3 +618,73 @@ int BLI_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *pat return FALSE; } } + + +/* -------------------------------------------------------------------- */ +/** + * Backup/Restore/Free functions, + * \note These functions assume the data won't chane order. + */ + +struct PathStore { + struct PathStore *next, *prev; +} PathStore; + +static int bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src) +{ + /* store the path and string in a single alloc */ + ListBase *ls = userdata; + size_t path_size = strlen(path_src) + 1; + struct PathStore *path_store = MEM_mallocN(sizeof(PathStore) + path_size, __func__); + char *filepath = (char *)(path_store + 1); + + memcpy(filepath, path_src, path_size); + BLI_addtail(ls, path_store); + return FALSE; +} + +static int bpath_list_restore(void *userdata, char *path_dst, const char *path_src) +{ + /* assume ls->first wont be NULL because the number of paths can't change! + * (if they do caller is wrong) */ + ListBase *ls = userdata; + struct PathStore *path_store = ls->first; + const char *filepath = (char *)(path_store + 1); + int ret; + + if (strcmp(path_src, filepath) == 0) { + ret = FALSE; + } + else { + BLI_strncpy(path_dst, filepath, FILE_MAX); + ret = TRUE; + } + + BLI_freelinkN(ls, path_store); + return ret; +} + +/* return ls_handle */ +void *BLI_bpath_list_backup(Main *bmain, const int flag) +{ + ListBase *ls = MEM_callocN(sizeof(ListBase), __func__); + + BLI_bpath_traverse_main(bmain, bpath_list_append, flag, ls); + + return ls; +} + +void BLI_bpath_list_restore(Main *bmain, const int flag, void *ls_handle) +{ + ListBase *ls = ls_handle; + + BLI_bpath_traverse_main(bmain, bpath_list_restore, flag, ls); +} + +void BLI_bpath_list_free(void *ls_handle) +{ + ListBase *ls = ls_handle; + BLI_assert(ls->first == NULL); /* assumes we were used */ + BLI_freelistN(ls); + MEM_freeN(ls); +} diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 8521b43e437..ac5366c26a3 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2890,7 +2890,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) fg.winpos= G.winpos; /* prevent to save this, is not good convention, and feature with concerns... */ - fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP|G_FILE_MESH_COMPAT)); + fg.fileflags= (fileflags & ~G_FILE_FLAGS_RUNTIME); fg.globalf= G.f; BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename)); @@ -3039,6 +3039,10 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL char tempname[FILE_MAX+1]; int file, err, write_user_block; + /* path backup/restore */ + void *path_list_backup = NULL; + const int path_list_flag = (BLI_BPATH_TRAVERSE_SKIP_LIBRARY | BLI_BPATH_TRAVERSE_SKIP_MULTIFILE); + /* open temporary file, so we preserve the original in case we crash */ BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath); @@ -3048,6 +3052,11 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL return 0; } + /* check if we need to backup and restore paths */ + if (UNLIKELY((write_flags & G_FILE_RELATIVE_REMAP) && (G_FILE_SAVE_COPY & write_flags))) { + path_list_backup = BLI_bpath_list_backup(mainvar, path_list_flag); + } + /* remapping of relative paths to new file location */ if (write_flags & G_FILE_RELATIVE_REMAP) { char dir1[FILE_MAX]; @@ -3083,6 +3092,11 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL err= write_file_handle(mainvar, file, NULL, NULL, write_user_block, write_flags, thumb); close(file); + if (UNLIKELY(path_list_backup)) { + BLI_bpath_list_restore(mainvar, path_list_flag, path_list_backup); + BLI_bpath_list_free(path_list_backup); + } + if (err) { BKE_report(reports, RPT_ERROR, strerror(errno)); remove(tempname); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 549ded6ee48..c53c4dca74c 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -106,7 +106,7 @@ int WM_homefile_read_exec(struct bContext *C, struct wmOperator *op); int WM_homefile_read(struct bContext *C, struct ReportList *reports, short from_memory); int WM_homefile_write_exec(struct bContext *C, struct wmOperator *op); void WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports); -int WM_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports, int copy); +int WM_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports); void WM_autosave_init(struct wmWindowManager *wm); /* mouse cursors */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 6124b03778d..0e4af46d0fc 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -762,7 +762,7 @@ int write_crash_blend(void) } } -int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *reports, int copy) +int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *reports) { Library *li; int len; @@ -818,7 +818,7 @@ int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *re fileflags |= G_FILE_HISTORY; /* write file history */ if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { - if (!copy) { + if (!(fileflags & G_FILE_SAVE_COPY)) { G.relbase_valid = 1; BLI_strncpy(G.main->name, filepath, sizeof(G.main->name)); /* is guaranteed current file */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c9551ee28a4..054e48f0bfb 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -72,6 +72,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" /* BKE_ST_MAXNAME */ +#include "BKE_utildefines.h" #include "BKE_idcode.h" @@ -2077,7 +2078,6 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) { char path[FILE_MAX]; int fileflags; - int copy = 0; save_set_compress(op); @@ -2087,29 +2087,27 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) BLI_strncpy(path, G.main->name, FILE_MAX); untitled(path); } - - if (RNA_struct_property_is_set(op->ptr, "copy")) - copy = RNA_boolean_get(op->ptr, "copy"); fileflags = G.fileflags; /* set compression flag */ - if (RNA_boolean_get(op->ptr, "compress")) fileflags |= G_FILE_COMPRESS; - else fileflags &= ~G_FILE_COMPRESS; - if (RNA_boolean_get(op->ptr, "relative_remap")) fileflags |= G_FILE_RELATIVE_REMAP; - else fileflags &= ~G_FILE_RELATIVE_REMAP; + BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "compress"), + G_FILE_COMPRESS); + BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "relative_remap"), + G_FILE_RELATIVE_REMAP); + BKE_BIT_TEST_SET(fileflags, + (RNA_struct_property_is_set(op->ptr, "copy") && + RNA_boolean_get(op->ptr, "copy")), + G_FILE_SAVE_COPY); + #ifdef USE_BMESH_SAVE_AS_COMPAT - /* property only exists for 'Save As' */ - if (RNA_struct_find_property(op->ptr, "use_mesh_compat")) { - if (RNA_boolean_get(op->ptr, "use_mesh_compat")) fileflags |= G_FILE_MESH_COMPAT; - else fileflags &= ~G_FILE_MESH_COMPAT; - } - else { - fileflags &= ~G_FILE_MESH_COMPAT; - } + BKE_BIT_TEST_SET(fileflags, + (RNA_struct_find_property(op->ptr, "use_mesh_compat") && + RNA_boolean_get(op->ptr, "use_mesh_compat")), + G_FILE_MESH_COMPAT); #endif - if (WM_file_write(C, path, fileflags, op->reports, copy) != 0) + if (WM_file_write(C, path, fileflags, op->reports) != 0) return OPERATOR_CANCELLED; WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL); |