Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_file/filelist.c
| Show First 20 Lines • Show All 323 Lines • ▼ Show 20 Lines | |||||
| /* FileList.flags */ | /* FileList.flags */ | ||||
| enum { | enum { | ||||
| FL_FORCE_RESET = 1 << 0, | FL_FORCE_RESET = 1 << 0, | ||||
| FL_IS_READY = 1 << 1, | FL_IS_READY = 1 << 1, | ||||
| FL_IS_PENDING = 1 << 2, | FL_IS_PENDING = 1 << 2, | ||||
| FL_NEED_SORTING = 1 << 3, | FL_NEED_SORTING = 1 << 3, | ||||
| FL_NEED_FILTERING = 1 << 4, | FL_NEED_FILTERING = 1 << 4, | ||||
| FL_SORT_INVERT = 1 << 5, | |||||
| }; | }; | ||||
| #define SPECIAL_IMG_SIZE 48 | #define SPECIAL_IMG_SIZE 256 | ||||
| #define SPECIAL_IMG_ROWS 4 | #define SPECIAL_IMG_ROWS 1 | ||||
| #define SPECIAL_IMG_COLS 4 | #define SPECIAL_IMG_COLS 6 | ||||
| enum { | enum { | ||||
| SPECIAL_IMG_FOLDER = 0, | SPECIAL_IMG_DOCUMENT = 0, | ||||
| SPECIAL_IMG_PARENT = 1, | SPECIAL_IMG_FOLDER = 1, | ||||
| SPECIAL_IMG_REFRESH = 2, | SPECIAL_IMG_PARENT = 2, | ||||
| SPECIAL_IMG_BLENDFILE = 3, | SPECIAL_IMG_DRIVE_FIXED = 3, | ||||
| SPECIAL_IMG_SOUNDFILE = 4, | SPECIAL_IMG_DRIVE_ATTACHED = 4, | ||||
| SPECIAL_IMG_MOVIEFILE = 5, | SPECIAL_IMG_DRIVE_REMOTE = 5, | ||||
| SPECIAL_IMG_PYTHONFILE = 6, | |||||
| SPECIAL_IMG_TEXTFILE = 7, | |||||
| SPECIAL_IMG_FONTFILE = 8, | |||||
| SPECIAL_IMG_UNKNOWNFILE = 9, | |||||
| SPECIAL_IMG_LOADING = 10, | |||||
| SPECIAL_IMG_BACKUP = 11, | |||||
| SPECIAL_IMG_MAX, | SPECIAL_IMG_MAX, | ||||
| }; | }; | ||||
| static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX]; | static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX]; | ||||
| static void filelist_readjob_main( | static void filelist_readjob_main( | ||||
| struct FileList *, const char *, short *, short *, float *, ThreadMutex *); | struct FileList *, const char *, short *, short *, float *, ThreadMutex *); | ||||
| static void filelist_readjob_lib( | static void filelist_readjob_lib( | ||||
| struct FileList *, const char *, short *, short *, float *, ThreadMutex *); | struct FileList *, const char *, short *, short *, float *, ThreadMutex *); | ||||
| static void filelist_readjob_dir( | static void filelist_readjob_dir( | ||||
| struct FileList *, const char *, short *, short *, float *, ThreadMutex *); | struct FileList *, const char *, short *, short *, float *, ThreadMutex *); | ||||
| /* helper, could probably go in BKE actually? */ | /* helper, could probably go in BKE actually? */ | ||||
| static int groupname_to_code(const char *group); | static int groupname_to_code(const char *group); | ||||
| static unsigned int groupname_to_filter_id(const char *group); | static unsigned int groupname_to_filter_id(const char *group); | ||||
| static void filelist_filter_clear(FileList *filelist); | static void filelist_filter_clear(FileList *filelist); | ||||
| static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size); | static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size); | ||||
| /* ********** Sort helpers ********** */ | /* ********** Sort helpers ********** */ | ||||
| struct FileSortData { | |||||
| bool inverted; | |||||
| }; | |||||
| static int compare_apply_inverted(int val, const struct FileSortData *sort_data) | |||||
| { | |||||
| return sort_data->inverted ? -val : val; | |||||
| } | |||||
| /** | |||||
| * Handles inverted sorting itself (currently there's nothing to invert), so if this returns non-0, | |||||
| * it should be used as-is and not inverted. | |||||
| */ | |||||
| static int compare_direntry_generic(const FileListInternEntry *entry1, | static int compare_direntry_generic(const FileListInternEntry *entry1, | ||||
| const FileListInternEntry *entry2) | const FileListInternEntry *entry2) | ||||
| { | { | ||||
| /* type is equal to stat.st_mode */ | /* type is equal to stat.st_mode */ | ||||
| if (entry1->typeflag & FILE_TYPE_DIR) { | if (entry1->typeflag & FILE_TYPE_DIR) { | ||||
| if (entry2->typeflag & FILE_TYPE_DIR) { | if (entry2->typeflag & FILE_TYPE_DIR) { | ||||
| /* If both entries are tagged as dirs, we make a 'sub filter' that shows first the real dirs, | /* If both entries are tagged as dirs, we make a 'sub filter' that shows first the real dirs, | ||||
| Show All 35 Lines | static int compare_direntry_generic(const FileListInternEntry *entry1, | ||||
| } | } | ||||
| if (FILENAME_IS_PARENT(entry2->relpath)) { | if (FILENAME_IS_PARENT(entry2->relpath)) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2) | static int compare_name(void *user_data, const void *a1, const void *a2) | ||||
| { | { | ||||
| const FileListInternEntry *entry1 = a1; | const FileListInternEntry *entry1 = a1; | ||||
| const FileListInternEntry *entry2 = a2; | const FileListInternEntry *entry2 = a2; | ||||
| const struct FileSortData *sort_data = user_data; | |||||
| char *name1, *name2; | char *name1, *name2; | ||||
| int ret; | int ret; | ||||
| if ((ret = compare_direntry_generic(entry1, entry2))) { | if ((ret = compare_direntry_generic(entry1, entry2))) { | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| name1 = entry1->name; | name1 = entry1->name; | ||||
| name2 = entry2->name; | name2 = entry2->name; | ||||
| return BLI_strcasecmp_natural(name1, name2); | return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); | ||||
| } | } | ||||
| static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2) | static int compare_date(void *user_data, const void *a1, const void *a2) | ||||
| { | { | ||||
| const FileListInternEntry *entry1 = a1; | const FileListInternEntry *entry1 = a1; | ||||
| const FileListInternEntry *entry2 = a2; | const FileListInternEntry *entry2 = a2; | ||||
| const struct FileSortData *sort_data = user_data; | |||||
| char *name1, *name2; | char *name1, *name2; | ||||
| int64_t time1, time2; | int64_t time1, time2; | ||||
| int ret; | int ret; | ||||
| if ((ret = compare_direntry_generic(entry1, entry2))) { | if ((ret = compare_direntry_generic(entry1, entry2))) { | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| time1 = (int64_t)entry1->st.st_mtime; | time1 = (int64_t)entry1->st.st_mtime; | ||||
| time2 = (int64_t)entry2->st.st_mtime; | time2 = (int64_t)entry2->st.st_mtime; | ||||
| if (time1 < time2) { | if (time1 < time2) { | ||||
| return 1; | return compare_apply_inverted(1, sort_data); | ||||
| } | } | ||||
| if (time1 > time2) { | if (time1 > time2) { | ||||
| return -1; | return compare_apply_inverted(-1, sort_data); | ||||
| } | } | ||||
| name1 = entry1->name; | name1 = entry1->name; | ||||
| name2 = entry2->name; | name2 = entry2->name; | ||||
| return BLI_strcasecmp_natural(name1, name2); | return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); | ||||
| } | } | ||||
| static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2) | static int compare_size(void *user_data, const void *a1, const void *a2) | ||||
| { | { | ||||
| const FileListInternEntry *entry1 = a1; | const FileListInternEntry *entry1 = a1; | ||||
| const FileListInternEntry *entry2 = a2; | const FileListInternEntry *entry2 = a2; | ||||
| const struct FileSortData *sort_data = user_data; | |||||
| char *name1, *name2; | char *name1, *name2; | ||||
| uint64_t size1, size2; | uint64_t size1, size2; | ||||
| int ret; | int ret; | ||||
| if ((ret = compare_direntry_generic(entry1, entry2))) { | if ((ret = compare_direntry_generic(entry1, entry2))) { | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| size1 = entry1->st.st_size; | size1 = entry1->st.st_size; | ||||
| size2 = entry2->st.st_size; | size2 = entry2->st.st_size; | ||||
| if (size1 < size2) { | if (size1 < size2) { | ||||
| return 1; | return compare_apply_inverted(1, sort_data); | ||||
| } | } | ||||
| if (size1 > size2) { | if (size1 > size2) { | ||||
| return -1; | return compare_apply_inverted(-1, sort_data); | ||||
| } | } | ||||
| name1 = entry1->name; | name1 = entry1->name; | ||||
| name2 = entry2->name; | name2 = entry2->name; | ||||
| return BLI_strcasecmp_natural(name1, name2); | return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); | ||||
| } | } | ||||
| static int compare_extension(void *UNUSED(user_data), const void *a1, const void *a2) | static int compare_extension(void *user_data, const void *a1, const void *a2) | ||||
| { | { | ||||
| const FileListInternEntry *entry1 = a1; | const FileListInternEntry *entry1 = a1; | ||||
| const FileListInternEntry *entry2 = a2; | const FileListInternEntry *entry2 = a2; | ||||
| const struct FileSortData *sort_data = user_data; | |||||
| char *name1, *name2; | char *name1, *name2; | ||||
| int ret; | int ret; | ||||
| if ((ret = compare_direntry_generic(entry1, entry2))) { | if ((ret = compare_direntry_generic(entry1, entry2))) { | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && !(entry2->typeflag & FILE_TYPE_BLENDERLIB)) { | if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && !(entry2->typeflag & FILE_TYPE_BLENDERLIB)) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| if (!(entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) { | if (!(entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) { | if ((entry1->typeflag & FILE_TYPE_BLENDERLIB) && (entry2->typeflag & FILE_TYPE_BLENDERLIB)) { | ||||
| if ((entry1->typeflag & FILE_TYPE_DIR) && !(entry2->typeflag & FILE_TYPE_DIR)) { | if ((entry1->typeflag & FILE_TYPE_DIR) && !(entry2->typeflag & FILE_TYPE_DIR)) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| if (!(entry1->typeflag & FILE_TYPE_DIR) && (entry2->typeflag & FILE_TYPE_DIR)) { | if (!(entry1->typeflag & FILE_TYPE_DIR) && (entry2->typeflag & FILE_TYPE_DIR)) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| if (entry1->blentype < entry2->blentype) { | if (entry1->blentype < entry2->blentype) { | ||||
| return -1; | return compare_apply_inverted(-1, sort_data); | ||||
| } | } | ||||
| if (entry1->blentype > entry2->blentype) { | if (entry1->blentype > entry2->blentype) { | ||||
| return 1; | return compare_apply_inverted(1, sort_data); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| const char *sufix1, *sufix2; | const char *sufix1, *sufix2; | ||||
| if (!(sufix1 = strstr(entry1->relpath, ".blend.gz"))) { | if (!(sufix1 = strstr(entry1->relpath, ".blend.gz"))) { | ||||
| sufix1 = strrchr(entry1->relpath, '.'); | sufix1 = strrchr(entry1->relpath, '.'); | ||||
| } | } | ||||
| if (!(sufix2 = strstr(entry2->relpath, ".blend.gz"))) { | if (!(sufix2 = strstr(entry2->relpath, ".blend.gz"))) { | ||||
| sufix2 = strrchr(entry2->relpath, '.'); | sufix2 = strrchr(entry2->relpath, '.'); | ||||
| } | } | ||||
| if (!sufix1) { | if (!sufix1) { | ||||
| sufix1 = ""; | sufix1 = ""; | ||||
| } | } | ||||
| if (!sufix2) { | if (!sufix2) { | ||||
| sufix2 = ""; | sufix2 = ""; | ||||
| } | } | ||||
| if ((ret = BLI_strcasecmp(sufix1, sufix2))) { | if ((ret = BLI_strcasecmp(sufix1, sufix2))) { | ||||
| return ret; | return compare_apply_inverted(ret, sort_data); | ||||
| } | } | ||||
| } | } | ||||
| name1 = entry1->name; | name1 = entry1->name; | ||||
| name2 = entry2->name; | name2 = entry2->name; | ||||
| return BLI_strcasecmp_natural(name1, name2); | return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); | ||||
| } | } | ||||
| void filelist_sort(struct FileList *filelist) | void filelist_sort(struct FileList *filelist) | ||||
| { | { | ||||
| if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) { | if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) { | ||||
| void *sort_cb = NULL; | |||||
| switch (filelist->sort) { | switch (filelist->sort) { | ||||
| case FILE_SORT_ALPHA: | case FILE_SORT_ALPHA: | ||||
| BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_name, NULL); | sort_cb = compare_name; | ||||
| break; | break; | ||||
| case FILE_SORT_TIME: | case FILE_SORT_TIME: | ||||
| BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_date, NULL); | sort_cb = compare_date; | ||||
| break; | break; | ||||
| case FILE_SORT_SIZE: | case FILE_SORT_SIZE: | ||||
| BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_size, NULL); | sort_cb = compare_size; | ||||
| break; | break; | ||||
| case FILE_SORT_EXTENSION: | case FILE_SORT_EXTENSION: | ||||
| BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_extension, NULL); | sort_cb = compare_extension; | ||||
| break; | break; | ||||
| case FILE_SORT_NONE: /* Should never reach this point! */ | case FILE_SORT_NONE: /* Should never reach this point! */ | ||||
| default: | default: | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| break; | break; | ||||
| } | } | ||||
| BLI_listbase_sort_r( | |||||
| &filelist->filelist_intern.entries, | |||||
| sort_cb, | |||||
| &(struct FileSortData){.inverted = (filelist->flags & FL_SORT_INVERT) != 0}); | |||||
| filelist_filter_clear(filelist); | filelist_filter_clear(filelist); | ||||
| filelist->flags &= ~FL_NEED_SORTING; | filelist->flags &= ~FL_NEED_SORTING; | ||||
| } | } | ||||
| } | } | ||||
| void filelist_setsorting(struct FileList *filelist, const short sort) | void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort) | ||||
| { | { | ||||
| if (filelist->sort != sort) { | const bool was_invert_sort = filelist->flags & FL_SORT_INVERT; | ||||
| if ((filelist->sort != sort) || (was_invert_sort != invert_sort)) { | |||||
| filelist->sort = sort; | filelist->sort = sort; | ||||
| filelist->flags |= FL_NEED_SORTING; | filelist->flags |= FL_NEED_SORTING; | ||||
| filelist->flags = invert_sort ? (filelist->flags | FL_SORT_INVERT) : | |||||
| (filelist->flags & ~FL_SORT_INVERT); | |||||
mont29: I don't think this is going to work well with the asset engines. Sorting/filtering callback… | |||||
| } | } | ||||
| } | } | ||||
| /* ********** Filter helpers ********** */ | /* ********** Filter helpers ********** */ | ||||
| static bool is_hidden_file(const char *filename, FileListFilter *filter) | static bool is_hidden_file(const char *filename, FileListFilter *filter) | ||||
| { | { | ||||
| char *sep = (char *)BLI_last_slash(filename); | char *sep = (char *)BLI_last_slash(filename); | ||||
| Show All 38 Lines | |||||
| } | } | ||||
| static bool is_filtered_file(FileListInternEntry *file, | static bool is_filtered_file(FileListInternEntry *file, | ||||
| const char *UNUSED(root), | const char *UNUSED(root), | ||||
| FileListFilter *filter) | FileListFilter *filter) | ||||
| { | { | ||||
| bool is_filtered = !is_hidden_file(file->relpath, filter); | bool is_filtered = !is_hidden_file(file->relpath, filter); | ||||
| if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) { | if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { | ||||
| /* We only check for types if some type are enabled in filtering. */ | /* We only check for types if some type are enabled in filtering. */ | ||||
| if (filter->filter) { | if (filter->filter && (filter->flags & FLF_DO_FILTER)) { | ||||
| if (file->typeflag & FILE_TYPE_DIR) { | if (file->typeflag & FILE_TYPE_DIR) { | ||||
| if (file->typeflag & | if (file->typeflag & | ||||
| (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | ||||
| if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (!(filter->filter & FILE_TYPE_FOLDER)) { | if (!(filter->filter & FILE_TYPE_FOLDER)) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (!(file->typeflag & filter->filter)) { | if (!(file->typeflag & filter->filter)) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */ | |||||
| if (is_filtered && (filter->filter_search[0] != '\0')) { | if (is_filtered && (filter->filter_search[0] != '\0')) { | ||||
| if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { | if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return is_filtered; | return is_filtered; | ||||
| } | } | ||||
| static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter) | static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter) | ||||
| { | { | ||||
| bool is_filtered; | bool is_filtered; | ||||
| char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name; | char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name; | ||||
| BLI_join_dirfile(path, sizeof(path), root, file->relpath); | BLI_join_dirfile(path, sizeof(path), root, file->relpath); | ||||
| if (BLO_library_path_explode(path, dir, &group, &name)) { | if (BLO_library_path_explode(path, dir, &group, &name)) { | ||||
| is_filtered = !is_hidden_file(file->relpath, filter); | is_filtered = !is_hidden_file(file->relpath, filter); | ||||
| if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) { | if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { | ||||
| /* We only check for types if some type are enabled in filtering. */ | /* We only check for types if some type are enabled in filtering. */ | ||||
| if (filter->filter || filter->filter_id) { | if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) { | ||||
| if (file->typeflag & FILE_TYPE_DIR) { | if (file->typeflag & FILE_TYPE_DIR) { | ||||
| if (file->typeflag & | if (file->typeflag & | ||||
| (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | ||||
| if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 9 Lines | if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { | ||||
| else { | else { | ||||
| unsigned int filter_id = groupname_to_filter_id(group); | unsigned int filter_id = groupname_to_filter_id(group); | ||||
| if (!(filter_id & filter->filter_id)) { | if (!(filter_id & filter->filter_id)) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */ | |||||
| if (is_filtered && (filter->filter_search[0] != '\0')) { | if (is_filtered && (filter->filter_search[0] != '\0')) { | ||||
| if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { | if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char *relpath) | static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char *relpath) | ||||
| { | { | ||||
| ImBuf *ibuf = NULL; | ImBuf *ibuf = NULL; | ||||
| if (typeflag & FILE_TYPE_DIR) { | if (typeflag & FILE_TYPE_DIR) { | ||||
| if (FILENAME_IS_PARENT(relpath)) { | if (FILENAME_IS_PARENT(relpath)) { | ||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT]; | ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT]; | ||||
| } | } | ||||
| else if (FILENAME_IS_CURRENT(relpath)) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH]; | |||||
| } | |||||
| else { | else { | ||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER]; | ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER]; | ||||
| } | } | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_BLENDER) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE]; | |||||
| } | |||||
| else if (typeflag & FILE_TYPE_BLENDERLIB) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE]; | |||||
| } | |||||
| else if (typeflag & (FILE_TYPE_MOVIE)) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE]; | |||||
| } | |||||
| else if (typeflag & FILE_TYPE_SOUND) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE]; | |||||
| } | |||||
| else if (typeflag & FILE_TYPE_PYSCRIPT) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE]; | |||||
| } | |||||
| else if (typeflag & FILE_TYPE_FTFONT) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE]; | |||||
| } | |||||
| else if (typeflag & FILE_TYPE_TEXT) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE]; | |||||
| } | |||||
| else if (typeflag & FILE_TYPE_IMAGE) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING]; | |||||
| } | |||||
| else if (typeflag & FILE_TYPE_BLENDER_BACKUP) { | |||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP]; | |||||
| } | |||||
| else { | else { | ||||
| ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE]; | ibuf = gSpecialFileImages[SPECIAL_IMG_DOCUMENT]; | ||||
| } | } | ||||
| return ibuf; | return ibuf; | ||||
| } | } | ||||
| ImBuf *filelist_geticon_image(struct FileList *filelist, const int index) | ImBuf *filelist_geticon_image(struct FileList *filelist, const int index) | ||||
| { | { | ||||
| FileDirEntry *file = filelist_geticon_get_file(filelist, index); | FileDirEntry *file = filelist_geticon_get_file(filelist, index); | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | static int filelist_geticon_ex(const int typeflag, | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_FTFONT) { | else if (typeflag & FILE_TYPE_FTFONT) { | ||||
| return ICON_FILE_FONT; | return ICON_FILE_FONT; | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_BTX) { | else if (typeflag & FILE_TYPE_BTX) { | ||||
| return ICON_FILE_BLANK; | return ICON_FILE_BLANK; | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_COLLADA) { | else if (typeflag & FILE_TYPE_COLLADA) { | ||||
| return ICON_FILE_BLANK; | return ICON_FILE_3D; | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_ALEMBIC) { | else if (typeflag & FILE_TYPE_ALEMBIC) { | ||||
| return ICON_FILE_BLANK; | return ICON_FILE_3D; | ||||
| } | |||||
| else if (typeflag & FILE_TYPE_OBJECT_IO) { | |||||
| return ICON_FILE_3D; | |||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_TEXT) { | else if (typeflag & FILE_TYPE_TEXT) { | ||||
| return ICON_FILE_TEXT; | return ICON_FILE_TEXT; | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_BLENDERLIB) { | else if (typeflag & FILE_TYPE_BLENDERLIB) { | ||||
| const int ret = UI_idcode_icon_get(blentype); | const int ret = UI_idcode_icon_get(blentype); | ||||
| if (ret != ICON_NONE) { | if (ret != ICON_NONE) { | ||||
| return ret; | return ret; | ||||
| ▲ Show 20 Lines • Show All 222 Lines • ▼ Show 20 Lines | |||||
| static void filelist_cache_previews_clear(FileListEntryCache *cache) | static void filelist_cache_previews_clear(FileListEntryCache *cache) | ||||
| { | { | ||||
| FileListEntryPreview *preview; | FileListEntryPreview *preview; | ||||
| if (cache->previews_pool) { | if (cache->previews_pool) { | ||||
| BLI_task_pool_cancel(cache->previews_pool); | BLI_task_pool_cancel(cache->previews_pool); | ||||
| while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) { | while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) { | ||||
| // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, preview->img); | // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, | ||||
| // preview->img); | |||||
| if (preview->img) { | if (preview->img) { | ||||
| IMB_freeImBuf(preview->img); | IMB_freeImBuf(preview->img); | ||||
| } | } | ||||
| MEM_freeN(preview); | MEM_freeN(preview); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 868 Lines • ▼ Show 20 Lines | else if (BLI_path_extension_check(path, ".btx")) { | ||||
| return FILE_TYPE_BTX; | return FILE_TYPE_BTX; | ||||
| } | } | ||||
| else if (BLI_path_extension_check(path, ".dae")) { | else if (BLI_path_extension_check(path, ".dae")) { | ||||
| return FILE_TYPE_COLLADA; | return FILE_TYPE_COLLADA; | ||||
| } | } | ||||
| else if (BLI_path_extension_check(path, ".abc")) { | else if (BLI_path_extension_check(path, ".abc")) { | ||||
| return FILE_TYPE_ALEMBIC; | return FILE_TYPE_ALEMBIC; | ||||
| } | } | ||||
| else if (BLI_path_extension_check_n(path, ".obj", ".3ds", ".fbx", ".glb", ".gltf", NULL)) { | |||||
Done Inline Actionsisn't gltf missing a dot here? mont29: isn't `gltf` missing a dot here? | |||||
| return FILE_TYPE_OBJECT_IO; | |||||
| } | |||||
| else if (BLI_path_extension_check_array(path, imb_ext_image)) { | else if (BLI_path_extension_check_array(path, imb_ext_image)) { | ||||
| return FILE_TYPE_IMAGE; | return FILE_TYPE_IMAGE; | ||||
| } | } | ||||
| else if (BLI_path_extension_check(path, ".ogg")) { | else if (BLI_path_extension_check(path, ".ogg")) { | ||||
| if (IMB_isanim(path)) { | if (IMB_isanim(path)) { | ||||
| return FILE_TYPE_MOVIE; | return FILE_TYPE_MOVIE; | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 33 Lines | case FILE_TYPE_PYSCRIPT: | ||||
| return ICON_FILE_SCRIPT; | return ICON_FILE_SCRIPT; | ||||
| case FILE_TYPE_SOUND: | case FILE_TYPE_SOUND: | ||||
| return ICON_FILE_SOUND; | return ICON_FILE_SOUND; | ||||
| case FILE_TYPE_FTFONT: | case FILE_TYPE_FTFONT: | ||||
| return ICON_FILE_FONT; | return ICON_FILE_FONT; | ||||
| case FILE_TYPE_BTX: | case FILE_TYPE_BTX: | ||||
| return ICON_FILE_BLANK; | return ICON_FILE_BLANK; | ||||
| case FILE_TYPE_COLLADA: | case FILE_TYPE_COLLADA: | ||||
| return ICON_FILE_BLANK; | |||||
| case FILE_TYPE_ALEMBIC: | case FILE_TYPE_ALEMBIC: | ||||
| return ICON_FILE_BLANK; | case FILE_TYPE_OBJECT_IO: | ||||
| return ICON_FILE_3D; | |||||
| case FILE_TYPE_TEXT: | case FILE_TYPE_TEXT: | ||||
| return ICON_FILE_TEXT; | return ICON_FILE_TEXT; | ||||
| default: | default: | ||||
| return ICON_FILE_BLANK; | return ICON_FILE_BLANK; | ||||
| } | } | ||||
| } | } | ||||
| int filelist_empty(struct FileList *filelist) | int filelist_empty(struct FileList *filelist) | ||||
| ▲ Show 20 Lines • Show All 751 Lines • Show Last 20 Lines | |||||
I don't think this is going to work well with the asset engines. Sorting/filtering callback should handle 100% of the work imho, otherwise you may get some rather weird effects.
As a remainder, asset engine and changes it involved in filebrowser code are designed to only generate a small portion of the full listing, since some asset repos might potentially have thousands of items to list. In that case, that this simple approach will fail completely (as it would just reverse the order of the ten first items e.g., instead of showing the ten last...).
So please let the callbacks do their job. :)