Merged changes in the trunk up to revision 51718.
[blender.git] / source / blender / blenlib / intern / bpath.c
index 9b1f2ca69bc96dfad2f71aaa567210a03bc6651a..2f335b557fe33d63a709261bed2d0a3735c787ac 100644 (file)
@@ -20,7 +20,7 @@
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): Campbell barton
+ * Contributor(s): Campbell barton, Alex Fraser
  *
  * ***** END GPL LICENSE BLOCK *****
  */
  *  \ingroup bli
  */
 
+/* TODO,
+ * currently there are some cases we don't support.
+ * - passing output paths to the visitor?, like render out.
+ * - passing sequence strips with many images.
+ * - passing directory paths - visitors don't know which path is a dir or a file.
+ * */
 
 #include <sys/stat.h>
 
 #include <string.h>
 #include <assert.h>
 
-/* path/file handeling stuff */
+/* path/file handling stuff */
 #ifndef WIN32
-  #include <dirent.h>
-  #include <unistd.h>
+#  include <dirent.h>
+#  include <unistd.h>
 #else
-  #include <io.h>
-  #include "BLI_winstuff.h"
+#  include <io.h>
+#  include "BLI_winstuff.h"
 #endif
 
 #include "MEM_guardedalloc.h"
 
-#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h" /* to get the current frame */
+#include "DNA_brush_types.h"
 #include "DNA_image_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_text_types.h"
-#include "DNA_sound_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_object_fluidsim.h"
+#include "DNA_object_force.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
 #include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_text_types.h"
+#include "DNA_texture_types.h"
 #include "DNA_vfont_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_object_types.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_scene_types.h"
+#include "DNA_smoke_types.h"
+#include "DNA_freestyle_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_bpath.h"
 #include "BLI_utildefines.h"
 
-#include "BKE_global.h"
-#include "BKE_image.h" /* so we can check the image's type */
-#include "BKE_sequencer.h"
+#include "BKE_font.h"
+#include "BKE_library.h"
 #include "BKE_main.h"
-#include "BKE_utildefines.h"
 #include "BKE_report.h"
-#include "BKE_library.h"
-
-typedef struct BPathIteratorSeqData
-{
-       int totseq;
-       int seq;
-       struct Sequence **seqar;        /* Sequence */
-       struct Scene *scene;            /* Current scene */
-} BPathIteratorSeqData;
-
-typedef struct BPathIterator
-{
-       char*   _path; /* never access directly, use BLI_bpathIterator_getPath */
-       const char*     _lib;
-       const char*     _name;
-       void*   data;
-       int             len;
-       int             type;
-       int             flag; /* iterator options */
-
-       void (*setpath_callback)(struct BPathIterator *, const char *);
-       void (*getpath_callback)(struct BPathIterator *, char *);
-
-       const char*     base_path; /* base path, the directory the blend file is in - normally bmain->name */
-
-       Main *bmain;
-
-       /* only for seq data */
-       struct BPathIteratorSeqData seqdata;
-} BPathIterator;
-
-#define FILE_MAX                       240
-
-
-/* TODO - BPATH_PLUGIN, BPATH_SEQ */
-enum BPathTypes {
-       BPATH_IMAGE= 0,
-       BPATH_TEXTURE,
-       BPATH_TEXT,
-       BPATH_SOUND,
-       BPATH_FONT,
-       BPATH_LIB,
-       BPATH_SEQ,
-       BPATH_CDATA,
-
-       BPATH_DONE
-};
-
-void BLI_bpathIterator_init(struct BPathIterator **bpi_pt, Main *bmain, const char *basedir, const int flag)
-{
-       BPathIterator *bpi;
-
-       bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_init");
-       *bpi_pt= bpi;
-
-       bpi->type= BPATH_IMAGE;
-       bpi->data= NULL;
-
-       bpi->getpath_callback= NULL;
-       bpi->setpath_callback= NULL;
-
-       /* Sequencer specific */
-       bpi->seqdata.totseq= 0;
-       bpi->seqdata.seq= 0;
-       bpi->seqdata.seqar= NULL;
-       bpi->seqdata.scene= NULL;
-
-       bpi->flag= flag;
-
-       bpi->base_path= basedir; /* normally bmain->name */
-       bpi->bmain= bmain;
-
-       BLI_bpathIterator_step(bpi);
-}
-
-#if 0
-static void BLI_bpathIterator_alloc(struct BPathIterator **bpi)
-{
-       *bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_alloc");
-}
-#endif
-
-void BLI_bpathIterator_free(struct BPathIterator *bpi)
-{
-       if (bpi->seqdata.seqar)
-               MEM_freeN((void *)bpi->seqdata.seqar);
-       bpi->seqdata.seqar= NULL;
-       bpi->seqdata.scene= NULL;
-
-       MEM_freeN(bpi);
-}
-
-void BLI_bpathIterator_getPath(struct BPathIterator *bpi, char *path)
-{
-       if (bpi->getpath_callback) {
-               bpi->getpath_callback(bpi, path);
-       }
-       else {
-               strcpy(path, bpi->_path); /* warning, we assume 'path' are long enough */
-       }
-}
-
-void BLI_bpathIterator_setPath(struct BPathIterator *bpi, const char *path)
-{
-       if (bpi->setpath_callback) {
-               bpi->setpath_callback(bpi, path);
-       }
-       else {
-               strcpy(bpi->_path, path); /* warning, we assume 'path' are long enough */
-       }
-}
-
-void BLI_bpathIterator_getPathExpanded(struct BPathIterator *bpi, char *path_expanded)
-{
-       const char *libpath;
-
-       BLI_bpathIterator_getPath(bpi, path_expanded);
-       libpath= BLI_bpathIterator_getLib(bpi);
-
-       if (libpath) { /* check the files location relative to its library path */
-               BLI_path_abs(path_expanded, libpath);
-       }
-       else { /* local data, use the blend files path */
-               BLI_path_abs(path_expanded, bpi->base_path);
-       }
-       BLI_cleanup_file(NULL, path_expanded);
-}
-const char* BLI_bpathIterator_getLib(struct BPathIterator *bpi)
-{
-       return bpi->_lib;
-}
-const char* BLI_bpathIterator_getName(struct BPathIterator *bpi)
-{
-       return bpi->_name;
-}
-int    BLI_bpathIterator_getType(struct BPathIterator *bpi)
-{
-       return bpi->type;
-}
-unsigned int   BLI_bpathIterator_getPathMaxLen(struct BPathIterator *bpi)
-{
-       return bpi->len;
-}
-const char* BLI_bpathIterator_getBasePath(struct BPathIterator *bpi)
-{
-       return bpi->base_path;
-}
+#include "BKE_sequencer.h"
+#include "BKE_image.h" /* so we can check the image's type */
 
