|
Blender
V2.59
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): Campbell barton 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <sys/stat.h> 00035 00036 #include <string.h> 00037 #include <assert.h> 00038 00039 /* path/file handeling stuff */ 00040 #ifndef WIN32 00041 #include <dirent.h> 00042 #include <unistd.h> 00043 #else 00044 #include <io.h> 00045 #include "BLI_winstuff.h" 00046 #endif 00047 00048 #include "MEM_guardedalloc.h" 00049 00050 #include "DNA_mesh_types.h" 00051 #include "DNA_scene_types.h" /* to get the current frame */ 00052 #include "DNA_image_types.h" 00053 #include "DNA_texture_types.h" 00054 #include "DNA_text_types.h" 00055 #include "DNA_sound_types.h" 00056 #include "DNA_sequence_types.h" 00057 #include "DNA_vfont_types.h" 00058 #include "DNA_windowmanager_types.h" 00059 00060 #include "BLI_blenlib.h" 00061 #include "BLI_bpath.h" 00062 #include "BLI_utildefines.h" 00063 00064 #include "BKE_global.h" 00065 #include "BKE_image.h" /* so we can check the image's type */ 00066 #include "BKE_sequencer.h" 00067 #include "BKE_main.h" 00068 #include "BKE_utildefines.h" 00069 #include "BKE_report.h" 00070 00071 typedef struct BPathIteratorSeqData 00072 { 00073 int totseq; 00074 int seq; 00075 struct Sequence **seqar; /* Sequence */ 00076 struct Scene *scene; /* Current scene */ 00077 } BPathIteratorSeqData; 00078 00079 typedef struct BPathIterator 00080 { 00081 char* _path; /* never access directly, use BLI_bpathIterator_getPath */ 00082 const char* _lib; 00083 const char* _name; 00084 void* data; 00085 int len; 00086 int type; 00087 int flag; /* iterator options */ 00088 00089 void (*setpath_callback)(struct BPathIterator *, const char *); 00090 void (*getpath_callback)(struct BPathIterator *, char *); 00091 00092 const char* base_path; /* base path, the directory the blend file is in - normally bmain->name */ 00093 00094 Main *bmain; 00095 00096 /* only for seq data */ 00097 struct BPathIteratorSeqData seqdata; 00098 } BPathIterator; 00099 00100 #define FILE_MAX 240 00101 00102 00103 /* TODO - BPATH_PLUGIN, BPATH_SEQ */ 00104 enum BPathTypes { 00105 BPATH_IMAGE= 0, 00106 BPATH_TEXTURE, 00107 BPATH_TEXT, 00108 BPATH_SOUND, 00109 BPATH_FONT, 00110 BPATH_LIB, 00111 BPATH_SEQ, 00112 BPATH_CDATA, 00113 00114 BPATH_DONE 00115 }; 00116 00117 void BLI_bpathIterator_init(struct BPathIterator **bpi_pt, Main *bmain, const char *basedir, const int flag) 00118 { 00119 BPathIterator *bpi; 00120 00121 bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_init"); 00122 *bpi_pt= bpi; 00123 00124 bpi->type= BPATH_IMAGE; 00125 bpi->data= NULL; 00126 00127 bpi->getpath_callback= NULL; 00128 bpi->setpath_callback= NULL; 00129 00130 /* Sequencer specific */ 00131 bpi->seqdata.totseq= 0; 00132 bpi->seqdata.seq= 0; 00133 bpi->seqdata.seqar= NULL; 00134 bpi->seqdata.scene= NULL; 00135 00136 bpi->flag= flag; 00137 00138 bpi->base_path= basedir; /* normally bmain->name */ 00139 bpi->bmain= bmain; 00140 00141 BLI_bpathIterator_step(bpi); 00142 } 00143 00144 #if 0 00145 static void BLI_bpathIterator_alloc(struct BPathIterator **bpi) 00146 { 00147 *bpi= MEM_mallocN(sizeof(BPathIterator), "BLI_bpathIterator_alloc"); 00148 } 00149 #endif 00150 00151 void BLI_bpathIterator_free(struct BPathIterator *bpi) 00152 { 00153 if (bpi->seqdata.seqar) 00154 MEM_freeN((void *)bpi->seqdata.seqar); 00155 bpi->seqdata.seqar= NULL; 00156 bpi->seqdata.scene= NULL; 00157 00158 MEM_freeN(bpi); 00159 } 00160 00161 void BLI_bpathIterator_getPath(struct BPathIterator *bpi, char *path) 00162 { 00163 if (bpi->getpath_callback) { 00164 bpi->getpath_callback(bpi, path); 00165 } 00166 else { 00167 strcpy(path, bpi->_path); /* warning, we assume 'path' are long enough */ 00168 } 00169 } 00170 00171 void BLI_bpathIterator_setPath(struct BPathIterator *bpi, const char *path) 00172 { 00173 if (bpi->setpath_callback) { 00174 bpi->setpath_callback(bpi, path); 00175 } 00176 else { 00177 strcpy(bpi->_path, path); /* warning, we assume 'path' are long enough */ 00178 } 00179 } 00180 00181 void BLI_bpathIterator_getPathExpanded(struct BPathIterator *bpi, char *path_expanded) 00182 { 00183 const char *libpath; 00184 00185 BLI_bpathIterator_getPath(bpi, path_expanded); 00186 libpath= BLI_bpathIterator_getLib(bpi); 00187 00188 if (libpath) { /* check the files location relative to its library path */ 00189 BLI_path_abs(path_expanded, libpath); 00190 } 00191 else { /* local data, use the blend files path */ 00192 BLI_path_abs(path_expanded, bpi->base_path); 00193 } 00194 BLI_cleanup_file(NULL, path_expanded); 00195 } 00196 const char* BLI_bpathIterator_getLib(struct BPathIterator *bpi) 00197 { 00198 return bpi->_lib; 00199 } 00200 const char* BLI_bpathIterator_getName(struct BPathIterator *bpi) 00201 { 00202 return bpi->_name; 00203 } 00204 int BLI_bpathIterator_getType(struct BPathIterator *bpi) 00205 { 00206 return bpi->type; 00207 } 00208 unsigned int BLI_bpathIterator_getPathMaxLen(struct BPathIterator *bpi) 00209 { 00210 return bpi->len; 00211 } 00212 const char* BLI_bpathIterator_getBasePath(struct BPathIterator *bpi) 00213 { 00214 return bpi->base_path; 00215 } 00216 00217 /* gets the first or the next image that has a path - not a viewer node or generated image */ 00218 static struct Image *ima_stepdata__internal(struct Image *ima, const int step_next, const int flag) 00219 { 00220 if (ima==NULL) 00221 return NULL; 00222 00223 if (step_next) 00224 ima= ima->id.next; 00225 00226 while (ima) { 00227 if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { 00228 if(ima->packedfile==NULL || (flag & BPATH_USE_PACKED)) { 00229 break; 00230 } 00231 } 00232 /* image is not a image with a path, skip it */ 00233 ima= ima->id.next; 00234 } 00235 return ima; 00236 } 00237 00238 static struct Tex *tex_stepdata__internal(struct Tex *tex, const int step_next, const int UNUSED(flag)) 00239 { 00240 if (tex==NULL) 00241 return NULL; 00242 00243 if (step_next) 00244 tex= tex->id.next; 00245 00246 while (tex) { 00247 if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format)) 00248 break; 00249 /* image is not a image with a path, skip it */ 00250 tex= tex->id.next; 00251 } 00252 return tex; 00253 } 00254 00255 static struct Text *text_stepdata__internal(struct Text *text, const int step_next, const int UNUSED(flag)) 00256 { 00257 if (text==NULL) 00258 return NULL; 00259 00260 if (step_next) 00261 text= text->id.next; 00262 00263 while (text) { 00264 if (text->name) 00265 break; 00266 /* image is not a image with a path, skip it */ 00267 text= text->id.next; 00268 } 00269 return text; 00270 } 00271 00272 static struct VFont *vf_stepdata__internal(struct VFont *vf, const int step_next, const int flag) 00273 { 00274 if (vf==NULL) 00275 return NULL; 00276 00277 if (step_next) 00278 vf= vf->id.next; 00279 00280 while (vf) { 00281 if (strcmp(vf->name, FO_BUILTIN_NAME)!=0) { 00282 if(vf->packedfile==NULL || (flag & BPATH_USE_PACKED)) { 00283 break; 00284 } 00285 } 00286 00287 /* font with no path, skip it */ 00288 vf= vf->id.next; 00289 } 00290 return vf; 00291 } 00292 00293 static struct bSound *snd_stepdata__internal(struct bSound *snd, int step_next, const int flag) 00294 { 00295 if (snd==NULL) 00296 return NULL; 00297 00298 if (step_next) 00299 snd= snd->id.next; 00300 00301 while (snd) { 00302 if(snd->packedfile==NULL || (flag & BPATH_USE_PACKED)) { 00303 break; 00304 } 00305 00306 /* font with no path, skip it */ 00307 snd= snd->id.next; 00308 } 00309 return snd; 00310 } 00311 00312 static struct Sequence *seq_stepdata__internal(struct BPathIterator *bpi, int step_next) 00313 { 00314 Editing *ed; 00315 Sequence *seq; 00316 00317 /* Initializing */ 00318 if (bpi->seqdata.scene==NULL) { 00319 bpi->seqdata.scene= bpi->bmain->scene.first; 00320 } 00321 00322 if (step_next) { 00323 bpi->seqdata.seq++; 00324 } 00325 00326 while (bpi->seqdata.scene) { 00327 ed= seq_give_editing(bpi->seqdata.scene, 0); 00328 if (ed) { 00329 if (bpi->seqdata.seqar == NULL) { 00330 /* allocate the sequencer array */ 00331 seq_array(ed, &bpi->seqdata.seqar, &bpi->seqdata.totseq, 0); 00332 bpi->seqdata.seq= 0; 00333 } 00334 00335 if (bpi->seqdata.seq >= bpi->seqdata.totseq) { 00336 seq= NULL; 00337 } 00338 else { 00339 seq= bpi->seqdata.seqar[bpi->seqdata.seq]; 00340 while (!SEQ_HAS_PATH(seq) && seq->plugin==NULL) { 00341 bpi->seqdata.seq++; 00342 if (bpi->seqdata.seq >= bpi->seqdata.totseq) { 00343 seq= NULL; 00344 break; 00345 } 00346 seq= bpi->seqdata.seqar[bpi->seqdata.seq]; 00347 } 00348 } 00349 if (seq) { 00350 return seq; 00351 } 00352 else { 00353 /* keep looking through the next scene, reallocate seq array */ 00354 if (bpi->seqdata.seqar) { 00355 MEM_freeN((void *)bpi->seqdata.seqar); 00356 bpi->seqdata.seqar= NULL; 00357 } 00358 bpi->seqdata.scene= bpi->seqdata.scene->id.next; 00359 } 00360 } 00361 else { 00362 /* no seq data in this scene, next */ 00363 bpi->seqdata.scene= bpi->seqdata.scene->id.next; 00364 } 00365 } 00366 00367 return NULL; 00368 } 00369 00370 static void seq_getpath(struct BPathIterator *bpi, char *path) 00371 { 00372 Sequence *seq= (Sequence *)bpi->data; 00373 00374 00375 path[0]= '\0'; /* incase we cant get the path */ 00376 if (seq==NULL) return; 00377 if (SEQ_HAS_PATH(seq)) { 00378 if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) { 00379 BLI_strncpy(path, seq->strip->dir, FILE_MAX); 00380 BLI_add_slash(path); /* incase its missing */ 00381 if (seq->strip->stripdata) { /* should always be true! */ 00382 /* Using the first image is weak for image sequences */ 00383 strcat(path, seq->strip->stripdata->name); 00384 } 00385 } 00386 else { 00387 /* simple case */ 00388 BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir)); 00389 } 00390 } 00391 else if (seq->plugin) { 00392 BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name)); 00393 } 00394 } 00395 00396 static void seq_setpath(struct BPathIterator *bpi, const char *path) 00397 { 00398 Sequence *seq= (Sequence *)bpi->data; 00399 if (seq==NULL) return; 00400 00401 if (SEQ_HAS_PATH(seq)) { 00402 if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) { 00403 BLI_split_dirfile(path, seq->strip->dir, seq->strip->stripdata->name); 00404 } 00405 else { 00406 /* simple case */ 00407 BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir)); 00408 } 00409 } 00410 else if (seq->plugin) { 00411 BLI_strncpy(seq->plugin->name, path, sizeof(seq->plugin->name)); 00412 } 00413 } 00414 00415 static void text_getpath(struct BPathIterator *bpi, char *path) 00416 { 00417 Text *text= (Text *)bpi->data; 00418 path[0]= '\0'; /* incase we cant get the path */ 00419 if(text->name) { 00420 strcpy(path, text->name); 00421 } 00422 } 00423 00424 static void text_setpath(struct BPathIterator *bpi, const char *path) 00425 { 00426 Text *text= (Text *)bpi->data; 00427 if (text==NULL) return; 00428 00429 if(text->name) { 00430 MEM_freeN(text->name); 00431 } 00432 00433 text->name= BLI_strdup(path); 00434 } 00435 00436 static struct Mesh *cdata_stepdata__internal(struct Mesh *me, int step_next) 00437 { 00438 if (me==NULL) 00439 return NULL; 00440 00441 if (step_next) 00442 me= me->id.next; 00443 00444 while (me) { 00445 if (me->fdata.external) { 00446 break; 00447 } 00448 00449 me= me->id.next; 00450 } 00451 return me; 00452 } 00453 00454 static void bpi_type_step__internal(struct BPathIterator *bpi) 00455 { 00456 bpi->type++; /* advance to the next type */ 00457 bpi->data= NULL; 00458 00459 switch (bpi->type) { 00460 case BPATH_SEQ: 00461 bpi->getpath_callback= seq_getpath; 00462 bpi->setpath_callback= seq_setpath; 00463 break; 00464 case BPATH_TEXT: /* path is malloc'd */ 00465 bpi->getpath_callback= text_getpath; 00466 bpi->setpath_callback= text_setpath; 00467 break; 00468 default: 00469 bpi->getpath_callback= NULL; 00470 bpi->setpath_callback= NULL; 00471 break; 00472 } 00473 } 00474 00475 void BLI_bpathIterator_step(struct BPathIterator *bpi) 00476 { 00477 while (bpi->type != BPATH_DONE) { 00478 00479 if ((bpi->type) == BPATH_IMAGE) { 00480 /*if (bpi->data) bpi->data= ((ID *)bpi->data)->next;*/ 00481 if (bpi->data) bpi->data= ima_stepdata__internal((Image *)bpi->data, 1, bpi->flag); /* must skip images that have no path */ 00482 else bpi->data= ima_stepdata__internal(bpi->bmain->image.first, 0, bpi->flag); 00483 00484 if (bpi->data) { 00485 /* get the path info from this datatype */ 00486 Image *ima= (Image *)bpi->data; 00487 00488 bpi->_lib= ima->id.lib ? ima->id.lib->filepath : NULL; 00489 bpi->_path= ima->name; 00490 bpi->_name= ima->id.name+2; 00491 bpi->len= sizeof(ima->name); 00492 00493 /* we are done, advancing to the next item, this type worked fine */ 00494 break; 00495 00496 } 00497 else { 00498 bpi_type_step__internal(bpi); 00499 } 00500 } 00501 00502 if ((bpi->type) == BPATH_TEXTURE) { 00503 /*if (bpi->data) bpi->data= ((ID *)bpi->data)->next;*/ 00504 if (bpi->data) bpi->data= tex_stepdata__internal( (Tex *)bpi->data, 1, bpi->flag); /* must skip images that have no path */ 00505 else bpi->data= tex_stepdata__internal(bpi->bmain->tex.first, 0, bpi->flag); 00506 00507 if (bpi->data) { 00508 /* get the path info from this datatype */ 00509 Tex *tex= (Tex *)bpi->data; 00510 00511 if(tex->type == TEX_VOXELDATA) { 00512 bpi->_lib= tex->id.lib ? tex->id.lib->filepath : NULL; 00513 bpi->_path= tex->vd->source_path; 00514 bpi->_name= tex->id.name+2; 00515 bpi->len= sizeof(tex->vd->source_path); 00516 } 00517 else { 00518 assert(!"Texture has no path, incorrect step 'tex_stepdata__internal'"); 00519 } 00520 00521 /* we are done, advancing to the next item, this type worked fine */ 00522 break; 00523 00524 } 00525 else { 00526 bpi_type_step__internal(bpi); 00527 } 00528 } 00529 00530 if ((bpi->type) == BPATH_TEXT) { 00531 /*if (bpi->data) bpi->data= ((ID *)bpi->data)->next;*/ 00532 if (bpi->data) bpi->data= text_stepdata__internal((Text *)bpi->data, 1, bpi->flag); /* must skip images that have no path */ 00533 else bpi->data= text_stepdata__internal(bpi->bmain->text.first, 0, bpi->flag); 00534 00535 if (bpi->data) { 00536 /* get the path info from this datatype */ 00537 Text *text= (Text *)bpi->data; 00538 00539 bpi->_lib= text->id.lib ? text->id.lib->filepath : NULL; 00540 bpi->_path= NULL; /* bpi->path= text->name; */ /* get/set functions override. */ 00541 bpi->_name= text->id.name+2; 00542 bpi->len= FILE_MAX; /* malloc'd but limit anyway since large paths may mess up other areas */ 00543 00544 /* we are done, advancing to the next item, this type worked fine */ 00545 break; 00546 00547 } 00548 else { 00549 bpi_type_step__internal(bpi); 00550 } 00551 } 00552 else if ((bpi->type) == BPATH_SOUND) { 00553 if (bpi->data) bpi->data= snd_stepdata__internal((bSound *)bpi->data, 1, bpi->flag); /* must skip images that have no path */ 00554 else bpi->data= snd_stepdata__internal(bpi->bmain->sound.first, 0, bpi->flag); 00555 00556 if (bpi->data) { 00557 /* get the path info from this datatype */ 00558 bSound *snd= (bSound *)bpi->data; 00559 00560 bpi->_lib= snd->id.lib ? snd->id.lib->filepath : NULL; 00561 bpi->_path= snd->name; 00562 bpi->_name= snd->id.name+2; 00563 bpi->len= sizeof(snd->name); 00564 00565 /* we are done, advancing to the next item, this type worked fine */ 00566 break; 00567 } 00568 else { 00569 bpi_type_step__internal(bpi); 00570 } 00571 } 00572 else if ((bpi->type) == BPATH_FONT) { 00573 00574 if (bpi->data) bpi->data= vf_stepdata__internal((VFont *)bpi->data, 1, bpi->flag); 00575 else bpi->data= vf_stepdata__internal(bpi->bmain->vfont.first, 0, bpi->flag); 00576 00577 if (bpi->data) { 00578 /* get the path info from this datatype */ 00579 VFont *vf= (VFont *)bpi->data; 00580 00581 bpi->_lib= vf->id.lib ? vf->id.lib->filepath : NULL; 00582 bpi->_path= vf->name; 00583 bpi->_name= vf->id.name+2; 00584 bpi->len= sizeof(vf->name); 00585 00586 /* we are done, advancing to the next item, this type worked fine */ 00587 break; 00588 } 00589 else { 00590 bpi_type_step__internal(bpi); 00591 } 00592 00593 } 00594 else if ((bpi->type) == BPATH_LIB) { 00595 if (bpi->data) bpi->data= ((ID *)bpi->data)->next; 00596 else bpi->data= bpi->bmain->library.first; 00597 00598 if (bpi->data) { 00599 /* get the path info from this datatype */ 00600 Library *lib= (Library *)bpi->data; 00601 00602 bpi->_lib= NULL; 00603 bpi->_path= lib->name; 00604 bpi->_name= NULL; 00605 bpi->len= sizeof(lib->name); 00606 00607 /* we are done, advancing to the next item, this type worked fine */ 00608 break; 00609 } 00610 else { 00611 bpi_type_step__internal(bpi); 00612 } 00613 } 00614 else if ((bpi->type) == BPATH_SEQ) { 00615 if (bpi->data) bpi->data= seq_stepdata__internal( bpi, 1 ); 00616 else bpi->data= seq_stepdata__internal( bpi, 0 ); 00617 if (bpi->data) { 00618 Sequence *seq= (Sequence *)bpi->data; 00619 bpi->_lib= NULL; 00620 bpi->_name= seq->name+2; 00621 bpi->len= seq->plugin ? sizeof(seq->plugin->name) : sizeof(seq->strip->dir) + sizeof(seq->strip->stripdata->name); 00622 break; 00623 } 00624 else { 00625 bpi_type_step__internal(bpi); 00626 } 00627 } 00628 else if ((bpi->type) == BPATH_CDATA) { 00629 if (bpi->data) bpi->data= cdata_stepdata__internal( bpi->data, 1 ); 00630 else bpi->data= cdata_stepdata__internal( bpi->bmain->mesh.first, 0 ); 00631 00632 if (bpi->data) { 00633 Mesh *me= (Mesh *)bpi->data; 00634 bpi->_lib= me->id.lib ? me->id.lib->filepath : NULL; 00635 bpi->_path= me->fdata.external->filename; 00636 bpi->_name= me->id.name+2; 00637 bpi->len= sizeof(me->fdata.external->filename); 00638 break; 00639 } 00640 else { 00641 bpi_type_step__internal(bpi); 00642 } 00643 } 00644 } 00645 } 00646 00647 int BLI_bpathIterator_isDone( struct BPathIterator *bpi) { 00648 return bpi->type==BPATH_DONE; 00649 } 00650 00651 /* include the path argument */ 00652 static void bpath_as_report(struct BPathIterator *bpi, const char *message, ReportList *reports) 00653 { 00654 const char *prefix; 00655 const char *name; 00656 char path_expanded[FILE_MAXDIR*2]; 00657 00658 if(reports==NULL) 00659 return; 00660 00661 switch(BLI_bpathIterator_getType(bpi)) { 00662 case BPATH_IMAGE: 00663 prefix= "Image"; 00664 break; 00665 case BPATH_TEXTURE: 00666 prefix= "Texture"; 00667 break; 00668 case BPATH_TEXT: 00669 prefix= "Text"; 00670 break; 00671 case BPATH_SOUND: 00672 prefix= "Sound"; 00673 break; 00674 case BPATH_FONT: 00675 prefix= "Font"; 00676 break; 00677 case BPATH_LIB: 00678 prefix= "Library"; 00679 break; 00680 case BPATH_SEQ: 00681 prefix= "Sequence"; 00682 break; 00683 case BPATH_CDATA: 00684 prefix= "Mesh Data"; 00685 break; 00686 default: 00687 prefix= "Unknown"; 00688 break; 00689 } 00690 00691 name= BLI_bpathIterator_getName(bpi); 00692 BLI_bpathIterator_getPathExpanded(bpi, path_expanded); 00693 00694 if(reports) { 00695 if (name) BKE_reportf(reports, RPT_WARNING, "%s \"%s\", \"%s\": %s", prefix, name, path_expanded, message); 00696 else BKE_reportf(reports, RPT_WARNING, "%s \"%s\": %s", prefix, path_expanded, message); 00697 } 00698 00699 } 00700 00701 /* high level function */ 00702 void checkMissingFiles(Main *bmain, ReportList *reports) { 00703 struct BPathIterator *bpi; 00704 00705 /* be sure there is low chance of the path being too short */ 00706 char filepath_expanded[FILE_MAXDIR*2]; 00707 00708 BLI_bpathIterator_init(&bpi, bmain, bmain->name, 0); 00709 while (!BLI_bpathIterator_isDone(bpi)) { 00710 BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded); 00711 00712 if (!BLI_exists(filepath_expanded)) 00713 bpath_as_report(bpi, "file not found", reports); 00714 00715 BLI_bpathIterator_step(bpi); 00716 } 00717 BLI_bpathIterator_free(bpi); 00718 } 00719 00720 /* dont log any errors at the moment, should probably do this */ 00721 void makeFilesRelative(Main *bmain, const char *basedir, ReportList *reports) { 00722 int tot= 0, changed= 0, failed= 0, linked= 0; 00723 struct BPathIterator *bpi; 00724 char filepath[FILE_MAX]; 00725 const char *libpath; 00726 00727 /* be sure there is low chance of the path being too short */ 00728 char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE]; 00729 00730 if(basedir[0] == '\0') { 00731 printf("makeFilesRelative: basedir='', this is a bug\n"); 00732 return; 00733 } 00734 00735 BLI_bpathIterator_init(&bpi, bmain, basedir, 0); 00736 while (!BLI_bpathIterator_isDone(bpi)) { 00737 BLI_bpathIterator_getPath(bpi, filepath); 00738 libpath= BLI_bpathIterator_getLib(bpi); 00739 00740 if(strncmp(filepath, "//", 2)) { 00741 if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */ 00742 linked++; 00743 } 00744 else { /* local data, use the blend files path */ 00745 BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative)); 00746 /* Important BLI_cleanup_dir runs before the path is made relative 00747 * because it wont work for paths that start with "//../" */ 00748 BLI_cleanup_file(bpi->base_path, filepath_relative); /* fix any /foo/../foo/ */ 00749 BLI_path_rel(filepath_relative, bpi->base_path); 00750 /* be safe and check the length */ 00751 if (BLI_bpathIterator_getPathMaxLen(bpi) <= strlen(filepath_relative)) { 00752 bpath_as_report(bpi, "couldn't make path relative (too long)", reports); 00753 failed++; 00754 } 00755 else { 00756 if(strncmp(filepath_relative, "//", 2)==0) { 00757 BLI_bpathIterator_setPath(bpi, filepath_relative); 00758 changed++; 00759 } 00760 else { 00761 bpath_as_report(bpi, "couldn't make path relative", reports); 00762 failed++; 00763 } 00764 } 00765 } 00766 } 00767 BLI_bpathIterator_step(bpi); 00768 tot++; 00769 } 00770 BLI_bpathIterator_free(bpi); 00771 00772 if(reports) 00773 BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); 00774 } 00775 00776 /* dont log any errors at the moment, should probably do this - 00777 * Verry similar to makeFilesRelative - keep in sync! */ 00778 void makeFilesAbsolute(Main *bmain, const char *basedir, ReportList *reports) 00779 { 00780 int tot= 0, changed= 0, failed= 0, linked= 0; 00781 00782 struct BPathIterator *bpi; 00783 char filepath[FILE_MAX]; 00784 const char *libpath; 00785 00786 /* be sure there is low chance of the path being too short */ 00787 char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE]; 00788 00789 if(basedir[0] == '\0') { 00790 printf("makeFilesAbsolute: basedir='', this is a bug\n"); 00791 return; 00792 } 00793 00794 BLI_bpathIterator_init(&bpi, bmain, basedir, 0); 00795 while (!BLI_bpathIterator_isDone(bpi)) { 00796 BLI_bpathIterator_getPath(bpi, filepath); 00797 libpath= BLI_bpathIterator_getLib(bpi); 00798 00799 if(strncmp(filepath, "//", 2)==0) { 00800 if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */ 00801 linked++; 00802 } 00803 else { /* get the expanded path and check it is relative or too long */ 00804 BLI_bpathIterator_getPathExpanded(bpi, filepath_absolute); 00805 BLI_cleanup_file(bpi->base_path, filepath_absolute); /* fix any /foo/../foo/ */ 00806 /* to be safe, check the length */ 00807 if (BLI_bpathIterator_getPathMaxLen(bpi) <= strlen(filepath_absolute)) { 00808 bpath_as_report(bpi, "couldn't make absolute (too long)", reports); 00809 failed++; 00810 } 00811 else { 00812 if(strncmp(filepath_absolute, "//", 2)) { 00813 BLI_bpathIterator_setPath(bpi, filepath_absolute); 00814 changed++; 00815 } 00816 else { 00817 bpath_as_report(bpi, "couldn't make absolute", reports); 00818 failed++; 00819 } 00820 } 00821 } 00822 } 00823 BLI_bpathIterator_step(bpi); 00824 tot++; 00825 } 00826 BLI_bpathIterator_free(bpi); 00827 00828 if(reports) 00829 BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); 00830 } 00831 00832 00833 /* find this file recursively, use the biggest file so thumbnails dont get used by mistake 00834 - dir: subdir to search 00835 - filename: set this filename 00836 - filesize: filesize for the file 00837 */ 00838 #define MAX_RECUR 16 00839 static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth) 00840 { 00841 /* file searching stuff */ 00842 DIR *dir; 00843 struct dirent *de; 00844 struct stat status; 00845 char path[FILE_MAX]; 00846 int size; 00847 00848 dir= opendir(dirname); 00849 00850 if (dir==NULL) 00851 return 0; 00852 00853 if (*filesize == -1) 00854 *filesize= 0; /* dir opened fine */ 00855 00856 while ((de= readdir(dir)) != NULL) { 00857 00858 if (strcmp(".", de->d_name)==0 || strcmp("..", de->d_name)==0) 00859 continue; 00860 00861 BLI_join_dirfile(path, sizeof(path), dirname, de->d_name); 00862 00863 if (stat(path, &status) != 0) 00864 continue; /* cant stat, dont bother with this file, could print debug info here */ 00865 00866 if (S_ISREG(status.st_mode)) { /* is file */ 00867 if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */ 00868 /* open the file to read its size */ 00869 size= status.st_size; 00870 if ((size > 0) && (size > *filesize)) { /* find the biggest file */ 00871 *filesize= size; 00872 BLI_strncpy(filename_new, path, FILE_MAX); 00873 } 00874 } 00875 } 00876 else if (S_ISDIR(status.st_mode)) { /* is subdir */ 00877 if (*recur_depth <= MAX_RECUR) { 00878 (*recur_depth)++; 00879 findFileRecursive(filename_new, path, filename, filesize, recur_depth); 00880 (*recur_depth)--; 00881 } 00882 } 00883 } 00884 closedir(dir); 00885 return 1; 00886 } 00887 00888 /* high level function - call from fileselector */ 00889 void findMissingFiles(Main *bmain, const char *str) { 00890 struct BPathIterator *bpi; 00891 00892 /* be sure there is low chance of the path being too short */ 00893 char filepath_expanded[FILE_MAXDIR*2]; 00894 char filepath[FILE_MAX]; 00895 const char *libpath; 00896 int filesize, recur_depth; 00897 00898 char dirname[FILE_MAX], filename_new[FILE_MAX]; 00899 00900 //XXX waitcursor( 1 ); 00901 00902 BLI_split_dirfile(str, dirname, NULL); 00903 00904 BLI_bpathIterator_init(&bpi, bmain, bmain->name, 0); 00905 00906 while (!BLI_bpathIterator_isDone(bpi)) { 00907 BLI_bpathIterator_getPath(bpi, filepath); 00908 libpath= BLI_bpathIterator_getLib(bpi); 00909 00910 /* Check if esc was pressed because searching files can be slow */ 00911 /*XXX if (blender_test_break()) { 00912 break; 00913 }*/ 00914 00915 if (libpath==NULL) { 00916 00917 BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded); 00918 00919 if (!BLI_exists(filepath_expanded)) { 00920 /* can the dir be opened? */ 00921 filesize= -1; 00922 recur_depth= 0; 00923 00924 findFileRecursive(filename_new, dirname, BLI_path_basename(filepath), &filesize, &recur_depth); 00925 if (filesize == -1) { /* could not open dir */ 00926 printf("Could not open dir \"%s\"\n", dirname); 00927 return; 00928 } 00929 00930 if (filesize > 0) { 00931 00932 if (BLI_bpathIterator_getPathMaxLen(bpi) < strlen(filename_new)) { 00933 printf("cannot set path \"%s\" too long!", filename_new); 00934 } 00935 else { 00936 /* copy the found path into the old one */ 00937 if (G.relbase_valid) 00938 BLI_path_rel(filename_new, bpi->base_path); 00939 00940 BLI_bpathIterator_setPath(bpi, filename_new); 00941 } 00942 } 00943 } 00944 } 00945 BLI_bpathIterator_step(bpi); 00946 } 00947 BLI_bpathIterator_free(bpi); 00948 00949 //XXX waitcursor( 0 ); 00950 }