Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_file/filelist.c
| Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "UI_interface_icons.h" | #include "UI_interface_icons.h" | ||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| #include "atomic_ops.h" | #include "atomic_ops.h" | ||||
| #include "file_indexer.h" | |||||
| #include "file_intern.h" | #include "file_intern.h" | ||||
| #include "filelist.h" | #include "filelist.h" | ||||
| #define FILEDIR_NBR_ENTRIES_UNSET -1 | #define FILEDIR_NBR_ENTRIES_UNSET -1 | ||||
| /* ----------------- FOLDERLIST (previous/next) -------------- */ | /* ----------------- FOLDERLIST (previous/next) -------------- */ | ||||
| typedef struct FolderList { | typedef struct FolderList { | ||||
| ▲ Show 20 Lines • Show All 294 Lines • ▼ Show 20 Lines | typedef struct FileList { | ||||
| struct AssetLibrary *asset_library; | struct AssetLibrary *asset_library; | ||||
| short flags; | short flags; | ||||
| short sort; | short sort; | ||||
| FileListFilter filter_data; | FileListFilter filter_data; | ||||
| /** | |||||
| * File indexer to use. Attribute is always set. | |||||
| */ | |||||
| const struct FileIndexer *indexer; | |||||
| struct FileListIntern filelist_intern; | struct FileListIntern filelist_intern; | ||||
| struct FileListEntryCache filelist_cache; | struct FileListEntryCache filelist_cache; | ||||
| /* We need to keep those info outside of actual filelist items, | /* We need to keep those info outside of actual filelist items, | ||||
| * because those are no more persistent | * because those are no more persistent | ||||
| * (only generated on demand, and freed as soon as possible). | * (only generated on demand, and freed as soon as possible). | ||||
| * Persistent part (mere list of paths + stat info) | * Persistent part (mere list of paths + stat info) | ||||
| ▲ Show 20 Lines • Show All 672 Lines • ▼ Show 20 Lines | void filelist_setfilter_options(FileList *filelist, | ||||
| if (update) { | if (update) { | ||||
| /* And now, free filtered data so that we know we have to filter again. */ | /* And now, free filtered data so that we know we have to filter again. */ | ||||
| filelist_tag_needs_filtering(filelist); | filelist_tag_needs_filtering(filelist); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Set the indexer to be used by the filelist. | |||||
| * | |||||
| * The given indexer allocation should be handled by the caller or defined statically. | |||||
| */ | |||||
| void filelist_setindexer(FileList *filelist, const FileIndexer *indexer) | |||||
| { | |||||
| BLI_assert(filelist); | |||||
| BLI_assert(indexer); | |||||
| filelist->indexer = indexer; | |||||
| } | |||||
| /** | |||||
| * \param catalog_id: The catalog that should be filtered by if \a catalog_visibility is | * \param catalog_id: The catalog that should be filtered by if \a catalog_visibility is | ||||
| * #FILE_SHOW_ASSETS_FROM_CATALOG. May be NULL otherwise. | * #FILE_SHOW_ASSETS_FROM_CATALOG. May be NULL otherwise. | ||||
| */ | */ | ||||
| void filelist_set_asset_catalog_filter_options( | void filelist_set_asset_catalog_filter_options( | ||||
| FileList *filelist, | FileList *filelist, | ||||
| eFileSel_Params_AssetCatalogVisibility catalog_visibility, | eFileSel_Params_AssetCatalogVisibility catalog_visibility, | ||||
| const bUUID *catalog_id) | const bUUID *catalog_id) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 675 Lines • ▼ Show 20 Lines | FileList *filelist_new(short type) | ||||
| FileList *p = MEM_callocN(sizeof(*p), __func__); | FileList *p = MEM_callocN(sizeof(*p), __func__); | ||||
| filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT); | filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT); | ||||
| p->selection_state = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); | p->selection_state = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); | ||||
| p->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET; | p->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET; | ||||
| filelist_settype(p, type); | filelist_settype(p, type); | ||||
| p->indexer = &file_indexer_noop; | |||||
| return p; | return p; | ||||
| } | } | ||||
| void filelist_settype(FileList *filelist, short type) | void filelist_settype(FileList *filelist, short type) | ||||
| { | { | ||||
| if (filelist->type == type) { | if (filelist->type == type) { | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,207 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); | FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); | ||||
| entry->relpath = BLI_strdup(group_name); | entry->relpath = BLI_strdup(group_name); | ||||
| entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR; | entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR; | ||||
| entry->blentype = idcode; | entry->blentype = idcode; | ||||
| return entry; | return entry; | ||||
| } | } | ||||
| static void filelist_readjob_list_lib_add_datablocks(ListBase *entries, | static void filelist_readjob_list_lib_add_datablock(ListBase *entries, | ||||
| LinkNode *datablock_infos, | const BLODataBlockInfo *datablock_info, | ||||
| const bool prefix_relpath_with_group_name, | const bool prefix_relpath_with_group_name, | ||||
| const int idcode, | const int idcode, | ||||
| const char *group_name) | const char *group_name) | ||||
| { | { | ||||
| for (LinkNode *ln = datablock_infos; ln; ln = ln->next) { | |||||
| struct BLODataBlockInfo *info = ln->link; | |||||
| FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); | FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); | ||||
| if (prefix_relpath_with_group_name) { | if (prefix_relpath_with_group_name) { | ||||
| entry->relpath = BLI_sprintfN("%s/%s", group_name, info->name); | entry->relpath = BLI_sprintfN("%s/%s", group_name, datablock_info->name); | ||||
| } | } | ||||
| else { | else { | ||||
| entry->relpath = BLI_strdup(info->name); | entry->relpath = BLI_strdup(datablock_info->name); | ||||
| } | } | ||||
| entry->typeflag |= FILE_TYPE_BLENDERLIB; | entry->typeflag |= FILE_TYPE_BLENDERLIB; | ||||
| if (info && info->asset_data) { | if (datablock_info && datablock_info->asset_data) { | ||||
| entry->typeflag |= FILE_TYPE_ASSET; | entry->typeflag |= FILE_TYPE_ASSET; | ||||
| /* Moves ownership! */ | /* Moves ownership! */ | ||||
| entry->imported_asset_data = info->asset_data; | entry->imported_asset_data = datablock_info->asset_data; | ||||
| } | } | ||||
| entry->blentype = idcode; | entry->blentype = idcode; | ||||
| BLI_addtail(entries, entry); | BLI_addtail(entries, entry); | ||||
| } | } | ||||
| static void filelist_readjob_list_lib_add_datablocks(ListBase *entries, | |||||
| LinkNode *datablock_infos, | |||||
| const bool prefix_relpath_with_group_name, | |||||
| const int idcode, | |||||
| const char *group_name) | |||||
| { | |||||
| for (LinkNode *ln = datablock_infos; ln; ln = ln->next) { | |||||
| struct BLODataBlockInfo *datablock_info = ln->link; | |||||
| filelist_readjob_list_lib_add_datablock( | |||||
| entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name); | |||||
| } | |||||
| } | |||||
| static void filelist_readjob_list_lib_add_from_indexer_entries( | |||||
| ListBase *entries, | |||||
| const FileIndexerEntries *indexer_entries, | |||||
| const bool prefix_relpath_with_group_name) | |||||
| { | |||||
| for (const LinkNode *ln = indexer_entries->entries; ln; ln = ln->next) { | |||||
| const FileIndexerEntry *indexer_entry = (const FileIndexerEntry *)ln->link; | |||||
| const char *group_name = BKE_idtype_idcode_to_name(indexer_entry->idcode); | |||||
| filelist_readjob_list_lib_add_datablock(entries, | |||||
| &indexer_entry->datablock_info, | |||||
| prefix_relpath_with_group_name, | |||||
| indexer_entry->idcode, | |||||
| group_name); | |||||
| } | |||||
| } | |||||
| static FileListInternEntry *filelist_readjob_list_lib_navigate_to_parent_entry_create(void) | |||||
| { | |||||
| FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); | |||||
| entry->relpath = BLI_strdup(FILENAME_PARENT); | |||||
| entry->typeflag |= (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR); | |||||
| return entry; | |||||
| } | |||||
| /** | |||||
| * Structure to keep the file indexer and its user data together. | |||||
| */ | |||||
| typedef struct FileIndexerRuntimeData { | |||||
| const FileIndexer *callbacks; | |||||
| /** | |||||
| * User data. Contains the result of `callbacks.init_user_data`. | |||||
| */ | |||||
| void *user_data; | |||||
| } FileIndexerRuntimeData; | |||||
| static int filelist_readjob_list_lib_populate_from_index(ListBase *entries, | |||||
| const ListLibOptions options, | |||||
| const int read_from_index, | |||||
| const FileIndexerEntries *indexer_entries) | |||||
| { | |||||
| int navigate_to_parent_len = 0; | |||||
| if (options & LIST_LIB_ADD_PARENT) { | |||||
| FileListInternEntry *entry = filelist_readjob_list_lib_navigate_to_parent_entry_create(); | |||||
| BLI_addtail(entries, entry); | |||||
| navigate_to_parent_len = 1; | |||||
| } | |||||
| filelist_readjob_list_lib_add_from_indexer_entries(entries, indexer_entries, true); | |||||
| return read_from_index + navigate_to_parent_len; | |||||
| } | } | ||||
| static int filelist_readjob_list_lib(const char *root, | static int filelist_readjob_list_lib(const char *root, | ||||
| ListBase *entries, | ListBase *entries, | ||||
| const ListLibOptions options) | const ListLibOptions options, | ||||
| FileIndexerRuntimeData *indexer) | |||||
| { | { | ||||
| BLI_assert(indexer); | |||||
| char dir[FILE_MAX_LIBEXTRA], *group; | char dir[FILE_MAX_LIBEXTRA], *group; | ||||
| struct BlendHandle *libfiledata = NULL; | struct BlendHandle *libfiledata = NULL; | ||||
| /* Check if the given root is actually a library. All folders are passed to | /* Check if the given root is actually a library. All folders are passed to | ||||
| * `filelist_readjob_list_lib` and based on the number of found entries `filelist_readjob_do` | * `filelist_readjob_list_lib` and based on the number of found entries `filelist_readjob_do` | ||||
| * will do a dir listing only when this function does not return any entries. */ | * will do a dir listing only when this function does not return any entries. */ | ||||
| /* TODO: We should consider introducing its own function to detect if it is a lib and | /* TODO(jbakker): We should consider introducing its own function to detect if it is a lib and | ||||
| * call it directly from `filelist_readjob_do` to increase readability. */ | * call it directly from `filelist_readjob_do` to increase readability. */ | ||||
| const bool is_lib = BLO_library_path_explode(root, dir, &group, NULL); | const bool is_lib = BLO_library_path_explode(root, dir, &group, NULL); | ||||
| if (!is_lib) { | if (!is_lib) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| const bool group_came_from_path = group != NULL; | |||||
| /* Try read from indexer. */ | |||||
| /* Indexing returns all entries in a blend file. We should ignore the index when listing a group | |||||
| * inside a blend file, so the `entries` isn't filled with undesired entries. | |||||
| * This happens when linking or appending data-blocks, where you can navigate into a group (fe | |||||
| * Materials/Objects) where you only want to work with partial indexes. | |||||
| * | |||||
| * Adding support for partial reading/updating indexes would increase the complexity. | |||||
| */ | |||||
| const bool use_indexer = !group_came_from_path; | |||||
| FileIndexerEntries indexer_entries = {NULL}; | |||||
| if (use_indexer) { | |||||
| int read_from_index = 0; | |||||
| eFileIndexerResult indexer_result = indexer->callbacks->read_index( | |||||
| dir, &indexer_entries, &read_from_index, indexer->user_data); | |||||
| if (indexer_result == FILE_INDEXER_ENTRIES_LOADED) { | |||||
| int entries_read = filelist_readjob_list_lib_populate_from_index( | |||||
| entries, options, read_from_index, &indexer_entries); | |||||
| ED_file_indexer_entries_clear(&indexer_entries); | |||||
| return entries_read; | |||||
| } | |||||
| } | |||||
| /* Open the library file. */ | /* Open the library file. */ | ||||
| BlendFileReadReport bf_reports = {.reports = NULL}; | BlendFileReadReport bf_reports = {.reports = NULL}; | ||||
| libfiledata = BLO_blendhandle_from_file(dir, &bf_reports); | libfiledata = BLO_blendhandle_from_file(dir, &bf_reports); | ||||
| if (libfiledata == NULL) { | if (libfiledata == NULL) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* Add current parent when requested. */ | /* Add current parent when requested. */ | ||||
| int parent_len = 0; | /* Is the navigate to previous level added to the list of entries. When added the return value | ||||
| * should be increased to match the actual number of entries added. It is introduced to keep | |||||
| * the code clean and readable and not counting in a single variable. */ | |||||
| int navigate_to_parent_len = 0; | |||||
| if (options & LIST_LIB_ADD_PARENT) { | if (options & LIST_LIB_ADD_PARENT) { | ||||
| FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); | FileListInternEntry *entry = filelist_readjob_list_lib_navigate_to_parent_entry_create(); | ||||
| entry->relpath = BLI_strdup(FILENAME_PARENT); | |||||
| entry->typeflag |= (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR); | |||||
| BLI_addtail(entries, entry); | BLI_addtail(entries, entry); | ||||
| parent_len = 1; | navigate_to_parent_len = 1; | ||||
| } | } | ||||
| int group_len = 0; | int group_len = 0; | ||||
| int datablock_len = 0; | int datablock_len = 0; | ||||
| const bool group_came_from_path = group != NULL; | |||||
| if (group_came_from_path) { | if (group_came_from_path) { | ||||
| const int idcode = groupname_to_code(group); | const int idcode = groupname_to_code(group); | ||||
| LinkNode *datablock_infos = BLO_blendhandle_get_datablock_info( | LinkNode *datablock_infos = BLO_blendhandle_get_datablock_info( | ||||
| libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &datablock_len); | libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &datablock_len); | ||||
| filelist_readjob_list_lib_add_datablocks(entries, datablock_infos, false, idcode, group); | filelist_readjob_list_lib_add_datablocks(entries, datablock_infos, false, idcode, group); | ||||
| BLI_linklist_freeN(datablock_infos); | BLI_linklist_freeN(datablock_infos); | ||||
| } | } | ||||
| else { | else { | ||||
| LinkNode *groups = BLO_blendhandle_get_linkable_groups(libfiledata); | LinkNode *groups = BLO_blendhandle_get_linkable_groups(libfiledata); | ||||
| group_len = BLI_linklist_count(groups); | group_len = BLI_linklist_count(groups); | ||||
| for (LinkNode *ln = groups; ln; ln = ln->next) { | for (LinkNode *ln = groups; ln; ln = ln->next) { | ||||
| const char *group_name = ln->link; | const char *group_name = ln->link; | ||||
| const int idcode = groupname_to_code(group_name); | const int idcode = groupname_to_code(group_name); | ||||
| FileListInternEntry *group_entry = filelist_readjob_list_lib_group_create(idcode, | FileListInternEntry *group_entry = filelist_readjob_list_lib_group_create(idcode, | ||||
| group_name); | group_name); | ||||
| BLI_addtail(entries, group_entry); | BLI_addtail(entries, group_entry); | ||||
| if (options & LIST_LIB_RECURSIVE) { | if (options & LIST_LIB_RECURSIVE) { | ||||
| int group_datablock_len; | int group_datablock_len; | ||||
| LinkNode *group_datablock_infos = BLO_blendhandle_get_datablock_info( | LinkNode *group_datablock_infos = BLO_blendhandle_get_datablock_info( | ||||
| libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &group_datablock_len); | libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &group_datablock_len); | ||||
| filelist_readjob_list_lib_add_datablocks( | filelist_readjob_list_lib_add_datablocks( | ||||
| entries, group_datablock_infos, true, idcode, group_name); | entries, group_datablock_infos, true, idcode, group_name); | ||||
| if (use_indexer) { | |||||
| ED_file_indexer_entries_extend_from_datablock_infos( | |||||
| &indexer_entries, group_datablock_infos, idcode); | |||||
| } | |||||
| BLI_linklist_freeN(group_datablock_infos); | BLI_linklist_freeN(group_datablock_infos); | ||||
| datablock_len += group_datablock_len; | datablock_len += group_datablock_len; | ||||
| } | } | ||||
| } | } | ||||
| BLI_linklist_freeN(groups); | BLI_linklist_freeN(groups); | ||||
| } | } | ||||
| BLO_blendhandle_close(libfiledata); | BLO_blendhandle_close(libfiledata); | ||||
| /* Update the index. */ | |||||
| if (use_indexer) { | |||||
| indexer->callbacks->update_index(dir, &indexer_entries, indexer->user_data); | |||||
| ED_file_indexer_entries_clear(&indexer_entries); | |||||
| } | |||||
| /* Return the number of items added to entries. */ | /* Return the number of items added to entries. */ | ||||
| int added_entries_len = group_len + datablock_len + parent_len; | int added_entries_len = group_len + datablock_len + navigate_to_parent_len; | ||||
| return added_entries_len; | return added_entries_len; | ||||
| } | } | ||||
| #if 0 | #if 0 | ||||
| /* Kept for reference here, in case we want to add back that feature later. | /* Kept for reference here, in case we want to add back that feature later. | ||||
| * We do not need it currently. */ | * We do not need it currently. */ | ||||
| /* Code ***NOT*** updated for job stuff! */ | /* Code ***NOT*** updated for job stuff! */ | ||||
| static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) | static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) | ||||
| ▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | typedef struct FileListReadJob { | ||||
| Main *current_main; | Main *current_main; | ||||
| struct FileList *filelist; | struct FileList *filelist; | ||||
| /** Shallow copy of #filelist for thread-safe access. | /** Shallow copy of #filelist for thread-safe access. | ||||
| * | * | ||||
| * The job system calls #filelist_readjob_update which moves any read file from #tmp_filelist | * The job system calls #filelist_readjob_update which moves any read file from #tmp_filelist | ||||
| * into #filelist in a thread-safe way. | * into #filelist in a thread-safe way. | ||||
| * | * | ||||
| * #tmp_filelist also keeps an `AssetLibrary *` so that it can be loaded in the same thread, and | * #tmp_filelist also keeps an `AssetLibrary *` so that it can be loaded in the same thread, | ||||
| * moved to #filelist once all categories are loaded. | * and moved to #filelist once all categories are loaded. | ||||
| * | * | ||||
| * NOTE: #tmp_filelist is freed in #filelist_readjob_free, so any copied pointers need to be set | * NOTE: #tmp_filelist is freed in #filelist_readjob_free, so any copied pointers need to be | ||||
| * to NULL to avoid double-freeing them. */ | * set to NULL to avoid double-freeing them. */ | ||||
| struct FileList *tmp_filelist; | struct FileList *tmp_filelist; | ||||
| } FileListReadJob; | } FileListReadJob; | ||||
| static bool filelist_readjob_should_recurse_into_entry(const int max_recursion, | static bool filelist_readjob_should_recurse_into_entry(const int max_recursion, | ||||
| const bool is_lib, | const bool is_lib, | ||||
| const int current_recursion_level, | const int current_recursion_level, | ||||
| FileListInternEntry *entry) | FileListInternEntry *entry) | ||||
| { | { | ||||
| if (max_recursion == 0) { | if (max_recursion == 0) { | ||||
| /* Recursive loading is disabled. */ | /* Recursive loading is disabled. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (!is_lib && current_recursion_level > max_recursion) { | if (!is_lib && current_recursion_level > max_recursion) { | ||||
| /* No more levels of recursion left. */ | /* No more levels of recursion left. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Show entries when recursion is set to `Blend file` even when `current_recursion_level` exceeds | /* Show entries when recursion is set to `Blend file` even when `current_recursion_level` | ||||
| * `max_recursion`. */ | * exceeds `max_recursion`. */ | ||||
| if (!is_lib && (current_recursion_level >= max_recursion) && | if (!is_lib && (current_recursion_level >= max_recursion) && | ||||
| ((entry->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) == 0)) { | ((entry->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) == 0)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (entry->typeflag & FILE_TYPE_BLENDERLIB) { | if (entry->typeflag & FILE_TYPE_BLENDERLIB) { | ||||
| /* Libraries are already loaded recursively when recursive loaded is used. No need to add | /* Libraries are already loaded recursively when recursive loaded is used. No need to add | ||||
| * them another time. This loading is done with the `LIST_LIB_RECURSIVE` option. */ | * them another time. This loading is done with the `LIST_LIB_RECURSIVE` option. */ | ||||
| return false; | return false; | ||||
| Show All 38 Lines | static void filelist_readjob_do(const bool do_lib, | ||||
| td_dir->level = 1; | td_dir->level = 1; | ||||
| BLI_strncpy(dir, filelist->filelist.root, sizeof(dir)); | BLI_strncpy(dir, filelist->filelist.root, sizeof(dir)); | ||||
| BLI_strncpy(filter_glob, filelist->filter_data.filter_glob, sizeof(filter_glob)); | BLI_strncpy(filter_glob, filelist->filter_data.filter_glob, sizeof(filter_glob)); | ||||
| BLI_path_normalize_dir(job_params->main_name, dir); | BLI_path_normalize_dir(job_params->main_name, dir); | ||||
| td_dir->dir = BLI_strdup(dir); | td_dir->dir = BLI_strdup(dir); | ||||
| /* Init the file indexer. */ | |||||
| FileIndexerRuntimeData indexer_rt = {.callbacks = filelist->indexer}; | |||||
| if (indexer_rt.callbacks->init_user_data) { | |||||
| indexer_rt.user_data = indexer_rt.callbacks->init_user_data(filelist->asset_library_ref); | |||||
| } | |||||
| while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) { | while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) { | ||||
| FileListInternEntry *entry; | FileListInternEntry *entry; | ||||
| int nbr_entries = 0; | int nbr_entries = 0; | ||||
| char *subdir; | char *subdir; | ||||
| char rel_subdir[FILE_MAX_LIBEXTRA]; | char rel_subdir[FILE_MAX_LIBEXTRA]; | ||||
| int recursion_level; | int recursion_level; | ||||
| bool skip_currpar; | bool skip_currpar; | ||||
| Show All 26 Lines | if (do_lib) { | ||||
| if (max_recursion > 0) { | if (max_recursion > 0) { | ||||
| list_lib_options |= LIST_LIB_RECURSIVE; | list_lib_options |= LIST_LIB_RECURSIVE; | ||||
| } | } | ||||
| /* Only load assets when browsing an asset library. For normal file browsing we return all | /* Only load assets when browsing an asset library. For normal file browsing we return all | ||||
| * entries. `FLF_ASSETS_ONLY` filter can be enabled/disabled by the user.*/ | * entries. `FLF_ASSETS_ONLY` filter can be enabled/disabled by the user.*/ | ||||
| if (filelist->asset_library_ref) { | if (filelist->asset_library_ref) { | ||||
| list_lib_options |= LIST_LIB_ASSETS_ONLY; | list_lib_options |= LIST_LIB_ASSETS_ONLY; | ||||
| } | } | ||||
| nbr_entries = filelist_readjob_list_lib(subdir, &entries, list_lib_options); | nbr_entries = filelist_readjob_list_lib(subdir, &entries, list_lib_options, &indexer_rt); | ||||
| if (nbr_entries > 0) { | if (nbr_entries > 0) { | ||||
| is_lib = true; | is_lib = true; | ||||
| } | } | ||||
| } | } | ||||
| if (!is_lib) { | if (!is_lib) { | ||||
| nbr_entries = filelist_readjob_list_dir( | nbr_entries = filelist_readjob_list_dir( | ||||
| subdir, &entries, filter_glob, do_lib, job_params->main_name, skip_currpar); | subdir, &entries, filter_glob, do_lib, job_params->main_name, skip_currpar); | ||||
| Show All 34 Lines | if (nbr_entries) { | ||||
| BLI_mutex_unlock(&job_params->lock); | BLI_mutex_unlock(&job_params->lock); | ||||
| } | } | ||||
| nbr_done_dirs++; | nbr_done_dirs++; | ||||
| *progress = (float)nbr_done_dirs / (float)nbr_todo_dirs; | *progress = (float)nbr_done_dirs / (float)nbr_todo_dirs; | ||||
| MEM_freeN(subdir); | MEM_freeN(subdir); | ||||
| } | } | ||||
| /* Finalize and free indexer. */ | |||||
| if (indexer_rt.callbacks->filelist_finished && BLI_stack_is_empty(todo_dirs)) { | |||||
| indexer_rt.callbacks->filelist_finished(indexer_rt.user_data); | |||||
| } | |||||
| if (indexer_rt.callbacks->free_user_data && indexer_rt.user_data) { | |||||
| indexer_rt.callbacks->free_user_data(indexer_rt.user_data); | |||||
| indexer_rt.user_data = NULL; | |||||
| } | |||||
| /* If we were interrupted by stop, stack may not be empty and we need to free | /* If we were interrupted by stop, stack may not be empty and we need to free | ||||
| * pending dir paths. */ | * pending dir paths. */ | ||||
| while (!BLI_stack_is_empty(todo_dirs)) { | while (!BLI_stack_is_empty(todo_dirs)) { | ||||
| td_dir = BLI_stack_peek(todo_dirs); | td_dir = BLI_stack_peek(todo_dirs); | ||||
| MEM_freeN(td_dir->dir); | MEM_freeN(td_dir->dir); | ||||
| BLI_stack_discard(todo_dirs); | BLI_stack_discard(todo_dirs); | ||||
| } | } | ||||
| BLI_stack_free(todo_dirs); | BLI_stack_free(todo_dirs); | ||||
| Show All 38 Lines | static void filelist_readjob_load_asset_library_data(FileListReadJob *job_params, short *do_update) | ||||
| if (job_params->filelist->asset_library_ref != NULL) { | if (job_params->filelist->asset_library_ref != NULL) { | ||||
| char library_root_path[FILE_MAX]; | char library_root_path[FILE_MAX]; | ||||
| filelist_asset_library_path(job_params, library_root_path); | filelist_asset_library_path(job_params, library_root_path); | ||||
| /* Load asset catalogs, into the temp filelist for thread-safety. | /* Load asset catalogs, into the temp filelist for thread-safety. | ||||
| * #filelist_readjob_endjob() will move it into the real filelist. */ | * #filelist_readjob_endjob() will move it into the real filelist. */ | ||||
| tmp_filelist->asset_library = BKE_asset_library_load(library_root_path); | tmp_filelist->asset_library = BKE_asset_library_load(library_root_path); | ||||
| /* AssetLibraryIndexing needs the reference to generate the correct name for the index | |||||
| * folder. See `AssetLibraryIndex`. As both instances are freed we need duplicate the | |||||
| * instance. | |||||
| * TODO(jbakker): We should consider copying the struct in stead of using pointers. */ | |||||
| tmp_filelist->asset_library_ref = MEM_dupallocN(job_params->filelist->asset_library_ref); | |||||
| *do_update = true; | *do_update = true; | ||||
| } | } | ||||
| } | } | ||||
| static void filelist_readjob_asset_library(FileListReadJob *job_params, | static void filelist_readjob_asset_library(FileListReadJob *job_params, | ||||
| short *stop, | short *stop, | ||||
| short *do_update, | short *do_update, | ||||
| float *progress) | float *progress) | ||||
| ▲ Show 20 Lines • Show All 233 Lines • Show Last 20 Lines | |||||