bpath
authorCampbell Barton <ideasman42@gmail.com>
Thu, 27 Oct 2011 03:40:12 +0000 (03:40 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 27 Oct 2011 03:40:12 +0000 (03:40 +0000)
- loop over all sequence images and pointcache
- option not to loop over library / packed data, expose in bpy.utils.blend_paths()

source/blender/blenlib/BLI_bpath.h
source/blender/blenlib/intern/bpath.c
source/blender/python/intern/bpy.c

index 6a167d6..1c95333 100644 (file)
@@ -42,12 +42,14 @@ struct ID;
    path has changed, and in that case, should write the result to pathOut. */
 typedef int (*BPathVisitor)(void *userdata, char *path_dst, const char *path_src);
 /* Executes 'visit' for each path associated with 'id'. */
-void bpath_traverse_id(struct Main *bmain, struct ID *id, BPathVisitor visit_cb, int flag, void *userdata);
-void bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVisitor visit_cb, int flag, void *userdata);
-void bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, int flag, void *userdata);
+void bpath_traverse_id(struct Main *bmain, struct ID *id, BPathVisitor visit_cb, const int flag, void *userdata);
+void bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVisitor visit_cb, const int flag, void *userdata);
+void bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata);
 int bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src);
 
-#define BPATH_TRAVERSE_ABS 1 /* convert paths to absolute */
+#define BPATH_TRAVERSE_ABS          (1<<0) /* convert paths to absolute */
+#define BPATH_TRAVERSE_SKIP_LIBRARY (1<<2) /* skip library paths */
+#define BPATH_TRAVERSE_SKIP_PACKED  (1<<3) /* skip packed data */
 
 /* high level funcs */
 
@@ -57,6 +59,4 @@ void makeFilesRelative(struct Main *bmain, const char *basedir, struct ReportLis
 void makeFilesAbsolute(struct Main *bmain, const char *basedir, struct ReportList *reports);
 void findMissingFiles(struct Main *bmain, const char *searchpath, struct ReportList *reports);
 
-#define BPATH_USE_PACKED 1
-
 #endif // BLI_BPATH_H
index 36b81d9..af12a59 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 dont support.
+ * - passing output paths to the visitor?, like render out.
+ * - passing sequence strips with many images.
+ * - passing directory paths - visitors dont know which path is a dir or a file.
+ * */
 
 #include <sys/stat.h>
 
 
 #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_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_object_types.h"
-#include "DNA_object_fluidsim.h"
+#include "DNA_scene_types.h"
+#include "DNA_smoke_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_bpath.h"
 #include "BLI_utildefines.h"
 
-#include "BKE_image.h" /* so we can check the image's type */
-#include "BKE_sequencer.h"
+#include "BKE_library.h"
 #include "BKE_main.h"
-#include "BKE_utildefines.h"
 #include "BKE_report.h"
-#include "BKE_library.h"
+#include "BKE_sequencer.h"
+#include "BKE_utildefines.h"
+#include "BKE_image.h" /* so we can check the image's type */
 
 static int checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
 {
@@ -349,29 +360,96 @@ static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *ab
 }
 
 /* Run visitor function 'visit' on all paths contained in 'id'. */
-void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, int flag, void *userdata)
+void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *userdata)
 {
        Image *ima;
        const char *absbase= (flag & BPATH_TRAVERSE_ABS) ? (id->lib ? id->lib->filepath : bmain->name) : NULL;
 
+       if ((flag & BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) {
+               return;
+       }
 
        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, absbase, userdata);
+               ima= (Image *)id;
+               if (ima->packedfile == NULL || (flag & 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, userdata);
+                       }
+               }
+               break;
+       case ID_BR:
+               {
+                       Brush *brush= (Brush *)id;
+                       if (brush->icon_filepath[0]) {
+                               rewrite_path_fixed(brush->icon_filepath, visit_cb, absbase, userdata);
+                       }
+               }
                break;
        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, userdata);  \
+                       }                                                                  \
+               }                                                                      \
+       }                                                                          \
+
+
                {
                        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, userdata);
                        }
