Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / bpath.c
index 4018b757559f77a18de89309c53d13831ffce486..f3ff0f253e53dfbe55335c38a07385ba839d416d 100644 (file)
@@ -55,7 +55,6 @@
 #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 "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_sequencer.h"
-#include "BKE_image.h" /* so we can check the image's type */
+#include "BKE_image.h"
 
 #include "BKE_bpath.h"  /* own include */
 
+#ifndef _MSC_VER
+#  include "BLI_strict_flags.h"
+#endif
+
 static bool checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
 {
        ReportList *reports = (ReportList *)userdata;
@@ -94,7 +97,8 @@ static bool checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), c
 /* high level function */
 void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports)
 {
-       BKE_bpath_traverse_main(bmain, checkMissingFiles_visit_cb, BKE_BPATH_TRAVERSE_ABS, reports);
+       BKE_bpath_traverse_main(bmain, checkMissingFiles_visit_cb,
+                               BKE_BPATH_TRAVERSE_ABS | BKE_BPATH_TRAVERSE_SKIP_PACKED, reports);
 }
 
 typedef struct BPathRemap_Data {
@@ -106,7 +110,7 @@ typedef struct BPathRemap_Data {
        int count_failed;
 } BPathRemap_Data;
 
-static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
 {
        BPathRemap_Data *data = (BPathRemap_Data *)userdata;
 
@@ -132,6 +136,7 @@ static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const cha
 void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
 {
        BPathRemap_Data data = {NULL};
+       const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
 
        if (basedir[0] == '\0') {
                printf("%s: basedir='', this is a bug\n", __func__);
@@ -141,14 +146,14 @@ void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re
        data.basedir = basedir;
        data.reports = reports;
 
-       BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
+       BKE_bpath_traverse_main(bmain, bpath_relative_convert_visit_cb, flag, (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);
 }
 
-static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
 {
        BPathRemap_Data *data = (BPathRemap_Data *)userdata;
 
@@ -175,6 +180,7 @@ static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const cha
 void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
 {
        BPathRemap_Data data = {NULL};
+       const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
 
        if (basedir[0] == '\0') {
                printf("%s: basedir='', this is a bug\n", __func__);
@@ -184,7 +190,7 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
        data.basedir = basedir;
        data.reports = reports;
 
-       BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
+       BKE_bpath_traverse_main(bmain, bpath_absolute_convert_visit_cb, flag, (void *)&data);
 
        BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
                    "Total files %d | Changed %d | Failed %d",
@@ -201,18 +207,19 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
  * \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 bool missing_files_find__recursive(
+        char *filename_new,
+        const char *dirname,
+        const char *filename,
+        off_t *r_filesize,
+        int *r_recur_depth)
 {
        /* file searching stuff */
        DIR *dir;
        struct dirent *de;
-       struct stat status;
+       BLI_stat_t status;
        char path[FILE_MAX];
-       int size;
+       off_t size;
        bool found = false;
 
        dir = opendir(dirname);
@@ -220,35 +227,35 @@ static int findFileRecursive(char *filename_new,
        if (dir == NULL)
                return found;
 
-       if (*filesize == -1)
-               *filesize = 0;  /* dir opened fine */
+       if (*r_filesize == -1)
+               *r_filesize = 0;  /* dir opened fine */
 
        while ((de = readdir(dir)) != NULL) {
 
-               if (STREQ(".", de->d_name) || STREQ("..", de->d_name))
+               if (FILENAME_IS_CURRPAR(de->d_name))
                        continue;
 
                BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
 
-               if (BLI_stat(path, &status) != 0)
+               if (BLI_stat(path, &status) == -1)
                        continue;  /* cant stat, don't bother with this file, could print debug info here */
 
                if (S_ISREG(status.st_mode)) { /* is file */
                        if (STREQLEN(filename, de->d_name, FILE_MAX)) { /* name matches */
                                /* open the file to read its size */
                                size = status.st_size;
-                               if ((size > 0) && (size > *filesize)) { /* find the biggest file */
-                                       *filesize = size;
+                               if ((size > 0) && (size > *r_filesize)) { /* find the biggest file */
+                                       *r_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)++;
-                               found |= findFileRecursive(filename_new, path, filename, filesize, recur_depth);
-                               (*recur_depth)--;
+                       if (*r_recur_depth <= MAX_RECUR) {
+                               (*r_recur_depth)++;
+                               found |= missing_files_find__recursive(filename_new, path, filename, r_filesize, r_recur_depth);
+                               (*r_recur_depth)--;
                        }
                }
        }
@@ -263,14 +270,14 @@ typedef struct BPathFind_Data {
        bool find_all;
 } BPathFind_Data;
 
-static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const char *path_src)
 {
        BPathFind_Data *data = (BPathFind_Data *)userdata;
        char filename_new[FILE_MAX];
 
-       int filesize = -1;
+       off_t filesize = -1;
        int recur_depth = 0;
-       int found;
+       bool found;
 
        if (data->find_all == false) {
                if (BLI_exists(path_src)) {
@@ -280,9 +287,10 @@ static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char
 
        filename_new[0] = '\0';
 
-       found = findFileRecursive(filename_new,
-                                 data->searchdir, BLI_path_basename((char *)path_src),
-                                 &filesize, &recur_depth);
+       found = missing_files_find__recursive(
+               filename_new,
+               data->searchdir, BLI_path_basename(path_src),
+               &filesize, &recur_depth);
 
        if (filesize == -1) { /* could not open dir */
                BKE_reportf(data->reports, RPT_WARNING,
@@ -293,11 +301,18 @@ static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char
        else if (found == false) {
                BKE_reportf(data->reports, RPT_WARNING,
                            "Could not find '%s' in '%s'",
-                           BLI_path_basename((char *)path_src), data->searchdir);
+                           BLI_path_basename(path_src), data->searchdir);
                return false;
        }
        else {
+               bool was_relative = BLI_path_is_rel(path_dst);
+
                BLI_strncpy(path_dst, filename_new, FILE_MAX);
+
+               /* keep path relative if the previous one was relative */
+               if (was_relative)
+                       BLI_path_rel(path_dst, data->basedir);
+
                return true;
        }
 }
@@ -306,12 +321,14 @@ void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportLis
                                   const bool find_all)
 {
        struct BPathFind_Data data = {NULL};
+       const int flag = BKE_BPATH_TRAVERSE_ABS | BKE_BPATH_TRAVERSE_RELOAD_EDITED;
 
+       data.basedir = bmain->name;
        data.reports = reports;
        data.searchdir = searchpath;
        data.find_all = find_all;
 
-       BKE_bpath_traverse_main(bmain, findMissingFiles_visit_cb, BKE_BPATH_TRAVERSE_ABS, (void *)&data);
+       BKE_bpath_traverse_main(bmain, missing_files_find__visit_cb, flag, (void *)&data);
 }
 
 /* Run a visitor on a string, replacing the contents of the string as needed. */
@@ -330,6 +347,9 @@ static bool rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *ab
                path_src = path;
        }
 
+       /* so functions can check old value */
+       BLI_strncpy(path_dst, path, FILE_MAX);
+
        if (visit_cb(userdata, path_dst, path_src)) {
                BLI_strncpy(path, path_dst, FILE_MAX);
                return true;
@@ -350,6 +370,9 @@ static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR],
 
        BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file);
 
+       /* so functions can check old value */
+       BLI_strncpy(path_dst, path_src, FILE_MAX);
+
        if (absbase) {
                BLI_path_abs(path_src, absbase);
        }
@@ -379,7 +402,7 @@ static bool rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *a
        }
 
        if (visit_cb(userdata, path_dst, path_src)) {
-               MEM_freeN((*path));
+               MEM_freeN(*path);
                (*path) = BLI_strdup(path_dst);
                return true;
        }
@@ -388,12 +411,19 @@ static bool rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *a
        }
 }
 
+/* fix the image user "ok" tag after updating paths, so ImBufs get loaded */
+static void bpath_traverse_image_user_cb(Image *ima, ImageUser *iuser, void *customdata)
+{
+       if (ima == customdata)
+               iuser->ok = 1;
+}
+
 /* Run visitor function 'visit' on all paths contained in 'id'. */
 void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
 {
        const char *absbase = (flag & BKE_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
 
-       if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) {
+       if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && ID_IS_LINKED_DATABLOCK(id)) {
                return;
        }
 
@@ -402,9 +432,19 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
                {
                        Image *ima;
                        ima = (Image *)id;
-                       if (ima->packedfile == NULL || (flag & BKE_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);
+                       if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+                               if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+                                       if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
+                                               if (flag & BKE_BPATH_TRAVERSE_RELOAD_EDITED) {
+                                                       if (!BKE_image_has_packedfile(ima) &&
+                                                           /* image may have been painted onto (and not saved, T44543) */
+                                                           !BKE_image_is_dirty(ima))
+                                                       {
+                                                               BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+                                                               BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb);
+                                                       }
+                                               }
+                                       }
                                }
                        }
                        break;
@@ -421,20 +461,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
                {
                        Object *ob = (Object *)id;
                        ModifierData *md;
-                       ParticleSystem *psys;
-
-#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
 
                        /* do via modifiers instead */
 #if 0
@@ -450,16 +476,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
                                                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);
@@ -470,16 +486,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
                                }
                        }
 
-                       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:
@@ -555,19 +561,20 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
                                SEQ_BEGIN(scene->ed, seq)
                                {
                                        if (SEQ_HAS_PATH(seq)) {
-                                               if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM)) {
-                                                       rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name,
+                                               StripElem *se = seq->strip->stripdata;
+
+                                               if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
+                                                       rewrite_path_fixed_dirfile(seq->strip->dir, se->name,
                                                                                   visit_cb, absbase, bpath_user_data);
                                                }
-                                               else if (seq->type == SEQ_TYPE_IMAGE) {
+                                               else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
                                                        /* 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;
+                                                       unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
+                                                       unsigned int i;
 
                                                        if (flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) {
                                                                /* only operate on one path */
-                                                               len = MIN2(1, len);
+                                                               len = MIN2(1u, len);
                                                        }
 
                                                        for (i = 0; i < len; i++, se++) {
@@ -671,7 +678,7 @@ bool BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *pa
 /* -------------------------------------------------------------------- */
 /**
  * Backup/Restore/Free functions,
- * \note These functions assume the data won't chane order.
+ * \note These functions assume the data won't change order.
  */
 
 struct PathStore {
@@ -732,7 +739,7 @@ void BKE_bpath_list_restore(Main *bmain, const int flag, void *ls_handle)
 void BKE_bpath_list_free(void *ls_handle)
 {
        ListBase *ls = ls_handle;
-       BLI_assert(ls->first == NULL);  /* assumes we were used */
+       BLI_assert(BLI_listbase_is_empty(ls));  /* assumes we were used */
        BLI_freelistN(ls);
        MEM_freeN(ls);
 }