-/* gets the first or the next image that has a path - not a viewer node or generated image */
-static struct Image *ima_stepdata__internal(struct Image *ima, const int step_next, const int flag)
+static int checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
 {
-       if (ima==NULL)
-               return NULL;
+       ReportList *reports = (ReportList *)userdata;
 
-       if (step_next)
-               ima= ima->id.next;
-
-       while (ima) {
-               if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
-                       if(ima->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
-                               break;
-                       }
-               }
-               /* image is not a image with a path, skip it */
-               ima= ima->id.next;
+       if (!BLI_exists(path_src)) {
+               BKE_reportf(reports, RPT_WARNING, "Path '%s' not found", path_src);
        }
-       return ima;
-}
-
-static struct Tex *tex_stepdata__internal(struct Tex *tex, const int step_next, const int UNUSED(flag))
-{
-       if (tex==NULL)
-               return NULL;
 
-       if (step_next)
-               tex= tex->id.next;
-
-       while (tex) {
-               if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format))
-                       break;
-               /* image is not a image with a path, skip it */
-               tex= tex->id.next;
-       }
-       return tex;
+       return FALSE;
 }
 
-static struct Text *text_stepdata__internal(struct Text *text, const int step_next, const int UNUSED(flag))
-{
-       if (text==NULL)
-               return NULL;
-
-       if (step_next)
-               text= text->id.next;
-
-       while (text) {
-               if (text->name)
-                       break;
-               /* image is not a image with a path, skip it */
-               text= text->id.next;
-       }
-       return text;
-}
-
-static struct VFont *vf_stepdata__internal(struct VFont *vf, const int step_next, const int flag)
+/* high level function */
+void BLI_bpath_missing_files_check(Main *bmain, ReportList *reports)
 {
-       if (vf==NULL)
-               return NULL;
-
-       if (step_next)
-               vf= vf->id.next;
-
-       while (vf) {
-               if (strcmp(vf->name, FO_BUILTIN_NAME)!=0) {
-                       if(vf->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
-                               break;
-                       }
-               }
-
-               /* font with no path, skip it */
-               vf= vf->id.next;
-       }
-       return vf;
+       BLI_bpath_traverse_main(bmain, checkMissingFiles_visit_cb, BLI_BPATH_TRAVERSE_ABS, reports);
 }
 
-static struct bSound *snd_stepdata__internal(struct bSound *snd, int step_next, const int flag)
-{
-       if (snd==NULL)
-               return NULL;
+typedef struct BPathRemap_Data {
+       const char *basedir;
+       ReportList *reports;
 
-       if (step_next)
-               snd= snd->id.next;
+       int count_tot;
+       int count_changed;
+       int count_failed;
+} BPathRemap_Data;
 
-       while (snd) {
-               if(snd->packedfile==NULL || (flag & BPATH_USE_PACKED)) {
-                       break;
-               }
-
-               /* font with no path, skip it */
-               snd= snd->id.next;
-       }
-       return snd;
-}
-
-static struct Sequence *seq_stepdata__internal(struct BPathIterator *bpi, int step_next)
+static int makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src)
 {
-       Editing *ed;
-       Sequence *seq;
-
-       /* Initializing */
-       if (bpi->seqdata.scene==NULL) {
-               bpi->seqdata.scene= bpi->bmain->scene.first;
-       }
-
-       if (step_next) {
-               bpi->seqdata.seq++;
-       }
-
-       while (bpi->seqdata.scene) {
-               ed= seq_give_editing(bpi->seqdata.scene, 0);
-               if (ed) {
-                       if (bpi->seqdata.seqar == NULL) {
-                               /* allocate the sequencer array */
-                               seq_array(ed, &bpi->seqdata.seqar, &bpi->seqdata.totseq, 0);
-                               bpi->seqdata.seq= 0;
-                       }
-
-                       if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
-                               seq= NULL;
-                       }
-                       else {
-                               seq= bpi->seqdata.seqar[bpi->seqdata.seq];
-                               while (!SEQ_HAS_PATH(seq) && seq->plugin==NULL) {
-                                       bpi->seqdata.seq++;
-                                       if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
-                                               seq= NULL;
-                                               break;
-                                       }
-                                       seq= bpi->seqdata.seqar[bpi->seqdata.seq];
-                               }
-                       }
-                       if (seq) {
-                               return seq;
-                       }
-                       else {
-                               /* keep looking through the next scene, reallocate seq array */
-                               if (bpi->seqdata.seqar) {
-                                       MEM_freeN((void *)bpi->seqdata.seqar);
-                                       bpi->seqdata.seqar= NULL;
-                               }
-                               bpi->seqdata.scene= bpi->seqdata.scene->id.next;
-                       }
-               }
-               else {
-                       /* no seq data in this scene, next */
-                       bpi->seqdata.scene= bpi->seqdata.scene->id.next;
-               }
-       }
+       BPathRemap_Data *data = (BPathRemap_Data *)userdata;
 
-       return NULL;
-}
+       data->count_tot++;
 