-                       /* TODO: add modifiers, e.g. point cache for particles. */
+#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, userdata);
+                                       }
+                               }
+                               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);
+                               }
+                       }
+
+                       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:
-               rewrite_path_fixed(((bSound *)id)->name, visit_cb, absbase, userdata);
+               {
+                       bSound *sound= (bSound *)id;
+                       if (sound->packedfile == NULL || (flag & BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+                               rewrite_path_fixed(sound->name, visit_cb, absbase, userdata);
+                       }
+               }
                break;
        case ID_TXT:
                if (((Text*)id)->name) {
@@ -379,8 +457,13 @@ void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, int flag, voi
                }
                break;
        case ID_VF:
-               if (strcmp(((VFont*)id)->name, FO_BUILTIN_NAME) != 0) {
-                       rewrite_path_fixed(((VFont *)id)->name, visit_cb, absbase, userdata);
+               {
+                       VFont *vf= (VFont *)id;
+                       if (vf->packedfile == NULL || (flag & BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+                               if (strcmp(vf->name, FO_BUILTIN_NAME) != 0) {
+                                       rewrite_path_fixed(((VFont *)id)->name, visit_cb, absbase, userdata);
+                               }
+                       }
                }
                break;
        case ID_TE:
@@ -405,9 +488,19 @@ void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, int flag, voi
 
                                SEQ_BEGIN(scene->ed, seq) {
                                        if (SEQ_HAS_PATH(seq)) {
-                                               if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) {
+                                               if (ELEM(seq->type, SEQ_MOVIE, SEQ_SOUND)) {
                                                        rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name, visit_cb, absbase, userdata);
                                                }
+                                               else if (seq->type == SEQ_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;
+
+                                                       for(i= 0; i < len; i++, se++) {
+                                                               rewrite_path_fixed_dirfile(seq->strip->dir, se->name, visit_cb, absbase, userdata);
+                                                       }
+                                               }
                                                else {
                                                        /* simple case */
                                                        rewrite_path_fixed(seq->strip->dir, visit_cb, absbase, userdata);
@@ -438,14 +531,13 @@ void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, int flag, voi
                        }
                }
                break;
-       /* TODO: add other ID types e.g. object (modifiers) */
        default:
                /* Nothing to do for other IDs that don't contain file paths. */
                break;
        }
 }
 
-void bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, int flag, void *userdata)
+void bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *userdata)
 {
        ID *id;
        for(id= lb->first; id; id= id->next) {
@@ -453,7 +545,7 @@ void bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, in
        }
 }
 
-void bpath_traverse_main(Main *bmain, BPathVisitor visit_cb, int flag, void *userdata)
+void bpath_traverse_main(Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata)
 {
        ListBase *lbarray[MAX_LIBARRAY];
        int a= set_listbasepointers(bmain, lbarray);
@@ -472,7 +564,7 @@ int bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_sr
        if (strncmp(base_old, "//", 2) == 0) {
                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
@@ -485,10 +577,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;
        }
 }
index d740f7c..dfb7a1e 100644 (file)
@@ -91,12 +91,16 @@ static int bpy_blend_paths_visit_cb(void *userdata, char *UNUSED(path_dst), cons
 }
 
 PyDoc_STRVAR(bpy_blend_paths_doc,
-".. function:: blend_paths(absolute=False)\n"
+".. function:: blend_paths(absolute=False, packed=False, local=False)\n"
 "\n"
 "   Returns a list of paths to external files referenced by the loaded .blend file.\n"
 "\n"
 "   :arg absolute: When true the paths returned are made absolute.\n"
 "   :type absolute: boolean\n"
+"   :arg packed: When true skip file paths for packed data.\n"
+"   :type packed: boolean\n"
+"   :arg local: When true skip linked library paths.\n"
+"   :type local: boolean\n"
 "   :return: path list.\n"
 "   :rtype: list of strings\n"
 );
@@ -105,16 +109,21 @@ static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObjec
        int flag= 0;
        PyObject *list;
 
-       int absolute= 0;
-       static const char *kwlist[]= {"absolute", NULL};
+       int absolute= FALSE;
+       int packed=   FALSE;
+       int local=    FALSE;
+       static const char *kwlist[]= {"absolute", "packed", "local", NULL};
 
-       if (!PyArg_ParseTupleAndKeywords(args, kw, "|i:blend_paths", (char **)kwlist, &absolute))
+       if (!PyArg_ParseTupleAndKeywords(args, kw, "|ii:blend_paths",
+                                        (char **)kwlist, &absolute, &packed))
+       {
                return NULL;
-
-       if (absolute) {
-               flag |= BPATH_TRAVERSE_ABS;
        }
 
+       if (absolute) flag |= BPATH_TRAVERSE_ABS;
+       if (!packed)  flag |= BPATH_TRAVERSE_SKIP_PACKED;
+       if (local)    flag |= BPATH_TRAVERSE_SKIP_LIBRARY;
+
        list= PyList_New(0);
 
        bpath_traverse_main(G.main, bpy_blend_paths_visit_cb, flag, (void *)list);
@@ -137,10 +146,10 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj
                return NULL;
        
        /* stupid string compare */
-       if     (!strcmp(type, "DATAFILES")) folder_id= BLENDER_USER_DATAFILES;
-       else if (!strcmp(type, "CONFIG"))   folder_id= BLENDER_USER_CONFIG;
-       else if (!strcmp(type, "SCRIPTS"))  folder_id= BLENDER_USER_SCRIPTS;
-       else if (!strcmp(type, "AUTOSAVE")) folder_id= BLENDER_USER_AUTOSAVE;
+       if      (!strcmp(type, "DATAFILES")) folder_id= BLENDER_USER_DATAFILES;
+       else if (!strcmp(type, "CONFIG"))    folder_id= BLENDER_USER_CONFIG;
+       else if (!strcmp(type, "SCRIPTS"))   folder_id= BLENDER_USER_SCRIPTS;
+       else if (!strcmp(type, "AUTOSAVE"))  folder_id= BLENDER_USER_AUTOSAVE;
        else {
                PyErr_SetString(PyExc_ValueError, "invalid resource argument");
                return NULL;