diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-01-08 20:50:55 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-01-08 20:50:55 +0300 |
commit | 1f1245a92a21b4744495549b951caf59fea06765 (patch) | |
tree | 941b6c2cdf7923b445b032996dc7f80591cc6f26 /source/blender | |
parent | 5dffae2346208d7b8185afb99d7ba0465214a515 (diff) |
Remap Relative paths save option.
If you have a blend file and want to save in a new directory enabling this will save with the paths corrected relative to the new directory.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_global.h | 1 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_bpath.h | 12 | ||||
-rw-r--r-- | source/blender/blenlib/intern/bpath.c | 152 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 20 | ||||
-rw-r--r-- | source/blender/editors/space_info/info_ops.c | 32 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 10 |
6 files changed, 100 insertions, 127 deletions
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 2e9ac2f65f0..9684aa1c602 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -146,6 +146,7 @@ typedef struct Global { #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) +#define G_FILE_RELATIVE_REMAP (1 << 24) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h index 874c8c7828c..730e3eda283 100644 --- a/source/blender/blenlib/BLI_bpath.h +++ b/source/blender/blenlib/BLI_bpath.h @@ -47,11 +47,13 @@ struct BPathIterator { void (*setpath_callback)(struct BPathIterator *, char *); void (*getpath_callback)(struct BPathIterator *, char *); + char* base_path; /* base path, the directry the blend file is in - normally G.sce */ + /* only for seq data */ struct BPathIteratorSeqData seqdata; }; -void BLI_bpathIterator_init (struct BPathIterator *bpi); +void BLI_bpathIterator_init (struct BPathIterator *bpi, char *base_path); void BLI_bpathIterator_free (struct BPathIterator *bpi); char* BLI_bpathIterator_getLib (struct BPathIterator *bpi); char* BLI_bpathIterator_getName (struct BPathIterator *bpi); @@ -66,7 +68,7 @@ void BLI_bpathIterator_setPath (struct BPathIterator *bpi, char *path); /* high level funcs */ /* creates a text file with missing files if there are any */ -void checkMissingFiles(char *txtname ); -void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked); -void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked); -void findMissingFiles(char *str); +void checkMissingFiles(char *basepath, ReportList *reports); +void makeFilesRelative(char *basepath, ReportList *reports); +void makeFilesAbsolute(char *basepath, ReportList *reports); +void findMissingFiles(char *basepath, char *str); diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 0df9d9b8db3..626c6ee8443 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -52,7 +52,7 @@ #include "DNA_sound_types.h" #include "DNA_scene_types.h" /* to get the current frame */ #include "DNA_sequence_types.h" -#include "DNA_text_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_blenlib.h" #include "BLI_bpath.h" @@ -61,7 +61,6 @@ #include "BKE_image.h" /* so we can check the image's type */ #include "BKE_main.h" /* so we can access G.main->*.first */ #include "BKE_sequencer.h" -#include "BKE_text.h" /* for writing to a textblock */ #include "BKE_utildefines.h" //XXX #include "BIF_screen.h" /* only for wait cursor */ @@ -86,19 +85,21 @@ enum BPathTypes { BPATH_DONE }; -void BLI_bpathIterator_init( struct BPathIterator *bpi ) { +void BLI_bpathIterator_init( struct BPathIterator *bpi, char *base_path ) { bpi->type = BPATH_IMAGE; bpi->data = NULL; bpi->getpath_callback = NULL; bpi->setpath_callback = NULL; - /* Sequencer spesific */ + /* Sequencer specific */ bpi->seqdata.totseq = 0; bpi->seqdata.seq = 0; bpi->seqdata.seqar = NULL; bpi->seqdata.scene = NULL; + bpi->base_path= base_path ? base_path : G.sce; + BLI_bpathIterator_step(bpi); } @@ -134,7 +135,7 @@ void BLI_bpathIterator_getPathExpanded( struct BPathIterator *bpi, char *path_ex if (libpath) { /* check the files location relative to its library path */ BLI_convertstringcode(path_expanded, libpath); } else { /* local data, use the blend files path */ - BLI_convertstringcode(path_expanded, G.sce); + BLI_convertstringcode(path_expanded, bpi->base_path); } } char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) { @@ -413,186 +414,157 @@ int BLI_bpathIterator_isDone( struct BPathIterator *bpi) { } /* include the path argument */ -static void bpathToText(Text *btxt, struct BPathIterator *bpi) +static void bpath_as_report(struct BPathIterator *bpi, const char *message, ReportList *reports) { + char *prefix; char *name; char path_expanded[FILE_MAXDIR*2]; + if(reports==NULL) + return; + switch(BLI_bpathIterator_getType(bpi)) { case BPATH_IMAGE: - txt_insert_buf( btxt, "Image \"" ); + prefix= "Image"; break; case BPATH_SOUND: - txt_insert_buf( btxt, "Sound \"" ); + prefix= "Sound"; break; case BPATH_FONT: - txt_insert_buf( btxt, "Font \"" ); + prefix= "Font"; break; case BPATH_LIB: - txt_insert_buf( btxt, "Library \"" ); + prefix= "Library"; break; case BPATH_SEQ: - txt_insert_buf( btxt, "Sequence \"" ); + prefix= "Sequence"; break; default: - txt_insert_buf( btxt, "Unknown \"" ); + prefix= "Unknown"; break; } name = BLI_bpathIterator_getName(bpi); - - if (name) { - txt_insert_buf( btxt, name ); - } - txt_insert_buf( btxt, "\" " ); - BLI_bpathIterator_getPathExpanded(bpi, path_expanded); - - txt_insert_buf( btxt, path_expanded ); - txt_insert_buf( btxt, "\n" ); - txt_move_eof( btxt, 0 ); + + if(reports) { + if (name) BKE_reportf("%s \"%s\", \"%s\": %s", prefix, name, path_expanded, message); + else BKE_reportf("%s \"%s\": %s", prefix, path_expanded, message); + } + } /* high level function */ -void checkMissingFiles( char *txtname ) { - Text *btxt = NULL; +void checkMissingFiles(char *basepath, ReportList *reports) { struct BPathIterator bpi; /* be sure there is low chance of the path being too short */ char filepath_expanded[FILE_MAXDIR*2]; - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPathExpanded( &bpi, filepath_expanded ); - if (!BLI_exists(filepath_expanded)) { - if (!btxt) { - btxt = add_empty_text( "missing_files.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - } + if (!BLI_exists(filepath_expanded)) + bpath_as_report(&bpi, "file not found", reports); + BLI_bpathIterator_step(&bpi); } BLI_bpathIterator_free(&bpi); } /* dont log any errors at the moment, should probably do this */ -void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked) { +void makeFilesRelative(char *basepath, ReportList *reports) { + int tot= 0, changed= 0, failed= 0, linked= 0; struct BPathIterator bpi; char filepath[FILE_MAX], *libpath; /* be sure there is low chance of the path being too short */ char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE]; - Text *btxt = NULL; - - *tot = *changed = *failed = *linked = 0; - - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPath(&bpi, filepath); libpath = BLI_bpathIterator_getLib(&bpi); if(strncmp(filepath, "//", 2)) { if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */ - (*linked)++; + linked++; } else { /* local data, use the blend files path */ BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative)); /* Important BLI_cleanup_dir runs before the path is made relative * because it wont work for paths that start with "//../" */ - BLI_cleanup_file(G.sce, filepath_relative); /* fix any /foo/../foo/ */ - BLI_makestringcode(G.sce, filepath_relative); + BLI_cleanup_file(bpi.base_path, filepath_relative); /* fix any /foo/../foo/ */ + BLI_makestringcode(bpi.base_path, filepath_relative); /* be safe and check the length */ if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_relative)) { - if (!btxt) { - btxt = add_empty_text( "missing_no_rel.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make path relative (too long)", reports); + failed++; } else { if(strncmp(filepath_relative, "//", 2)==0) { BLI_bpathIterator_setPath(&bpi, filepath_relative); - (*changed)++; + changed++; } else { - if (!btxt) { - btxt = add_empty_text( "missing_no_rel.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make path relative", reports); + failed++; } } } } BLI_bpathIterator_step(&bpi); - (*tot)++; + tot++; } BLI_bpathIterator_free(&bpi); + + if(reports) + BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); } /* dont log any errors at the moment, should probably do this - * Verry similar to makeFilesRelative - keep in sync! */ -void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked) { +void makeFilesAbsolute(char *basepath, ReportList *reports) +{ + int tot= 0, changed= 0, failed= 0, linked= 0; + struct BPathIterator bpi; char filepath[FILE_MAX], *libpath; /* be sure there is low chance of the path being too short */ char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE]; - Text *btxt = NULL; - - *tot = *changed = *failed = *linked = 0; - - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPath(&bpi, filepath); libpath = BLI_bpathIterator_getLib(&bpi); if(strncmp(filepath, "//", 2)==0) { if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */ - (*linked)++; + linked++; } else { /* get the expanded path and check it is relative or too long */ BLI_bpathIterator_getPathExpanded( &bpi, filepath_absolute ); - BLI_cleanup_file(G.sce, filepath_absolute); /* fix any /foo/../foo/ */ + BLI_cleanup_file(bpi.base_path, filepath_absolute); /* fix any /foo/../foo/ */ /* to be safe, check the length */ if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_absolute)) { - if (!btxt) { - btxt = add_empty_text( "missing_no_abs.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make absolute (too long)", reports); + failed++; } else { if(strncmp(filepath_absolute, "//", 2)) { BLI_bpathIterator_setPath(&bpi, filepath_absolute); - (*changed)++; + changed++; } else { - if (!btxt) { - btxt = add_empty_text( "missing_no_abs.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make absolute", reports); + failed++; } } } } BLI_bpathIterator_step(&bpi); - (*tot)++; + tot++; } BLI_bpathIterator_free(&bpi); + + if(reports) + BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); } @@ -651,7 +623,7 @@ static int findFileRecursive(char *filename_new, const char *dirname, const char } /* high level function - call from fileselector */ -void findMissingFiles(char *str) { +void findMissingFiles(char *basepath, char *str) { struct BPathIterator bpi; /* be sure there is low chance of the path being too short */ @@ -665,7 +637,7 @@ void findMissingFiles(char *str) { BLI_split_dirfile_basic(str, dirname, NULL); - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPath(&bpi, filepath); @@ -699,7 +671,7 @@ void findMissingFiles(char *str) { } else { /* copy the found path into the old one */ if (G.relbase_valid) - BLI_makestringcode(G.sce, filename_new); + BLI_makestringcode(bpi.base_path, filename_new); BLI_bpathIterator_setPath( &bpi, filename_new ); } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 061ed71d77e..13033c8fcba 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -145,6 +145,7 @@ Any case: direct data is ALWAYS after the lib block #include "MEM_guardedalloc.h" // MEM_freeN #include "BLI_blenlib.h" #include "BLI_linklist.h" +#include "BLI_bpath.h" #include "BKE_action.h" #include "BKE_blender.h" @@ -2458,9 +2459,28 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report return 0; } + if(write_flags & G_FILE_RELATIVE_REMAP) { + char dir1[FILE_MAXDIR+FILE_MAXFILE]; + char dir2[FILE_MAXDIR+FILE_MAXFILE]; + BLI_split_dirfile_basic(dir, dir1, NULL); + BLI_split_dirfile_basic(mainvar->name, dir2, NULL); + + /* just incase there is some subtle difference */ + BLI_cleanup_dir(dir1); + BLI_cleanup_dir(dir2); + + if(strcmp(dir1, dir2)==0) + write_flags &= ~G_FILE_RELATIVE_REMAP; + else + makeFilesAbsolute(G.sce, reports); + } + BLI_make_file_string(G.sce, userfilename, BLI_gethome(), ".B25.blend"); write_user_block= BLI_streq(dir, userfilename); + if(write_flags & G_FILE_RELATIVE_REMAP) + makeFilesRelative(dir, NULL); /* note, making relative to something OTHER then G.sce */ + err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags); close(file); diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 13bcd3276af..81506d42d87 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -196,21 +196,12 @@ void FILE_OT_unpack_all(wmOperatorType *ot) static int make_paths_relative_exec(bContext *C, wmOperator *op) { - char txtname[24]; /* text block name */ - int tot, changed, failed, linked; - if(!G.relbase_valid) { BKE_report(op->reports, RPT_WARNING, "Can't set relative paths with an unsaved blend file."); return OPERATOR_CANCELLED; } - txtname[0] = '\0'; - makeFilesRelative(txtname, &tot, &changed, &failed, &linked); - - if(failed) - BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); - else - BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); + makeFilesRelative(G.sce, op->reports); return OPERATOR_FINISHED; } @@ -232,22 +223,12 @@ void FILE_OT_make_paths_relative(wmOperatorType *ot) static int make_paths_absolute_exec(bContext *C, wmOperator *op) { - char txtname[24]; /* text block name */ - int tot, changed, failed, linked; - if(!G.relbase_valid) { BKE_report(op->reports, RPT_WARNING, "Can't set absolute paths with an unsaved blend file."); return OPERATOR_CANCELLED; } - txtname[0] = '\0'; - makeFilesAbsolute(txtname, &tot, &changed, &failed, &linked); - - if(failed) - BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); - else - BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); - + makeFilesAbsolute(G.sce, op->reports); return OPERATOR_FINISHED; } @@ -273,12 +254,7 @@ static int report_missing_files_exec(bContext *C, wmOperator *op) txtname[0] = '\0'; /* run the missing file check */ - checkMissingFiles(txtname); - - if(txtname[0] == '\0') - BKE_report(op->reports, RPT_INFO, "No external files missing."); - else - BKE_reportf(op->reports, RPT_ERROR, "Missing files listed in Text \"%s\"", txtname); + checkMissingFiles(G.sce, op->reports); return OPERATOR_FINISHED; } @@ -303,7 +279,7 @@ static int find_missing_files_exec(bContext *C, wmOperator *op) char *path; path= RNA_string_get_alloc(op->ptr, "path", NULL, 0); - findMissingFiles(path); + findMissingFiles(path, G.sce); MEM_freeN(path); return OPERATOR_FINISHED; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c39ca20472c..ef586e3065e 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1535,10 +1535,10 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) 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, "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; WM_write_file(C, path, fileflags, op->reports); @@ -1559,6 +1559,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file."); + RNA_def_boolean(ot->srna, "relative_remap", 0, "Remap Relative", "Remap relative paths when saving in a different directory."); } /* *************** save file directly ******** */ @@ -1597,6 +1598,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot) WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file."); + RNA_def_boolean(ot->srna, "relative_remap", 0, "Remap Relative", "Remap relative paths when saving in a different directory."); } |