-static void seq_getpath(struct BPathIterator *bpi, char *path)
-{
-       Sequence *seq= (Sequence *)bpi->data;
-
-
-       path[0]= '\0'; /* incase we cant get the path */
-       if (seq==NULL) return;
-       if (SEQ_HAS_PATH(seq)) {
-               if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
-                       BLI_strncpy(path, seq->strip->dir, FILE_MAX);
-                       BLI_add_slash(path); /* incase its missing */
-                       if (seq->strip->stripdata) { /* should always be true! */
-                               /* Using the first image is weak for image sequences */
-                               strcat(path, seq->strip->stripdata->name);
-                       }
-               }
-               else {
-                       /* simple case */
-                       BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
-               }
-       }
-       else if (seq->plugin) {
-               BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name));
+       if (BLI_path_is_rel(path_src)) {
+               return FALSE; /* already relative */
        }
-}
-
-static void seq_setpath(struct BPathIterator *bpi, const char *path)
-{
-       Sequence *seq= (Sequence *)bpi->data;
-       if (seq==NULL) return;
-
-       if (SEQ_HAS_PATH(seq)) {
-               if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
-                       BLI_split_dirfile(path, seq->strip->dir, seq->strip->stripdata->name, sizeof(seq->strip->dir), sizeof(seq->strip->stripdata->name));
+       else {
+               strcpy(path_dst, path_src);
+               BLI_path_rel(path_dst, data->basedir);
+               if (BLI_path_is_rel(path_dst)) {
+                       data->count_changed++;
                }
                else {
-                       /* simple case */
-                       BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
-               }
-       }
-       else if (seq->plugin) {
-               BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name));
-       }
-}
-
-static void text_getpath(struct BPathIterator *bpi, char *path)
-{
-       Text *text= (Text *)bpi->data;
-       path[0]= '\0'; /* incase we cant get the path */
-       if(text->name) {
-               strcpy(path, text->name);
-       }
-}
-
-static void text_setpath(struct BPathIterator *bpi, const char *path)
-{
-       Text *text= (Text *)bpi->data;
-       if (text==NULL) return;
-
-       if(text->name) {
-               MEM_freeN(text->name);
-       }
-
-       text->name= BLI_strdup(path);
-}
-
-static struct Mesh *cdata_stepdata__internal(struct Mesh *me, int step_next)
-{
-       if (me==NULL)
-               return NULL;
-
-       if (step_next)
-               me= me->id.next;
-
-       while (me) {
-               if (me->fdata.external) {
-                       break;
-               }
-
-               me= me->id.next;
-       }
-       return me;
-}
-
-static void bpi_type_step__internal(struct BPathIterator *bpi)
-{
-       bpi->type++; /* advance to the next type */
-       bpi->data= NULL;
-
-       switch (bpi->type) {
-       case BPATH_SEQ:
-               bpi->getpath_callback= seq_getpath;
-               bpi->setpath_callback= seq_setpath;
-               break;
-       case BPATH_TEXT: /* path is malloc'd */
-               bpi->getpath_callback= text_getpath;
-               bpi->setpath_callback= text_setpath;
-               break;
-       default:
-               bpi->getpath_callback= NULL;
-               bpi->setpath_callback= NULL;
-               break;
-       }
-}
-
-void BLI_bpathIterator_step(struct BPathIterator *bpi)
-{
-       while (bpi->type != BPATH_DONE) {
-
-               if  ((bpi->type) == BPATH_IMAGE) {
-                       /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
-                       if (bpi->data)  bpi->data= ima_stepdata__internal((Image *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
-                       else                    bpi->data= ima_stepdata__internal(bpi->bmain->image.first, 0, bpi->flag);
-
-                       if (bpi->data) {
-                               /* get the path info from this datatype */
-                               Image *ima= (Image *)bpi->data;
-
-                               bpi->_lib= ima->id.lib ? ima->id.lib->filepath : NULL;
-                               bpi->_path= ima->name;
-                               bpi->_name= ima->id.name+2;
-                               bpi->len= sizeof(ima->name);
-
-                               /* we are done, advancing to the next item, this type worked fine */
-                               break;
-
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
-               }
-
-               if  ((bpi->type) == BPATH_TEXTURE) {
-                       /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
-                       if (bpi->data)  bpi->data= tex_stepdata__internal( (Tex *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
-                       else                    bpi->data= tex_stepdata__internal(bpi->bmain->tex.first, 0, bpi->flag);
-
-                       if (bpi->data) {
-                               /* get the path info from this datatype */
-                               Tex *tex= (Tex *)bpi->data;
-
-                               if(tex->type == TEX_VOXELDATA) {
-                                       bpi->_lib= tex->id.lib ? tex->id.lib->filepath : NULL;
-                                       bpi->_path= tex->vd->source_path;
-                                       bpi->_name= tex->id.name+2;
-                                       bpi->len= sizeof(tex->vd->source_path);
-                               }
-                               else {
-                                       assert(!"Texture has no path, incorrect step 'tex_stepdata__internal'");
-                               }
-
-                               /* we are done, advancing to the next item, this type worked fine */
-                               break;
-
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
-               }
-
-               if  ((bpi->type) == BPATH_TEXT) {
-                       /*if (bpi->data)        bpi->data= ((ID *)bpi->data)->next;*/
-                       if (bpi->data)  bpi->data= text_stepdata__internal((Text *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
-                       else                    bpi->data= text_stepdata__internal(bpi->bmain->text.first, 0, bpi->flag);
-
-                       if (bpi->data) {
-                               /* get the path info from this datatype */
-                               Text *text= (Text *)bpi->data;
-
-                               bpi->_lib= text->id.lib ? text->id.lib->filepath : NULL;
-                               bpi->_path= NULL; /* bpi->path= text->name; */ /* get/set functions override. */
-                               bpi->_name= text->id.name+2;
-                               bpi->len= FILE_MAX; /* malloc'd but limit anyway since large paths may mess up other areas */
-
-                               /* we are done, advancing to the next item, this type worked fine */
-                               break;
-
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
-               }
-               else if  ((bpi->type) == BPATH_SOUND) {
-                       if (bpi->data)  bpi->data= snd_stepdata__internal((bSound *)bpi->data, 1, bpi->flag); /* must skip images that have no path */
-                       else                    bpi->data= snd_stepdata__internal(bpi->bmain->sound.first, 0, bpi->flag);
-
-                       if (bpi->data) {
-                               /* get the path info from this datatype */
-                               bSound *snd= (bSound *)bpi->data;
-
-                               bpi->_lib= snd->id.lib ? snd->id.lib->filepath : NULL;
-                               bpi->_path= snd->name;
-                               bpi->_name= snd->id.name+2;
-                               bpi->len= sizeof(snd->name);
-
-                               /* we are done, advancing to the next item, this type worked fine */
-                               break;
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
-               }
-               else if  ((bpi->type) == BPATH_FONT) {
-
-                       if (bpi->data)  bpi->data= vf_stepdata__internal((VFont *)bpi->data, 1, bpi->flag);
-                       else                    bpi->data= vf_stepdata__internal(bpi->bmain->vfont.first, 0, bpi->flag);
-
-                       if (bpi->data) {
-                               /* get the path info from this datatype */
-                               VFont *vf= (VFont *)bpi->data;
-
-                               bpi->_lib= vf->id.lib ? vf->id.lib->filepath : NULL;
-                               bpi->_path= vf->name;
-                               bpi->_name= vf->id.name+2;
-                               bpi->len= sizeof(vf->name);
-
-                               /* we are done, advancing to the next item, this type worked fine */
-                               break;
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
-
-               }
-               else if  ((bpi->type) == BPATH_LIB) {
-                       if (bpi->data)  bpi->data= ((ID *)bpi->data)->next;
-                       else                    bpi->data= bpi->bmain->library.first;
-
-                       if (bpi->data) {
-                               /* get the path info from this datatype */
-                               Library *lib= (Library *)bpi->data;
-
-                               bpi->_lib= NULL;
-                               bpi->_path= lib->name;
-                               bpi->_name= NULL;
-                               bpi->len= sizeof(lib->name);
-
-                               /* we are done, advancing to the next item, this type worked fine */
-                               break;
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
-               }
-               else if  ((bpi->type) == BPATH_SEQ) {
-                       if (bpi->data)  bpi->data= seq_stepdata__internal( bpi, 1 );
-                       else                    bpi->data= seq_stepdata__internal( bpi, 0 );
-                       if (bpi->data) {
-                               Sequence *seq= (Sequence *)bpi->data;
-                               bpi->_lib= NULL;
-                               bpi->_name= seq->name+2;
-                               bpi->len= seq->plugin ? sizeof(seq->plugin->name) : sizeof(seq->strip->dir) + sizeof(seq->strip->stripdata->name);
-                               break;
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
-               }
-               else if  ((bpi->type) == BPATH_CDATA) {
-                       if (bpi->data)  bpi->data= cdata_stepdata__internal( bpi->data, 1 );
-                       else                    bpi->data= cdata_stepdata__internal( bpi->bmain->mesh.first, 0 );
-
-                       if (bpi->data) {
-                               Mesh *me= (Mesh *)bpi->data;
-                               bpi->_lib= me->id.lib ? me->id.lib->filepath : NULL;
-                               bpi->_path= me->fdata.external->filename;
-                               bpi->_name= me->id.name+2;
-                               bpi->len= sizeof(me->fdata.external->filename);
-                               break;
-                       }
-                       else {
-                               bpi_type_step__internal(bpi);
-                       }
+                       BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src);
+                       data->count_failed++;
                }
+               return TRUE;
        }
 }
 
-int BLI_bpathIterator_isDone( struct BPathIterator *bpi)
+void BLI_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
 {
-       return bpi->type==BPATH_DONE;
-}
+       BPathRemap_Data data = {NULL};
 
-/* include the path argument */
-static void bpath_as_report(struct BPathIterator *bpi, const char *message, ReportList *reports)
-{
-       const char *prefix;
-       const char *name;
-       char path_expanded[FILE_MAXDIR*2];
-
-       if(reports==NULL)
+       if (basedir[0] == '\0') {
+               printf("%s: basedir='', this is a bug\n", __func__);
                return;
-
-       switch(BLI_bpathIterator_getType(bpi)) {
-       case BPATH_IMAGE:
-               prefix= "Image";
-               break;
-       case BPATH_TEXTURE:
-               prefix= "Texture";
-               break;
-       case BPATH_TEXT:
-               prefix= "Text";
-               break;
-       case BPATH_SOUND:
-               prefix= "Sound";
-               break;
-       case BPATH_FONT:
-               prefix= "Font";
-               break;
-       case BPATH_LIB:
-               prefix= "Library";
-               break;
-       case BPATH_SEQ:
-               prefix= "Sequence";
-               break;
-       case BPATH_CDATA:
-               prefix= "Mesh Data";
-               break;
-       default:
-               prefix= "Unknown";
-               break;
        }
 
-       name= BLI_bpathIterator_getName(bpi);
-       BLI_bpathIterator_getPathExpanded(bpi, path_expanded);
+       data.basedir = basedir;
+       data.reports = reports;
 
-       if(reports) {
-               if (name)       BKE_reportf(reports, RPT_WARNING, "%s \"%s\", \"%s\": %s", prefix, name, path_expanded, message);
-               else            BKE_reportf(reports, RPT_WARNING, "%s \"%s\": %s", prefix, path_expanded, message);
-       }
+       BLI_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
 
+       BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
+                   "Total files %d | Changed %d | Failed %d",
+                   data.count_tot, data.count_changed, data.count_failed);
 }
 
-/* high level function */
-void checkMissingFiles(Main *bmain, ReportList *reports)
+static int makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src)
 {
-       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, bmain, bmain->name, 0);
-       while (!BLI_bpathIterator_isDone(bpi)) {
-               BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded);
+       BPathRemap_Data *data = (BPathRemap_Data *)userdata;
 
-               if (!BLI_exists(filepath_expanded))
-                       bpath_as_report(bpi, "file not found", reports);
+       data->count_tot++;
 
-               BLI_bpathIterator_step(bpi);
+       if (BLI_path_is_rel(path_src) == FALSE) {
+               return FALSE; /* already absolute */
        }
-       BLI_bpathIterator_free(bpi);
-}
-
-/* dont log any errors at the moment, should probably do this */
-void makeFilesRelative(Main *bmain, const char *basedir, ReportList *reports)
-{
-       int tot= 0, changed= 0, failed= 0, linked= 0;
-       struct BPathIterator *bpi;
-       char filepath[FILE_MAX];
-       const char *libpath;
-
-       /* be sure there is low chance of the path being too short */
-       char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE];
-
-       if(basedir[0] == '\0') {
-               printf("makeFilesRelative: basedir='', this is a bug\n");
-               return;
-       }
-
-       BLI_bpathIterator_init(&bpi, bmain, basedir, 0);
-       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++;
-                       }
-                       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(bpi->base_path, filepath_relative); /* fix any /foo/../foo/ */
-                               BLI_path_rel(filepath_relative, bpi->base_path);
-                               /* be safe and check the length */
-                               if (BLI_bpathIterator_getPathMaxLen(bpi) <= strlen(filepath_relative)) {
-                                       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++;
-                                       }
-                                       else {
-                                               bpath_as_report(bpi, "couldn't make path relative", reports);
-                                               failed++;
-                                       }
-                               }
-                       }
+       else {
+               strcpy(path_dst, path_src);
+               BLI_path_abs(path_dst, data->basedir);
+               if (BLI_path_is_rel(path_dst) == FALSE) {
+                       data->count_changed++;
                }
-               BLI_bpathIterator_step(bpi);
-               tot++;
+               else {
+                       BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
+                       data->count_failed++;
+               }
+               return TRUE;
        }
-       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(Main *bmain, const char *basedir, ReportList *reports)
+/* similar to BLI_bpath_relative_convert - keep in sync! */
+void BLI_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
 {
-       int tot= 0, changed= 0, failed= 0, linked= 0;
-
-       struct BPathIterator *bpi;
-       char filepath[FILE_MAX];
-       const char *libpath;
+       BPathRemap_Data data = {NULL};
 
-       /* be sure there is low chance of the path being too short */
-       char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE];
-
-       if(basedir[0] == '\0') {
-               printf("makeFilesAbsolute: basedir='', this is a bug\n");
+       if (basedir[0] == '\0') {
+               printf("%s: basedir='', this is a bug\n", __func__);
                return;
        }
 
-       BLI_bpathIterator_init(&bpi, bmain, basedir, 0);
-       while (!BLI_bpathIterator_isDone(bpi)) {
-               BLI_bpathIterator_getPath(bpi, filepath);
-               libpath= BLI_bpathIterator_getLib(bpi);
+       data.basedir = basedir;
+       data.reports = reports;
 
-               if(strncmp(filepath, "//", 2)==0) {
-                       if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */
-                               linked++;
-                       }
-                       else { /* get the expanded path and check it is relative or too long */
-                               BLI_bpathIterator_getPathExpanded(bpi, filepath_absolute);
-                               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)) {
-                                       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++;
-                                       }
-                                       else {
-                                               bpath_as_report(bpi, "couldn't make absolute", reports);
-                                               failed++;
-                                       }
-                               }
-                       }
-               }
-               BLI_bpathIterator_step(bpi);
-               tot++;
-       }
-       BLI_bpathIterator_free(bpi);
+       BLI_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
 
-       if(reports)
-               BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
+       BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
+                   "Total files %d | Changed %d | Failed %d",
+                   data.count_tot, data.count_changed, data.count_failed);
 }
 
-
-/* find this file recursively, use the biggest file so thumbnails dont get used by mistake
- - dir: subdir to search
- - filename: set this filename
- - filesize: filesize for the file
-*/
+/**
+ * find this file recursively, use the biggest file so thumbnails don't get used by mistake
+ * \param filename_new: the path will be copied here, caller must initialize as empty string.
+ * \param dirname: subdir to search
+ * \param filename: set this filename
+ * \param filesize: filesize for the file
+ *
+ * \returns found: 1/0.
+ */
 #define MAX_RECUR 16
-static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth)
+static int findFileRecursive(char *filename_new,
+                             const char *dirname,
+                             const char *filename,
+                             int *filesize,
+                             int *recur_depth)
 {
        /* file searching stuff */
        DIR *dir;
@@ -849,118 +214,115 @@ static int findFileRecursive(char *filename_new, const char *dirname, const char
        struct stat status;
        char path[FILE_MAX];
        int size;
+       int found = FALSE;
 
-       dir= opendir(dirname);
+       dir = opendir(dirname);
 
-       if (dir==NULL)
-               return 0;
+       if (dir == NULL)
+               return found;
 
        if (*filesize == -1)
-               *filesize= 0; /* dir opened fine */
+               *filesize = 0;  /* dir opened fine */
 
-       while ((de= readdir(dir)) != NULL) {
+       while ((de = readdir(dir)) != NULL) {
 
-               if (strcmp(".", de->d_name)==0 || strcmp("..", de->d_name)==0)
+               if (strcmp(".", de->d_name) == 0 || strcmp("..", de->d_name) == 0)
                        continue;
 
                BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
 
                if (stat(path, &status) != 0)
-                       continue; /* cant stat, dont bother with this file, could print debug info here */
+                       continue;  /* cant stat, don't bother with this file, could print debug info here */
 
                if (S_ISREG(status.st_mode)) { /* is file */
-                       if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */
+                       if (strncmp(filename, de->d_name, FILE_MAX) == 0) { /* name matches */
                                /* open the file to read its size */
-                               size= status.st_size;
+                               size = status.st_size;
                                if ((size > 0) && (size > *filesize)) { /* find the biggest file */
-                                       *filesize= size;
+                                       *filesize = size;
                                        BLI_strncpy(filename_new, path, FILE_MAX);
+                                       found = TRUE;
                                }
                        }
                }
                else if (S_ISDIR(status.st_mode)) { /* is subdir */
                        if (*recur_depth <= MAX_RECUR) {
                                (*recur_depth)++;
-                               findFileRecursive(filename_new, path, filename, filesize, recur_depth);
+                               found |= findFileRecursive(filename_new, path, filename, filesize, recur_depth);
                                (*recur_depth)--;
                        }
                }
        }
        closedir(dir);
-       return 1;
+       return found;
 }
 
-/* high level function - call from fileselector */
-void findMissingFiles(Main *bmain, const char *str)
-{
-       struct BPathIterator *bpi;
-
-       /* be sure there is low chance of the path being too short */
-       char filepath_expanded[FILE_MAXDIR*2];
-       char filepath[FILE_MAX];
-       const char *libpath;
-       int filesize, recur_depth;
-
-       char dirname[FILE_MAX], filename_new[FILE_MAX];
-
-       //XXX waitcursor( 1 );
+typedef struct BPathFind_Data {
+       const char *basedir;
+       char searchdir[FILE_MAX];
+       ReportList *reports;
+} BPathFind_Data;
 
-       BLI_split_dir_part(str, dirname, sizeof(dirname));
-
-       BLI_bpathIterator_init(&bpi, bmain, bmain->name, 0);
-
-       while (!BLI_bpathIterator_isDone(bpi)) {
-               BLI_bpathIterator_getPath(bpi, filepath);
-               libpath= BLI_bpathIterator_getLib(bpi);
-
-               /* Check if esc was pressed because searching files can be slow */
-               /*XXX if (blender_test_break()) {
-                       break;
-               }*/
+static int findMissingFiles_visit_cb(void *userdata, char *path_dst, const char *path_src)
+{
+       BPathFind_Data *data = (BPathFind_Data *)userdata;
+       char filename_new[FILE_MAX];
 
-               if (libpath==NULL) {
+       int filesize = -1;
+       int recur_depth = 0;
+       int found;
 
-                       BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded);
+       filename_new[0] = '\0';
 
-                       if (!BLI_exists(filepath_expanded)) {
-                               /* can the dir be opened? */
-                               filesize= -1;
-                               recur_depth= 0;
+       found = findFileRecursive(filename_new,
+                                 data->searchdir, BLI_path_basename((char *)path_src),
+                                 &filesize, &recur_depth);
 
-                               findFileRecursive(filename_new, dirname, BLI_path_basename(filepath), &filesize, &recur_depth);
-                               if (filesize == -1) { /* could not open dir */
-                                       printf("Could not open dir \"%s\"\n", dirname);
-                                       return;
-                               }
-
-                               if (filesize > 0) {
+       if (filesize == -1) { /* could not open dir */
+               BKE_reportf(data->reports, RPT_WARNING,
+                           "Could not open directory '%s'",
+                           BLI_path_basename(data->searchdir));
+               return FALSE;
+       }
+       else if (found == FALSE) {
+               BKE_reportf(data->reports, RPT_WARNING,
+                           "Could not find '%s' in '%s'",
+                           BLI_path_basename((char *)path_src), data->searchdir);
+               return FALSE;
+       }
+       else {
+               BLI_strncpy(path_dst, filename_new, FILE_MAX);
+               return TRUE;
+       }
+}
 
-                                       if (BLI_bpathIterator_getPathMaxLen(bpi) < strlen(filename_new)) {
-                                               printf("cannot set path \"%s\" too long!", filename_new);
-                                       }
-                                       else {
-                                               /* copy the found path into the old one */
-                                               if (G.relbase_valid)
-                                                       BLI_path_rel(filename_new, bpi->base_path);
+void BLI_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportList *reports)
+{
+       struct BPathFind_Data data = {NULL};
 
-                                               BLI_bpathIterator_setPath(bpi, filename_new);
-                                       }
-                               }
-                       }
-               }
-               BLI_bpathIterator_step(bpi);
-       }
-       BLI_bpathIterator_free(bpi);
+       data.reports = reports;
+       BLI_split_dir_part(searchpath, data.searchdir, sizeof(data.searchdir));
 
-       //XXX waitcursor( 0 );
+       BLI_bpath_traverse_main(bmain, findMissingFiles_visit_cb, 0, (void *)&data);
 }
 
 /* Run a visitor on a string, replacing the contents of the string as needed. */
-static int rewrite_path_fixed(char path[FILE_MAX], BPathVisitor visit_cb, void *userdata)
+static int rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *absbase, void *userdata)
 {
+       char path_src_buf[FILE_MAX];
+       const char *path_src;
        char path_dst[FILE_MAX];
 
-       if (visit_cb(userdata, path_dst, (const char *)path)) {
+       if (absbase) {
+               BLI_strncpy(path_src_buf, path, sizeof(path_src_buf));
+               BLI_path_abs(path_src_buf, absbase);
+               path_src = path_src_buf;
+       }
+       else {
+               path_src = path;
+       }
+
+       if (visit_cb(userdata, path_dst, path_src)) {
                BLI_strncpy(path, path_dst, FILE_MAX);
                return TRUE;
        }
@@ -969,16 +331,23 @@ static int rewrite_path_fixed(char path[FILE_MAX], BPathVisitor visit_cb, void *
        }
 }
 
-static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], char path_file[FILE_MAXFILE], BPathVisitor visit_cb, void *userdata)
+static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR],
+                                      char path_file[FILE_MAXFILE],
+                                      BPathVisitor visit_cb,
+                                      const char *absbase,
+                                      void *userdata)
 {
        char path_src[FILE_MAX];
        char path_dst[FILE_MAX];
 
        BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file);
 
