diff options
Diffstat (limited to 'source/blender/editors/space_file/filelist.c')
-rw-r--r-- | source/blender/editors/space_file/filelist.c | 194 |
1 files changed, 151 insertions, 43 deletions
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 66acd7d05e3..ee42e14c86c 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -35,6 +35,7 @@ #include <stdlib.h> #include <math.h> #include <string.h> +#include <ctype.h> #ifndef WIN32 # include <unistd.h> @@ -49,6 +50,7 @@ #include "BLI_fnmatch.h" #include "BLI_linklist.h" #include "BLI_utildefines.h" +#include "BLI_ghash.h" #ifdef WIN32 # include "BLI_winstuff.h" @@ -208,9 +210,11 @@ typedef struct FileImage { typedef struct FileListFilter { bool hide_dot; bool hide_parent; + bool collapse_ima_seq; unsigned int filter; char filter_glob[64]; - char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */ + char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */ + GHash *unique_image_list; /* hash that stores unique filename */ } FileListFilter; typedef struct FileList { @@ -464,6 +468,55 @@ static bool is_filtered_file(struct direntry *file, const char *UNUSED(root), Fi } } + if (is_filtered && !(file->type & S_IFDIR) && filter->collapse_ima_seq) { + if (file->relname) { + struct direntry *ofile; + int frame, numdigits; + + if (BLI_path_frame_get(file->relname, &frame, &numdigits)) { + char filename[PATH_MAX]; + + BLI_strncpy(filename, file->relname, sizeof(filename)); + BLI_path_frame_strip(filename, false, NULL); + + if ((ofile = BLI_ghash_lookup(filter->unique_image_list, filename)) && + numdigits == ofile->collapsed_info.numdigits) + { + CollapsedEntry *collapsed = &ofile->collapsed_info; + is_filtered = false; + ofile->selflag |= FILE_SEL_COLLAPSED; + file->selflag |= FILE_SEL_COLLAPSED; + file->frame = frame; + BLI_addhead(&collapsed->list, BLI_genericNodeN(file)); + collapsed->totalsize += file->realsize; + collapsed->maxframe = MAX2(frame, collapsed->maxframe); + collapsed->minframe = MIN2(frame, collapsed->minframe); + collapsed->totfiles++; + } + else { + if (file->collapsed_info.darray) { + MEM_freeN(file->collapsed_info.darray); + file->collapsed_info.darray = NULL; + } + BLI_ghash_insert(filter->unique_image_list, BLI_strdup(filename), file); + file->frame = frame; + file->collapsed_info.totalsize = file->realsize; + file->collapsed_info.maxframe = file->collapsed_info.minframe = frame; + file->collapsed_info.numdigits = numdigits; + file->collapsed_info.totfiles = 1; + } + } + } + } + else { + if (file->collapsed_info.darray) { + MEM_freeN(file->collapsed_info.darray); + file->collapsed_info.darray = NULL; + } + /* may have been set in a previous filtering iteration, so always clear */ + file->selflag &= ~FILE_SEL_COLLAPSED; + } + return is_filtered; } @@ -500,6 +553,17 @@ static void filelist_filter_clear(FileList *filelist) filelist->numfiltered = 0; } +static int compareFrame(const void *pa, const void *pb) +{ + struct direntry *a = *((struct direntry **)pa); + struct direntry *b = *((struct direntry **)pb); + if (a->frame < b->frame) + return -1; + if (a->frame > b->frame) + return 1; + return 0; +} + void filelist_filter(FileList *filelist) { int num_filtered = 0; @@ -517,6 +581,11 @@ void filelist_filter(FileList *filelist) fidx_tmp = MEM_mallocN(sizeof(*fidx_tmp) * (size_t)filelist->numfiles, __func__); + /* */ + if (filelist->filter_data.collapse_ima_seq) { + filelist->filter_data.unique_image_list = BLI_ghash_str_new("image_seq_hash"); + } + /* Filter remap & count how many files are left after filter in a single loop. */ for (i = 0; i < filelist->numfiles; ++i) { struct direntry *file = &filelist->filelist[i]; @@ -526,6 +595,33 @@ void filelist_filter(FileList *filelist) } } + if (filelist->filter_data.unique_image_list) { + BLI_ghash_free(filelist->filter_data.unique_image_list, MEM_freeN, NULL); + filelist->filter_data.unique_image_list = NULL; + } + + /* extra step, need to sort the file list according to frame */ + if (filelist->filter_data.collapse_ima_seq) { + for (i = 0; i < num_filtered; i++) { + struct direntry *file = &filelist->filelist[fidx_tmp[i]]; + if (file->selflag & FILE_SEL_COLLAPSED) { + LinkData *fdata = file->collapsed_info.list.first; + int j = 1; + file->collapsed_info.darray = + MEM_mallocN(sizeof(struct direntry *) * file->collapsed_info.totfiles, "collapsed files"); + file->collapsed_info.darray[0] = file; + + for (; fdata; fdata = fdata->next, j++) { + file->collapsed_info.darray[j] = fdata->data; + } + qsort(file->collapsed_info.darray, file->collapsed_info.totfiles, sizeof(struct direntry *), compareFrame); + if (file->collapsed_info.list.first) { + BLI_freelistN(&file->collapsed_info.list); + } + } + } + } + /* Note: maybe we could even accept filelist->fidx to be filelist->numfiles -len allocated? */ filelist->fidx = MEM_mallocN(sizeof(*filelist->fidx) * (size_t)num_filtered, __func__); memcpy(filelist->fidx, fidx_tmp, sizeof(*filelist->fidx) * (size_t)num_filtered); @@ -535,17 +631,20 @@ void filelist_filter(FileList *filelist) } void filelist_setfilter_options(FileList *filelist, const bool hide_dot, const bool hide_parent, + const bool collapse_ima_seq, const unsigned int filter, const char *filter_glob, const char *filter_search) { if ((filelist->filter_data.hide_dot != hide_dot) || (filelist->filter_data.hide_parent != hide_parent) || + (filelist->filter_data.collapse_ima_seq != collapse_ima_seq) || (filelist->filter_data.filter != filter) || !STREQ(filelist->filter_data.filter_glob, filter_glob) || (BLI_strcmp_ignore_pad(filelist->filter_data.filter_search, filter_search, '*') != 0)) { filelist->filter_data.hide_dot = hide_dot; filelist->filter_data.hide_parent = hide_parent; + filelist->filter_data.collapse_ima_seq = collapse_ima_seq; filelist->filter_data.filter = filter; BLI_strncpy(filelist->filter_data.filter_glob, filter_glob, sizeof(filelist->filter_data.filter_glob)); @@ -611,6 +710,7 @@ ImBuf *filelist_getimage(struct FileList *filelist, const int index) { ImBuf *ibuf = NULL; int fidx = 0; + struct direntry *file; BLI_assert(G.background == false); @@ -618,8 +718,15 @@ ImBuf *filelist_getimage(struct FileList *filelist, const int index) return NULL; } fidx = filelist->fidx[index]; - ibuf = filelist->filelist[fidx].image; + file = filelist->filelist + fidx; + if (file->selflag & FILE_SEL_COLLAPSED) { + int curfra = file->collapsed_info.curfra; + ibuf = file->collapsed_info.darray[curfra]->image; + } + else { + ibuf = filelist->filelist[fidx].image; + } return ibuf; } @@ -654,7 +761,7 @@ ImBuf *filelist_geticon(struct FileList *filelist, const int index) if (file->flags & FILE_TYPE_BLENDER) { ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE]; } - else if ((file->flags & FILE_TYPE_MOVIE) || (file->flags & FILE_TYPE_MOVIE_ICON)) { + else if (file->flags & FILE_TYPE_MOVIE) { ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE]; } else if (file->flags & FILE_TYPE_SOUND) { @@ -670,7 +777,10 @@ ImBuf *filelist_geticon(struct FileList *filelist, const int index) ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE]; } else if (file->flags & FILE_TYPE_IMAGE) { - ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING]; + if (file->selflag & FILE_SEL_COLLAPSED) + ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE]; + else + ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING]; } else if (file->flags & FILE_TYPE_BLENDER_BACKUP) { ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP]; @@ -900,7 +1010,6 @@ static void filelist_setfiletypes(struct FileList *filelist) file = filelist->filelist; for (num = 0; num < filelist->numfiles; num++, file++) { - file->type = file->s.st_mode; /* restore the mess below */ #ifndef __APPLE__ /* Don't check extensions for directories, allow in OSX cause bundles have extensions*/ if (file->type & S_IFDIR) { @@ -1190,29 +1299,30 @@ static void filelist_from_main(struct FileList *filelist) filelist->filelist[0].relname = BLI_strdup(FILENAME_PARENT); filelist->filelist[1].relname = BLI_strdup("Scene"); - filelist->filelist[2].relname = BLI_strdup("Object"); - filelist->filelist[3].relname = BLI_strdup("Mesh"); - filelist->filelist[4].relname = BLI_strdup("Curve"); - filelist->filelist[5].relname = BLI_strdup("Metaball"); - filelist->filelist[6].relname = BLI_strdup("Material"); - filelist->filelist[7].relname = BLI_strdup("Texture"); - filelist->filelist[8].relname = BLI_strdup("Image"); - filelist->filelist[9].relname = BLI_strdup("Ika"); - filelist->filelist[10].relname = BLI_strdup("Wave"); - filelist->filelist[11].relname = BLI_strdup("Lattice"); - filelist->filelist[12].relname = BLI_strdup("Lamp"); - filelist->filelist[13].relname = BLI_strdup("Camera"); - filelist->filelist[14].relname = BLI_strdup("Ipo"); - filelist->filelist[15].relname = BLI_strdup("World"); - filelist->filelist[16].relname = BLI_strdup("Screen"); - filelist->filelist[17].relname = BLI_strdup("VFont"); - filelist->filelist[18].relname = BLI_strdup("Text"); - filelist->filelist[19].relname = BLI_strdup("Armature"); - filelist->filelist[20].relname = BLI_strdup("Action"); - filelist->filelist[21].relname = BLI_strdup("NodeTree"); - filelist->filelist[22].relname = BLI_strdup("Speaker"); + filelist->filelist[2].relname = BLI_strdup("CacheLibrary"); + filelist->filelist[3].relname = BLI_strdup("Object"); + filelist->filelist[4].relname = BLI_strdup("Mesh"); + filelist->filelist[5].relname = BLI_strdup("Curve"); + filelist->filelist[6].relname = BLI_strdup("Metaball"); + filelist->filelist[7].relname = BLI_strdup("Material"); + filelist->filelist[8].relname = BLI_strdup("Texture"); + filelist->filelist[9].relname = BLI_strdup("Image"); + filelist->filelist[10].relname = BLI_strdup("Ika"); + filelist->filelist[11].relname = BLI_strdup("Wave"); + filelist->filelist[12].relname = BLI_strdup("Lattice"); + filelist->filelist[13].relname = BLI_strdup("Lamp"); + filelist->filelist[14].relname = BLI_strdup("Camera"); + filelist->filelist[15].relname = BLI_strdup("Ipo"); + filelist->filelist[16].relname = BLI_strdup("World"); + filelist->filelist[17].relname = BLI_strdup("Screen"); + filelist->filelist[18].relname = BLI_strdup("VFont"); + filelist->filelist[19].relname = BLI_strdup("Text"); + filelist->filelist[20].relname = BLI_strdup("Armature"); + filelist->filelist[21].relname = BLI_strdup("Action"); + filelist->filelist[22].relname = BLI_strdup("NodeTree"); + filelist->filelist[23].relname = BLI_strdup("Speaker"); #ifdef WITH_FREESTYLE - filelist->filelist[23].relname = BLI_strdup("FreestyleLineStyle"); + filelist->filelist[24].relname = BLI_strdup("FreestyleLineStyle"); #endif } else { @@ -1235,7 +1345,7 @@ static void filelist_from_main(struct FileList *filelist) files = filelist->filelist; - if (!filelist->filter_data.hide_parent) { + if (files && !filelist->filter_data.hide_parent) { memset(&(filelist->filelist[0]), 0, sizeof(struct direntry)); filelist->filelist[0].relname = BLI_strdup(FILENAME_PARENT); filelist->filelist[0].type |= S_IFDIR; @@ -1247,7 +1357,7 @@ static void filelist_from_main(struct FileList *filelist) for (id = lb->first; id; id = id->next) { ok = 1; if (ok) { - if (!filelist->filter_data.hide_dot || id->name[2] != '.') { + if (files && (!filelist->filter_data.hide_dot || id->name[2] != '.')) { memset(files, 0, sizeof(struct direntry)); if (id->lib == NULL) { files->relname = BLI_strdup(id->name + 2); @@ -1334,20 +1444,23 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float tj->do_update = do_update; while ((*stop == 0) && (limg)) { + ThumbSource source = 0; + + BLI_assert(limg->flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | + FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)); if (limg->flags & FILE_TYPE_IMAGE) { - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_IMAGE); + source = THB_SOURCE_IMAGE; } else if (limg->flags & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_BLEND); + source = THB_SOURCE_BLEND; } else if (limg->flags & FILE_TYPE_MOVIE) { - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_MOVIE); - if (!limg->img) { - /* remember that file can't be loaded via IMB_open_anim */ - limg->flags &= ~FILE_TYPE_MOVIE; - limg->flags |= FILE_TYPE_MOVIE_ICON; - } + source = THB_SOURCE_MOVIE; } + else if (limg->flags & FILE_TYPE_FTFONT) { + source = THB_SOURCE_FONT; + } + limg->img = IMB_thumb_manage(limg->path, THB_LARGE, source); *do_update = true; PIL_sleep_ms(10); limg = limg->next; @@ -1363,11 +1476,6 @@ static void thumbnails_update(void *tjv) while (limg) { if (!limg->done && limg->img) { tj->filelist->filelist[limg->index].image = IMB_dupImBuf(limg->img); - /* update flag for movie files where thumbnail can't be created */ - if (limg->flags & FILE_TYPE_MOVIE_ICON) { - tj->filelist->filelist[limg->index].flags &= ~FILE_TYPE_MOVIE; - tj->filelist->filelist[limg->index].flags |= FILE_TYPE_MOVIE_ICON; - } limg->done = true; IMB_freeImBuf(limg->img); limg->img = NULL; @@ -1408,7 +1516,7 @@ void thumbnails_start(FileList *filelist, const bContext *C) continue; } if (!filelist->filelist[idx].image) { - if (filelist->filelist[idx].flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | + if (filelist->filelist[idx].flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { FileImage *limg = MEM_callocN(sizeof(*limg), __func__); |