diff options
author | Andrea Weikert <elubie@gmx.net> | 2007-09-02 21:25:03 +0400 |
---|---|---|
committer | Andrea Weikert <elubie@gmx.net> | 2007-09-02 21:25:03 +0400 |
commit | 356ab943736e8a2434a8ff5845873482597ba5e2 (patch) | |
tree | 910356ace904dc4f11f1daf15330bb0827934f5b /source/blender/src/filelist.c | |
parent | 22c23fb04f7f1297b971f03d69b8b04b7dd9caa4 (diff) |
== imagebrowser ==
Initial commit of imagebrowser in trunk.
BIG COMMIT!
Main changes:
* completely reworked imasel space
* creation and storage of the preview images for materials, textures, world and lamp
* thumbnails of images and movie files when browsing in the file system
* loading previews from external .blend when linking or appending
* thumbnail caching according to the Thumbnail Managing Standard: http://jens.triq.net/thumbnail-spec/
* for now just kept imasel access mostly as old imgbrowser (CTRL+F4, CTRL+F1) a bit hidden still.
* filtering of file types (images, movies, .blend, py,...)
* preliminary managing of bookmarks ('B' button to add, XKEY while bookmark active to delete)
More detailed info which will be updated here: http://wiki.blender.org/index.php/User:Elubie/PreviewImageBrowser
Places that need special review (and probably fixes):
* BLO_blendhandle_get_previews in readblenentry
* readfile.c: do_version and refactorings of do_library_append
* UI integration
TODO and known issues still:
* Accented characters do not display correctly with international fonts
* Crash was reported when browsing in directory with movie files
* Bookmark management still needs some UI work (second scrollbar?), feedback here is welcome!
Credits:
Samir Bharadwaj (samirbharadwaj@yahoo.com) for the icon images.
Many thanks to everyone who gave feedback and helped so far!
Diffstat (limited to 'source/blender/src/filelist.c')
-rw-r--r-- | source/blender/src/filelist.c | 1093 |
1 files changed, 1093 insertions, 0 deletions
diff --git a/source/blender/src/filelist.c b/source/blender/src/filelist.c new file mode 100644 index 00000000000..6dc97faca4e --- /dev/null +++ b/source/blender/src/filelist.c @@ -0,0 +1,1093 @@ +/** + * $Id: $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2007 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + + +/* global includes */ + +#include <stdlib.h> +#include <math.h> +#include <string.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef WIN32 +#include <unistd.h> +#else +#include <io.h> +#include <direct.h> +#endif +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_linklist.h" +#include "BLI_storage_types.h" + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BIF_filelist.h" +#include "BKE_library.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BLO_readfile.h" + +#include "DNA_space_types.h" +#include "DNA_ipo_types.h" +#include "DNA_ID.h" +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" +#include "DNA_scene_types.h" +#include "DNA_userdef_types.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_thumbs.h" + +#include "PIL_time.h" + +#include "datatoc.h" + +/* Elubie: VERY, really very ugly and evil! Remove asap!!! */ +/* for state of file */ +#define ACTIVE 2 + +/* max length of library group name within filesel */ +#define GROUP_MAX 32 + +typedef struct FileList +{ + struct direntry *filelist; + struct direntry *unfiltered; + + int numfiles; + int numunfiltered; + char dir[FILE_MAXDIR]; + short type; + short ipotype; + struct BlendHandle *libfiledata; + int has_func; + short prv_w; + short prv_h; + short hide_dot; + unsigned int filter; +} FileList; + +int BIF_groupname_to_code(char *group) +{ + char buf[32]; + char *lslash; + + BLI_strncpy(buf, group, 31); + lslash= BLI_last_slash(buf); + if (lslash) + lslash[0]= '\0'; + + return BLO_idcode_from_name(buf); +} + + +#define SPECIAL_IMG_SIZE 48 +#define SPECIAL_IMG_ROWS 4 +#define SPECIAL_IMG_COLS 4 + +#define SPECIAL_IMG_FOLDER 0 +#define SPECIAL_IMG_PARENT 1 +#define SPECIAL_IMG_REFRESH 2 +#define SPECIAL_IMG_BLENDFILE 3 +#define SPECIAL_IMG_SOUNDFILE 4 +#define SPECIAL_IMG_MOVIEFILE 5 +#define SPECIAL_IMG_PYTHONFILE 6 +#define SPECIAL_IMG_TEXTFILE 7 +#define SPECIAL_IMG_FONTFILE 8 +#define SPECIAL_IMG_UNKNOWNFILE 9 +#define SPECIAL_IMG_MAX SPECIAL_IMG_UNKNOWNFILE + 1 + +static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX]; + + +/* ******************* SORT ******************* */ + +static int compare_name(const void *a1, const void *a2) +{ + const struct direntry *entry1=a1, *entry2=a2; + + /* type is is equal to stat.st_mode */ + + if (S_ISDIR(entry1->type)){ + if (S_ISDIR(entry2->type)==0) return (-1); + } else{ + if (S_ISDIR(entry2->type)) return (1); + } + if (S_ISREG(entry1->type)){ + if (S_ISREG(entry2->type)==0) return (-1); + } else{ + if (S_ISREG(entry2->type)) return (1); + } + if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); + if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); + + /* make sure "." and ".." are always first */ + if( strcmp(entry1->relname, ".")==0 ) return (-1); + if( strcmp(entry2->relname, ".")==0 ) return (1); + if( strcmp(entry1->relname, "..")==0 ) return (-1); + + return (BLI_strcasecmp(entry1->relname,entry2->relname)); +} + +static int compare_date(const void *a1, const void *a2) +{ + const struct direntry *entry1=a1, *entry2=a2; + + /* type is equal to stat.st_mode */ + + if (S_ISDIR(entry1->type)){ + if (S_ISDIR(entry2->type)==0) return (-1); + } else{ + if (S_ISDIR(entry2->type)) return (1); + } + if (S_ISREG(entry1->type)){ + if (S_ISREG(entry2->type)==0) return (-1); + } else{ + if (S_ISREG(entry2->type)) return (1); + } + if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); + if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); + + /* make sure "." and ".." are always first */ + if( strcmp(entry1->relname, ".")==0 ) return (-1); + if( strcmp(entry2->relname, ".")==0 ) return (1); + if( strcmp(entry1->relname, "..")==0 ) return (-1); + + if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1; + if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1; + + else return BLI_strcasecmp(entry1->relname,entry2->relname); +} + +static int compare_size(const void *a1, const void *a2) +{ + const struct direntry *entry1=a1, *entry2=a2; + + /* type is equal to stat.st_mode */ + + if (S_ISDIR(entry1->type)){ + if (S_ISDIR(entry2->type)==0) return (-1); + } else{ + if (S_ISDIR(entry2->type)) return (1); + } + if (S_ISREG(entry1->type)){ + if (S_ISREG(entry2->type)==0) return (-1); + } else{ + if (S_ISREG(entry2->type)) return (1); + } + if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); + if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); + + /* make sure "." and ".." are always first */ + if( strcmp(entry1->relname, ".")==0 ) return (-1); + if( strcmp(entry2->relname, ".")==0 ) return (1); + if( strcmp(entry1->relname, "..")==0 ) return (-1); + + if ( entry1->s.st_size < entry2->s.st_size) return 1; + if ( entry1->s.st_size > entry2->s.st_size) return -1; + else return BLI_strcasecmp(entry1->relname,entry2->relname); +} + +static int compare_extension(const void *a1, const void *a2) { + const struct direntry *entry1=a1, *entry2=a2; + char *sufix1, *sufix2; + char *nil=""; + + if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) + sufix1= strrchr (entry1->relname, '.'); + if (!(sufix2= strstr (entry2->relname, ".blend.gz"))) + sufix2= strrchr (entry2->relname, '.'); + if (!sufix1) sufix1= nil; + if (!sufix2) sufix2= nil; + + /* type is is equal to stat.st_mode */ + + if (S_ISDIR(entry1->type)){ + if (S_ISDIR(entry2->type)==0) return (-1); + } else{ + if (S_ISDIR(entry2->type)) return (1); + } + if (S_ISREG(entry1->type)){ + if (S_ISREG(entry2->type)==0) return (-1); + } else{ + if (S_ISREG(entry2->type)) return (1); + } + if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); + if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); + + /* make sure "." and ".." are always first */ + if( strcmp(entry1->relname, ".")==0 ) return (-1); + if( strcmp(entry2->relname, ".")==0 ) return (1); + if( strcmp(entry1->relname, "..")==0 ) return (-1); + if( strcmp(entry2->relname, "..")==0 ) return (-1); + + return (BLI_strcasecmp(sufix1, sufix2)); +} + +void BIF_filelist_filter(FileList* filelist) +{ + int num_files = 0; + int num_filtered = 0; + struct direntry *old_filelist; + int i, j; + + if (!filelist->filelist) + return; + + if (!filelist->filter) { + if (filelist->unfiltered) { + old_filelist = filelist->filelist; + filelist->filelist = filelist->unfiltered; + filelist->numfiles = filelist->numunfiltered; + filelist->unfiltered = 0; + filelist->numunfiltered = 0; + free (old_filelist); + } + return; + } + + if (!filelist->unfiltered) { + filelist->unfiltered = filelist->filelist; + filelist->numunfiltered = filelist->numfiles; + } + + old_filelist = filelist->unfiltered; + num_files = filelist->numunfiltered; + + filelist->filelist = 0; + + // How many files are left after filter ? + for (i = 0; i < num_files; ++i) { + if (old_filelist[i].flags & filelist->filter) { + num_filtered++; + } + else if (old_filelist[i].type & S_IFDIR) { + if (filelist->filter & FOLDERFILE) { + num_filtered++; + } + } + } + + filelist->filelist = (struct direntry *)malloc(num_filtered * sizeof(struct direntry)); + filelist->numfiles = num_filtered; + + for (i = 0, j=0; i < num_files; ++i) { + if (old_filelist[i].flags & filelist->filter) { + filelist->filelist[j++] = old_filelist[i]; + } + else if (old_filelist[i].type & S_IFDIR) { + if (filelist->filter & FOLDERFILE) { + filelist->filelist[j++] = old_filelist[i]; + } + } + } +} + +void BIF_filelist_init_icons() +{ + short x, y, k; + ImBuf *bbuf; + ImBuf *ibuf; + bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect); + if (bbuf) { + for (y=0; y<SPECIAL_IMG_ROWS; y++) { + for (x=0; x<SPECIAL_IMG_COLS; x++) { + int tile = SPECIAL_IMG_COLS*y + x; + if (tile < SPECIAL_IMG_MAX) { + ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0); + for (k=0; k<SPECIAL_IMG_SIZE; k++) { + memcpy(&ibuf->rect[k*SPECIAL_IMG_SIZE], &bbuf->rect[(k+y*SPECIAL_IMG_SIZE)*SPECIAL_IMG_SIZE*SPECIAL_IMG_COLS+x*SPECIAL_IMG_SIZE], SPECIAL_IMG_SIZE*sizeof(int)); + } + gSpecialFileImages[tile] = ibuf; + } + } + } + IMB_freeImBuf(bbuf); + } + +} + +void BIF_filelist_free_icons() +{ + int i; + for (i=0; i < SPECIAL_IMG_MAX; ++i) { + IMB_freeImBuf(gSpecialFileImages[i]); + gSpecialFileImages[i] = NULL; + } +} + +struct FileList* BIF_filelist_new() +{ + FileList* p = MEM_callocN( sizeof(FileList), "filelist" ); + p->filelist = 0; + p->numfiles = 0; + p->dir[0] = '\0'; + p->libfiledata = 0; + p->type = 0; + p->has_func = 0; + p->filter = 0; + return p; +} + +struct FileList* BIF_filelist_copy(struct FileList* filelist) +{ + FileList* p = BIF_filelist_new(); + BLI_strncpy(p->dir, filelist->dir, FILE_MAXDIR); + p->filelist = NULL; + p->unfiltered = NULL; + p->type = filelist->type; + p->ipotype = filelist->ipotype; + p->has_func = filelist->has_func; + + return p; +} + +void BIF_filelist_free(struct FileList* filelist) +{ + int i; + + if (!filelist) { + printf("Attemtping to delete empty filelist.\n"); + return; + } + + if (filelist->unfiltered) { + struct direntry* filtered_files = filelist->filelist; + filelist->filelist = filelist->unfiltered; + filelist->numfiles = filelist->numunfiltered; + filelist->numunfiltered = 0; + free (filtered_files); + filelist->unfiltered = 0; + } + + for (i = 0; i < filelist->numfiles; ++i) { + if (filelist->filelist[i].image) + IMB_freeImBuf(filelist->filelist[i].image); + filelist->filelist[i].image = 0; + if (filelist->filelist[i].relname) + MEM_freeN(filelist->filelist[i].relname); + filelist->filelist[i].relname = 0; + if (filelist->filelist[i].string) + MEM_freeN(filelist->filelist[i].string); + filelist->filelist[i].string = 0; + } + + filelist->numfiles = 0; + free(filelist->filelist); + filelist->filelist = 0; +} + +void BIF_filelist_freelib(struct FileList* filelist) +{ + if(filelist->libfiledata) + BLO_blendhandle_close(filelist->libfiledata); + filelist->libfiledata= 0; +} + +struct BlendHandle *BIF_filelist_lib(struct FileList* filelist) +{ + return filelist->libfiledata; +} + +int BIF_filelist_numfiles(struct FileList* filelist) +{ + return filelist->numfiles; +} + +const char * BIF_filelist_dir(struct FileList* filelist) +{ + return filelist->dir; +} + +void BIF_filelist_setdir(struct FileList* filelist, const char *dir) +{ + BLI_strncpy(filelist->dir, dir, FILE_MAXDIR); +} + +void BIF_filelist_appenddir(struct FileList* filelist, const char *relname) +{ + strcat(filelist->dir, relname); + BLI_cleanup_dir(G.sce, filelist->dir); +} + +void BIF_filelist_imgsize(struct FileList* filelist, short w, short h) +{ + filelist->prv_w = w; + filelist->prv_h = h; +} + +void BIF_filelist_loadimage(struct FileList* filelist, int index) +{ + ImBuf *imb = NULL; + int imgwidth = filelist->prv_w; + int imgheight = filelist->prv_h; + short ex, ey, dx, dy; + float scaledx, scaledy; + + if (!filelist->filelist[index].image) + { + if (filelist->type != FILE_MAIN) + { + if ( filelist->filelist[index].flags & IMAGEFILE ) { + imb = IMB_thumb_manage(filelist->dir, filelist->filelist[index].relname, THB_NORMAL, THB_SOURCE_IMAGE); + } else if ( filelist->filelist[index].flags & MOVIEFILE ) { + imb = IMB_thumb_manage(filelist->dir, filelist->filelist[index].relname, THB_NORMAL, THB_SOURCE_MOVIE); + if (!imb) { + /* remember that file can't be loaded via IMB_open_anim */ + filelist->filelist[index].flags &= ~MOVIEFILE; + filelist->filelist[index].flags |= MOVIEFILE_ICON; + } + } + if (imb) { + if (imb->x > imb->y) { + scaledx = (float)imgwidth; + scaledy = ( (float)imb->y/(float)imb->x )*imgwidth; + } + else { + scaledy = imgheight; + scaledx = ( (float)imb->x/(float)imb->y )*imgheight; + } + ex = (short)scaledx; + ey = (short)scaledy; + + dx = imgwidth - ex; + dy = imgheight - ey; + + IMB_scaleImBuf(imb, ex, ey); + + } + filelist->filelist[index].image = imb; + + } + } +} + +struct ImBuf * BIF_filelist_getimage(struct FileList* filelist, int index) +{ + ImBuf* ibuf = filelist->filelist[index].image; + if (ibuf == NULL) { + struct direntry *file = &filelist->filelist[index]; + if (file->type & S_IFDIR) { + if ( strcmp(filelist->filelist[index].relname, "..") == 0) { + ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT]; + } else if ( strcmp(filelist->filelist[index].relname, ".") == 0) { + ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH]; + } else { + ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER]; + } + } else { + ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE]; + } + + if (file->flags & BLENDERFILE) { + ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE]; + } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) { + ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE]; + } else if (file->flags & SOUNDFILE) { + ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE]; + } else if (file->flags & PYSCRIPTFILE) { + ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE]; + } else if (file->flags & FTFONTFILE) { + ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE]; + } else if (file->flags & TEXTFILE) { + ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE]; + } + } + return ibuf; +} + +struct direntry * BIF_filelist_file(struct FileList* filelist, int index) +{ + return &filelist->filelist[index]; +} + +int BIF_filelist_find(struct FileList* filelist, char *file) +{ + int index = -1; + int i; + + for (i = 0; i < filelist->numfiles; ++i) { + if ( strcmp(filelist->filelist[i].relname, file) == 0) { + index = i; + break; + } + } + return index; +} + +void BIF_filelist_hidedot(struct FileList* filelist, short hide) +{ + filelist->hide_dot = hide; +} + +void BIF_filelist_setfilter(struct FileList* filelist, unsigned int filter) +{ + filelist->filter = filter; +} + +void BIF_filelist_readdir(struct FileList* filelist) +{ + char wdir[FILE_MAXDIR]; + int finished = 0; + + if (!filelist) return; + filelist->unfiltered = 0; + filelist->filelist = 0; + + if(filelist->type==FILE_MAIN) { + BIF_filelist_from_main(filelist); + finished = 1; + } else if(filelist->type==FILE_LOADLIB) { + BLI_cleanup_dir(G.sce, filelist->dir); + BIF_filelist_from_library(filelist); + if(filelist->libfiledata) { + finished = 1; + } + } + + if (!finished) { + BLI_getwdN(wdir); + + BLI_cleanup_dir(G.sce, filelist->dir); + BLI_hide_dot_files(filelist->hide_dot); + filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist)); + + chdir(wdir); + BIF_filelist_setfiletypes(filelist, G.have_quicktime); + BIF_filelist_filter(filelist); + + } +} + +int BIF_filelist_empty(struct FileList* filelist) +{ + return filelist->filelist == 0; +} + +void BIF_filelist_parent(struct FileList* filelist) +{ +#ifdef WIN32 + char c = '\\'; +#else + char c = '/'; +#endif + char *dir = filelist->dir; + size_t len = strlen(dir); + + while( (len > 0) && (dir[len-1] == c) ) + { + --len; + dir[len] = '\0'; + } + while ( (len > 0) && (dir[len-1] != c) ) + { + --len; + dir[len] = '\0'; + } + if (len == 0) + { + dir[0] = c; dir[1] = '\0'; + } +#ifdef WIN32 + strcat(filelist->dir, "\\"); +#else + strcat(filelist->dir, "/"); +#endif + + BLI_cleanup_dir(G.sce, filelist->dir); + BLI_make_exist(filelist->dir); + BIF_filelist_readdir(filelist); +} + +void BIF_filelist_setfiletypes(struct FileList* filelist, short has_quicktime) +{ + struct direntry *file; + int num; + + file= filelist->filelist; + + for(num=0; num<filelist->numfiles; num++, file++) { + file->flags= 0; + file->type= file->s.st_mode; /* restore the mess below */ + + /* Don't check extensions for directories */ + if (file->type & S_IFDIR) + continue; + + + + if(BLO_has_bfile_extension(file->relname)) { + file->flags |= BLENDERFILE; + if(filelist->type==FILE_LOADLIB) { + char name[FILE_MAXDIR+FILE_MAXFILE]; + BLI_strncpy(name, filelist->dir, sizeof(name)); + strcat(name, file->relname); + + /* prevent current file being used as acceptable dir */ + if (BLI_streq(G.main->name, name)==0) { + file->type &= ~S_IFMT; + file->type |= S_IFDIR; + } + } + } else if(BLI_testextensie(file->relname, ".py")) { + file->flags |= PYSCRIPTFILE; + } else if(BLI_testextensie(file->relname, ".txt")) { + file->flags |= TEXTFILE; + } else if( BLI_testextensie(file->relname, ".ttf") + || BLI_testextensie(file->relname, ".ttc") + || BLI_testextensie(file->relname, ".pfb") + || BLI_testextensie(file->relname, ".otf") + || BLI_testextensie(file->relname, ".otc")) { + file->flags |= FTFONTFILE; + } else if (has_quicktime){ + if( BLI_testextensie(file->relname, ".jpg") + || BLI_testextensie(file->relname, ".jpeg") + || BLI_testextensie(file->relname, ".tga") + || BLI_testextensie(file->relname, ".rgb") + || BLI_testextensie(file->relname, ".bmp") + || BLI_testextensie(file->relname, ".png") + || BLI_testextensie(file->relname, ".iff") + || BLI_testextensie(file->relname, ".lbm") + || BLI_testextensie(file->relname, ".gif") + || BLI_testextensie(file->relname, ".psd") + || BLI_testextensie(file->relname, ".tif") + || BLI_testextensie(file->relname, ".tiff") + || BLI_testextensie(file->relname, ".pct") + || BLI_testextensie(file->relname, ".pict") + || BLI_testextensie(file->relname, ".pntg") //macpaint + || BLI_testextensie(file->relname, ".qtif") + || BLI_testextensie(file->relname, ".sgi") +#ifdef WITH_OPENEXR + || BLI_testextensie(file->relname, ".exr") +#endif + ) { + file->flags |= IMAGEFILE; + } + else if(BLI_testextensie(file->relname, ".avi") + || BLI_testextensie(file->relname, ".flc") + || BLI_testextensie(file->relname, ".mov") + || BLI_testextensie(file->relname, ".movie") + || BLI_testextensie(file->relname, ".mp4") + || BLI_testextensie(file->relname, ".m4v") + || BLI_testextensie(file->relname, ".mv")) { + file->flags |= MOVIEFILE; + } + else if(BLI_testextensie(file->relname, ".wav")) { + file->flags |= SOUNDFILE; + } + } else { // no quicktime + if(BLI_testextensie(file->relname, ".jpg") + || BLI_testextensie(file->relname, ".tga") + || BLI_testextensie(file->relname, ".rgb") + || BLI_testextensie(file->relname, ".bmp") + || BLI_testextensie(file->relname, ".png") + || BLI_testextensie(file->relname, ".iff") + || BLI_testextensie(file->relname, ".tif") + || BLI_testextensie(file->relname, ".tiff") +#ifdef WITH_OPENEXR + || BLI_testextensie(file->relname, ".exr") +#endif + || BLI_testextensie(file->relname, ".lbm") + || BLI_testextensie(file->relname, ".sgi")) { + file->flags |= IMAGEFILE; + } + else if(BLI_testextensie(file->relname, ".avi") + || BLI_testextensie(file->relname, ".mp4") + || BLI_testextensie(file->relname, ".mv")) { + file->flags |= MOVIEFILE; + } + else if(BLI_testextensie(file->relname, ".wav")) { + file->flags |= SOUNDFILE; + } + } + } +} + +void BIF_filelist_swapselect(struct FileList* filelist) +{ + struct direntry *file; + int num, act= 0; + + file= filelist->filelist; + for(num=0; num<filelist->numfiles; num++, file++) { + if(file->flags & ACTIVE) { + act= 1; + break; + } + } + file= filelist->filelist+2; + for(num=2; num<filelist->numfiles; num++, file++) { + if(act) file->flags &= ~ACTIVE; + else file->flags |= ACTIVE; + } +} + +int BIF_filelist_islibrary(struct FileList* filelist, char* dir, char* group) +{ + /* return ok when a blenderfile, in dir is the filename, + * in group the type of libdata + */ + int len; + char *fd; + + strcpy(dir, filelist->dir); + len= strlen(dir); + if(len<7) return 0; + if( dir[len-1] != '/' && dir[len-1] != '\\') return 0; + + group[0]= 0; + dir[len-1]= 0; + + /* Find the last slash */ + fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\'); + + if(fd==0) return 0; + *fd= 0; + if(BLO_has_bfile_extension(fd+1)) { + *fd= '/'; + } + else { + char *gp = fd+1; // in case we have a .blend file, gp points to the group + + /* Find the last slash */ + fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\'); + if (!fd || !BLO_has_bfile_extension(fd+1)) return 0; + + /* now we know that we are in a blend file and it is safe to + assume that gp actually points to a group */ + BLI_strncpy(group, gp, GROUP_MAX); + } + return 1; +} + +void BIF_filelist_from_library(struct FileList* filelist) +{ + LinkNode *l, *names, *previews; + struct ImBuf* ima; + int ok, i, nnames, idcode; + char filename[FILE_MAXDIR+FILE_MAXFILE]; + char dir[FILE_MAXDIR], group[GROUP_MAX]; + + filelist->type = FILE_LOADLIB; + + /* name test */ + ok= BIF_filelist_islibrary(filelist, dir, group); + if (!ok) { + /* free */ + if(filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata); + filelist->libfiledata= 0; + return; + } + + BLI_strncpy(filename, G.sce, sizeof(filename)); // G.sce = last file loaded, for UI + + /* there we go */ + /* for the time being only read filedata when libfiledata==0 */ + if (filelist->libfiledata==0) { + filelist->libfiledata= BLO_blendhandle_from_file(dir); + if(filelist->libfiledata==0) return; + } + + idcode= BIF_groupname_to_code(group); + + // memory for strings is passed into filelist[i].relname + // and free'd in freefilelist + previews = NULL; + if (idcode) { + previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode); + names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode); + /* ugh, no rewind, need to reopen */ + BLO_blendhandle_close(filelist->libfiledata); + filelist->libfiledata= BLO_blendhandle_from_file(dir); + + } else { + names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata); + } + + nnames= BLI_linklist_length(names); + + filelist->numfiles= nnames + 2; + filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist)); + memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist)); + + filelist->filelist[0].relname= BLI_strdup("."); + filelist->filelist[0].type |= S_IFDIR; + filelist->filelist[1].relname= BLI_strdup(".."); + filelist->filelist[1].type |= S_IFDIR; + + for (i=0, l= names; i<nnames; i++, l= l->next) { + char *blockname= l->link; + + filelist->filelist[i + 2].relname= BLI_strdup(blockname); + if (!idcode) + filelist->filelist[i + 2].type |= S_IFDIR; + } + + if(previews) { + for (i=0, l= previews; i<nnames; i++, l= l->next) { + PreviewImage *img= l->link; + + if (img) { + unsigned int w = img->w[PREVIEW_MIPMAP_LARGE]; + unsigned int h = img->h[PREVIEW_MIPMAP_LARGE]; + unsigned int *rect = img->rect[PREVIEW_MIPMAP_LARGE]; + + /* first allocate imbuf for copying preview into it */ + if (w > 0 && h > 0 && rect) { + ima = IMB_allocImBuf(w, h, 32, IB_rect, 0); + memcpy(ima->rect, rect, w*h*sizeof(unsigned int)); + filelist->filelist[i + 2].image = ima; + filelist->filelist[i + 2].flags = IMAGEFILE; + } + } + } + } + + BLI_linklist_free(names, free); + if (previews) BLI_linklist_free(previews, MEM_freeN); + + BIF_filelist_sort(filelist, FILE_SORTALPHA); + + BLI_strncpy(G.sce, filename, sizeof(filename)); // prevent G.sce to change +} + +void BIF_filelist_append_library(struct FileList *filelist, char *dir, char *file, short flag, int idcode) +{ + BLO_library_append_(&filelist->libfiledata, filelist->filelist, filelist->numfiles, dir, file, flag, idcode); +} + +void BIF_filelist_from_main(struct FileList *filelist) +{ + ID *id; + struct direntry *files, *firstlib = NULL; + ListBase *lb; + int a, fake, idcode, ok, totlib, totbl; + + filelist->type = FILE_MAIN; + + if(filelist->dir[0]=='/') filelist->dir[0]= 0; + + if(filelist->dir[0]) { + idcode= BIF_groupname_to_code(filelist->dir); + if(idcode==0) filelist->dir[0]= 0; + } + + if( filelist->dir[0]==0) { + + /* make directories */ + filelist->numfiles= 23; + filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)); + + for(a=0; a<filelist->numfiles; a++) { + memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry)); + filelist->filelist[a].type |= S_IFDIR; + } + + filelist->filelist[0].relname= BLI_strdup(".."); + filelist->filelist[1].relname= BLI_strdup("."); + filelist->filelist[2].relname= BLI_strdup("Scene"); + 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"); + BIF_filelist_sort(filelist, FILE_SORTALPHA); + } + else { + + /* make files */ + idcode= BIF_groupname_to_code(filelist->dir); + + lb= wich_libbase(G.main, idcode ); + if(lb==0) return; + + id= lb->first; + filelist->numfiles= 0; + while(id) { + + if(filelist->has_func && idcode==ID_IP) { + if(filelist->ipotype== ((Ipo *)id)->blocktype) filelist->numfiles++; + } + else if (!filelist->hide_dot || id->name[2] != '.') { + filelist->numfiles++; + } + + id= id->next; + } + + if(!filelist->has_func) filelist->numfiles+= 2; + filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)); + + files = filelist->filelist; + + if(!filelist->has_func) { + memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry)); + filelist->filelist[0].relname= BLI_strdup("."); + filelist->filelist[0].type |= S_IFDIR; + memset( &(filelist->filelist[1]), 0 , sizeof(struct direntry)); + filelist->filelist[1].relname= BLI_strdup(".."); + filelist->filelist[1].type |= S_IFDIR; + + files+= 2; + } + + id= lb->first; + totlib= totbl= 0; + + while(id) { + + ok= 0; + if(filelist->has_func && idcode==ID_IP) { + if(filelist->ipotype== ((Ipo *)id)->blocktype) ok= 1; + } + else ok= 1; + + if(ok) { + /* TODO: hide dot files - elubie */ + memset( files, 0 , sizeof(struct direntry)); + if(id->lib==NULL) + files->relname= BLI_strdup(id->name+2); + else { + files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib"); + sprintf(files->relname, "%s | %s", id->lib->name, id->name+2); + } + /* files->type |= S_IFDIR; */ + if(!filelist->has_func) { /* F4 DATA BROWSE */ + if(idcode==ID_OB) { + if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE; + } + else if(idcode==ID_SCE) { + if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE; + } + } + files->nr= totbl+1; + files->poin= id; + fake= id->flag & LIB_FAKEUSER; + if(idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) { + files->flags |= IMAGEFILE; + } + if(id->lib && fake) sprintf(files->extra, "LF %d", id->us); + else if(id->lib) sprintf(files->extra, "L %d", id->us); + else if(fake) sprintf(files->extra, "F %d", id->us); + else sprintf(files->extra, " %d", id->us); + + if(id->lib) { + if(totlib==0) firstlib= files; + totlib++; + } + + files++; + totbl++; + } + + id= id->next; + } + + /* only qsort of library blocks */ + if(totlib>1) { + qsort(firstlib, totlib, sizeof(struct direntry), compare_name); + } + } +} + + +void BIF_filelist_settype(struct FileList* filelist, int type) +{ + filelist->type = type; +} + +short BIF_filelist_gettype(struct FileList* filelist) +{ + return filelist->type; +} + +void BIF_filelist_sort(struct FileList* filelist, short sort) +{ + struct direntry *file; + int num;/* , act= 0; */ + + switch(sort) { + case FILE_SORTALPHA: + qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name); + break; + case FILE_SORTDATE: + qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date); + break; + case FILE_SORTSIZE: + qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size); + break; + case FILE_SORTEXTENS: + qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension); + } + + file= filelist->filelist; + for(num=0; num<filelist->numfiles; num++, file++) { + file->flags &= ~HILITE; + } +} + + +void BIF_filelist_setipotype(struct FileList* filelist, short ipotype) +{ + filelist->ipotype = ipotype; +} + +void BIF_filelist_hasfunc(struct FileList* filelist, int has_func) +{ + filelist->has_func = has_func; +} + |