+       if (absbase) {
+               BLI_path_abs(path_src, absbase);
+       }
+
        if (visit_cb(userdata, path_dst, (const char *)path_src)) {
-               BLI_split_dirfile(path_dst, path_dir, path_file,
-                                 sizeof(path_dir), sizeof(path_file));
+               BLI_split_dirfile(path_dst, path_dir, path_file, FILE_MAXDIR, FILE_MAXFILE);
                return TRUE;
        }
        else {
@@ -986,13 +355,24 @@ static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], char path_file
        }
 }
 
-static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, void *userdata)
+static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *absbase, void *userdata)
 {
+       char path_src_buf[FILE_MAX];
+       const char *path_src;
        char path_dst[FILE_MAX];
 
-       if (visit_cb(userdata, path_dst, (const char *)(*path))) {
+       if (absbase) {
+               BLI_strncpy(path_src_buf, *path, sizeof(path_src_buf));
+               BLI_path_abs(path_src_buf, absbase);
+               path_src = path_src_buf;
+       }
+       else {
+               path_src = *path;
+       }
+
+       if (visit_cb(userdata, path_dst, path_src)) {
                MEM_freeN((*path));
-               (*path)= BLI_strdup(path_dst);
+               (*path) = BLI_strdup(path_dst);
                return TRUE;
        }
        else {
@@ -1001,117 +381,236 @@ static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, void *userdata
 }
 
 /* Run visitor function 'visit' on all paths contained in 'id'. */
-void bpath_traverse_id(ID *id, BPathVisitor visit_cb, void *userdata)
+void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
 {
        Image *ima;
+       const char *absbase = (flag & BLI_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
 
-       switch(GS(id->name)) {
-       case ID_IM:
-               ima = (Image *)id;
-               if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
-                       rewrite_path_fixed(ima->name, visit_cb, userdata);
-               break;
-       case ID_OB:
+       if ((flag & BLI_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) {
+               return;
+       }
+
+       switch (GS(id->name)) {
+               case ID_IM:
+                       ima = (Image *)id;
+                       if (ima->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+                               if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+                                       rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data);
+                               }
+                       }
+                       break;
+               case ID_BR:
                {
-                       Object *ob= (Object *)id;
-                       if (ob->fluidsimSettings) {
-                               rewrite_path_fixed(ob->fluidsimSettings->surfdataPath, visit_cb, userdata);
+                       Brush *brush = (Brush *)id;
+                       if (brush->icon_filepath[0]) {
+                               rewrite_path_fixed(brush->icon_filepath, visit_cb, absbase, bpath_user_data);
                        }
-                       /* TODO: add modifiers, e.g. point cache for particles. */
                }
                break;
-       case ID_SO:
-               rewrite_path_fixed(((bSound *)id)->name, visit_cb, userdata);
-               break;
-       case ID_TXT:
-               if (((Text*)id)->name) {
-                       rewrite_path_alloc(&((Text *)id)->name, visit_cb, userdata);
+               case ID_OB:
+
+#define BPATH_TRAVERSE_POINTCACHE(ptcaches)                                    \
+       {                                                                          \
+               PointCache *cache;                                                     \
+               for (cache = (ptcaches).first; cache; cache = cache->next) {           \
+                       if (cache->flag & PTCACHE_DISK_CACHE) {                            \
+                               rewrite_path_fixed(cache->path,                                \
+                                                  visit_cb,                                   \
+                                                  absbase,                                    \
+                                                  bpath_user_data);                           \
+                       }                                                                  \
+               }                                                                      \
+       } (void)0
+
+
+                       {
+                               Object *ob = (Object *)id;
+                               ModifierData *md;
+                               ParticleSystem *psys;
+
+                               /* do via modifiers instead */
+#if 0
+                               if (ob->fluidsimSettings) {
+                                       rewrite_path_fixed(ob->fluidsimSettings->surfdataPath, visit_cb, absbase, bpath_user_data);
+                               }
+#endif
+
+                               for (md = ob->modifiers.first; md; md = md->next) {
+                                       if (md->type == eModifierType_Fluidsim) {
+                                               FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
+                                               if (fluidmd->fss) {
+                                                       rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data);
+                                               }
+                                       }
+                                       else if (md->type == eModifierType_Smoke) {
+                                               SmokeModifierData *smd = (SmokeModifierData *)md;
+                                               if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
+                                                       BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]);
+                                               }
+                                       }
+                                       else if (md->type == eModifierType_Cloth) {
+                                               ClothModifierData *clmd = (ClothModifierData *) md;
+                                               BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches);
+                                       }
+                                       else if (md->type == eModifierType_Ocean) {
+                                               OceanModifierData *omd = (OceanModifierData *) md;
+                                               rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data);
+                                       }
+                               }
+
+                               if (ob->soft) {
+                                       BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches);
+                               }
+
+                               for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+                                       BPATH_TRAVERSE_POINTCACHE(psys->ptcaches);
+                               }
+                       }
+
+#undef BPATH_TRAVERSE_POINTCACHE
+
+                       break;
+               case ID_SO:
+               {
+                       bSound *sound = (bSound *)id;
+                       if (sound->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+                               rewrite_path_fixed(sound->name, visit_cb, absbase, bpath_user_data);
+                       }
                }
                break;
-       case ID_VF:
-               if (strcmp(((VFont*)id)->name, FO_BUILTIN_NAME) != 0) {
-                       rewrite_path_fixed(((VFont *)id)->name, visit_cb, userdata);
+               case ID_TXT:
+                       if (((Text *)id)->name) {
+                               rewrite_path_alloc(&((Text *)id)->name, visit_cb, absbase, bpath_user_data);
+                       }
+                       break;
+               case ID_VF:
+               {
+                       VFont *vfont = (VFont *)id;
+                       if (vfont->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+                               if (BKE_vfont_is_builtin(vfont) == FALSE) {
+                                       rewrite_path_fixed(((VFont *)id)->name, visit_cb, absbase, bpath_user_data);
+                               }
+                       }
                }
                break;
-       case ID_TE:
+               case ID_TE:
                {
                        Tex *tex = (Tex *)id;
-                       if (tex->plugin) {
-                               /* FIXME: rewrite_path assumes path length of FILE_MAX, but
-                                          tex->plugin->name is 160. ... is this field even a path? */
-                               //rewrite_path(tex->plugin->name, visit_cb, userdata);
-                       }
                        if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format)) {
-                               rewrite_path_fixed(tex->vd->source_path, visit_cb, userdata);
+                               rewrite_path_fixed(tex->vd->source_path, visit_cb, absbase, bpath_user_data);
                        }
                }
                break;
 
-       case ID_SCE:
+               case ID_SCE:
                {
-                       Scene *scene= (Scene *)id;
+                       Scene *scene = (Scene *)id;
+                       SceneRenderLayer *srl= scene->r.layers.first;
                        if (scene->ed) {
                                Sequence *seq;
 
-                               SEQ_BEGIN(scene->ed, seq) {
+                               SEQ_BEGIN(scene->ed, seq)
+                               {
                                        if (SEQ_HAS_PATH(seq)) {
-                                               if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
-                                                       rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name, visit_cb, userdata);
+                                               if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM)) {
+                                                       rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name,
+                                                                                  visit_cb, absbase, bpath_user_data);
+                                               }
+                                               else if (seq->type == SEQ_TYPE_IMAGE) {
+                                                       /* might want an option not to loop over all strips */
+                                                       StripElem *se = seq->strip->stripdata;
+                                                       int len = MEM_allocN_len(se) / sizeof(*se);
+                                                       int i;
+
+                                                       if (flag & BLI_BPATH_TRAVERSE_SKIP_MULTIFILE) {
+                                                               /* only operate on one path */
+                                                               len = MIN2(1, len);
+                                                       }
+
+                                                       for (i = 0; i < len; i++, se++) {
+                                                               rewrite_path_fixed_dirfile(seq->strip->dir, se->name,
+                                                                                          visit_cb, absbase, bpath_user_data);
+                                                       }
                                                }
                                                else {
                                                        /* simple case */
-                                                       rewrite_path_fixed(seq->strip->dir, visit_cb, userdata);
+                                                       rewrite_path_fixed(seq->strip->dir, visit_cb, absbase, bpath_user_data);
                                                }
                                        }
-                                       else if (seq->plugin) {
-                                               rewrite_path_fixed(seq->plugin->name, visit_cb, userdata);
-                                       }
 
                                }
                                SEQ_END
                        }
+                       for(; srl; srl= srl->next) {
+                               FreestyleModuleConfig* module= srl->freestyleConfig.modules.first;
+                               for (; module; module= module->next) {
+                                       rewrite_path_fixed(module->module_path, visit_cb, absbase, bpath_user_data);
+                               }
+                       }
                }
                break;
-       case ID_ME:
+               case ID_ME:
                {
-                       Mesh *me= (Mesh *)id;
-                       if (me->fdata.external) {
-                               rewrite_path_fixed(me->fdata.external->filename, visit_cb, userdata);
+                       Mesh *me = (Mesh *)id;
+                       if (me->ldata.external) {
+                               rewrite_path_fixed(me->ldata.external->filename, visit_cb, absbase, bpath_user_data);
                        }
                }
                break;
-       case ID_LI:
+               case ID_LI:
                {
-                       Library *lib= (Library *)id;
-                       if(rewrite_path_fixed(lib->name, visit_cb, userdata)) {
+                       Library *lib = (Library *)id;
+                       if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) {
                                BKE_library_filepath_set(lib, lib->name);
                        }
                }
                break;
-       /* TODO: add other ID types e.g. object (modifiers) */
-       default:
-               /* Nothing to do for other IDs that don't contain file paths. */
+               case ID_MC:
+               {
+                       MovieClip *clip = (MovieClip *)id;
+                       rewrite_path_fixed(clip->name, visit_cb, absbase, bpath_user_data);
+               }
                break;
+               default:
+                       /* Nothing to do for other IDs that don't contain file paths. */
+                       break;
+       }
+}
+
+void BLI_bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+{
+       ID *id;
+       for (id = lb->first; id; id = id->next) {
+               BLI_bpath_traverse_id(bmain, id, visit_cb, flag, bpath_user_data);
+       }
+}
+
+void BLI_bpath_traverse_main(Main *bmain, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+{
+       ListBase *lbarray[MAX_LIBARRAY];
+       int a = set_listbasepointers(bmain, lbarray);
+       while (a--) {
+               BLI_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);
        }
 }
 
 /* Rewrites a relative path to be relative to the main file - unless the path is
  absolute, in which case it is not altered. */
-int bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
* absolute, in which case it is not altered. */
+int BLI_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
 {
        /* be sure there is low chance of the path being too short */
        char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
-       const char *base_new= ((char **)pathbase_v)[0];
-       const char *base_old= ((char **)pathbase_v)[1];
+       const char *base_new = ((char **)pathbase_v)[0];
+       const char *base_old = ((char **)pathbase_v)[1];
 
-       if (strncmp(base_old, "//", 2) == 0) {
+       if (BLI_path_is_rel(base_old)) {
                printf("%s: error, old base path '%s' is not absolute.\n",
                       __func__, base_old);
-               return 0;
+               return FALSE;
        }
 
        /* Make referenced file absolute. This would be a side-effect of
-          BLI_cleanup_file, but we do it explicitely so we know if it changed. */
+        * BLI_cleanup_file, but we do it explicitly so we know if it changed. */
        BLI_strncpy(filepath, path_src, FILE_MAX);
        if (BLI_path_abs(filepath, base_old)) {
                /* Path was relative and is now absolute. Remap.
@@ -1120,10 +619,10 @@ int bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_sr
                BLI_cleanup_file(base_new, filepath);
                BLI_path_rel(filepath, base_new);
                BLI_strncpy(path_dst, filepath, FILE_MAX);
-               return 1;
+               return TRUE;
        }
        else {
                /* Path was not relative to begin with. */
-               return 0;
+               return FALSE;
        }
 }