Commit: fb2c646deeb917a6fac8a7d0e697dc518a8df3ec
Author: Bastien Montagne
Date:   Fri Feb 13 22:28:36 2015 +0100
Branches: asset-experiments
https://developer.blender.org/rBfb2c646deeb917a6fac8a7d0e697dc518a8df3ec

Rework job multi-level listing - factorize even more and avoid recursion.

This is much cleaner than previous code...

===================================================================

M       source/blender/editors/include/UI_interface_icons.h
M       source/blender/editors/space_file/filelist.c
M       source/blender/makesrna/intern/rna_ID.c

===================================================================

diff --git a/source/blender/editors/include/UI_interface_icons.h 
b/source/blender/editors/include/UI_interface_icons.h
index 549ee99..c721af1 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -34,6 +34,7 @@
 
 struct bContext;
 struct ID;
+struct Scene;
 struct Image;
 struct ImBuf;
 struct World;
diff --git a/source/blender/editors/space_file/filelist.c 
b/source/blender/editors/space_file/filelist.c
index ec5991a..b08a010 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -37,10 +37,10 @@
 #include <string.h>
 
 #ifndef WIN32
-#include <unistd.h>
+#  include <unistd.h>
 #else
-#include <io.h>
-#include <direct.h>
+#  include <io.h>
+#  include <direct.h>
 #endif   
 #include "MEM_guardedalloc.h"
 
@@ -49,6 +49,7 @@
 #include "BLI_fnmatch.h"
 #include "BLI_linklist.h"
 #include "BLI_math.h"
+#include "BLI_stack.h"
 #include "BLI_threads.h"
 #include "BLI_utildefines.h"
 #include "BLI_fileops_types.h"
@@ -1229,7 +1230,9 @@ int ED_file_extension_icon(const char *path)
        return ICON_FILE_BLANK;
 }
 
-static void filelist_setfiletypes(const char *root, struct direntry *files, 
const int numfiles, const char *filter_glob)
+static void filelist_setfiletypes(
+        const char *root, struct direntry *files, const int numfiles, const 
char *filter_glob,
+        const bool do_lib, const char *main_name)
 {
        struct direntry *file;
        int num;
@@ -1252,6 +1255,19 @@ static void filelist_setfiletypes(const char *root, 
struct direntry *files, cons
                else {
                        file->flags = file_extension_type(root, file->relname);
                }
+
+               /* If we are considering .blend files as libs, promote them to 
directory status! */
+               if (do_lib && BLO_has_bfile_extension(file->relname)) {
+                       char name[FILE_MAX];
+
+                       BLI_join_dirfile(name, sizeof(name), root, 
file->relname);
+
+                       /* prevent current file being used as acceptable dir */
+                       if (BLI_path_cmp(main_name, name) != 0) {
+                               file->type &= ~S_IFMT;
+                               file->type |= S_IFDIR;
+                       }
+               }
        }
 }
 
@@ -1354,13 +1370,20 @@ static unsigned int groupname_to_filter_id(const char 
*group)
  * and main one (used by UI among other things).
  */
 
+typedef struct TodoDir {
+       int level;
+       char *dir;
+} TodoDir;
+
 /* This helper is highly specialized for our needs, it 'transfers' most data 
(strings/pointers) from subfiles to
  * filelist_buff. Only dirname->relname is actually duplicated.
+ * It also detects new sub-directories we want to list too, and add them to 
todo_dirs stack.
  */
 static void filelist_readjob_merge_sublist(
-        struct direntry **filelist_buff, int *filelist_buff_size, int 
*filelist_used_size,
-        const char *root, const char *subdir, struct direntry *subfiles, const 
int num_subfiles,
-        const bool ignore_currpar)
+        struct direntry **filelist_buff, int *filelist_buff_size, int 
*filelist_used_size, const char *main_name,
+        const char *root, const char *subdir, struct direntry *subfiles, const 
int num_subfiles, int *done_files,
+        const bool is_lib, const bool ignore_currpar, const int 
recursion_level, const int max_recursion,
+        BLI_Stack *todo_dirs)
 {
        if (num_subfiles) {
                struct direntry *f;
@@ -1380,7 +1403,7 @@ static void filelist_readjob_merge_sublist(
                        *filelist_buff = new_filelist;
                }
                for (i = *filelist_used_size, j = 0, f = subfiles; j < 
num_subfiles; j++, f++) {
-                       if (ignore_currpar&& FILENAME_IS_CURRPAR(f->relname)) {
+                       if (ignore_currpar && FILENAME_IS_CURRPAR(f->relname)) {
                                /* Ignore 'inner' curr/parent! */
                                new_numfiles--;
                                continue;
@@ -1390,6 +1413,32 @@ static void filelist_readjob_merge_sublist(
                        BLI_path_rel(dir, root);
                        (*filelist_buff)[i] = *f;
                        (*filelist_buff)[i].relname = BLI_strdup(dir + 2);  /* 
+ 2 to remove '//' added by BLI_path_rel */
+                       (*done_files)++;
+
+                       /* Here we decide whether current filedirentry is to be 
listed too, or not. */
+                       /* Not a loop, just to be able to break. */
+                       while (max_recursion && (is_lib || (recursion_level <= 
max_recursion))) {
+                               TodoDir *td_dir;
+
+                               if ((f->type & S_IFDIR) == 0) {
+                                       break;
+                               }
+                               else if (!is_lib && (recursion_level >= 
max_recursion) &&
+                                                !ELEM(f->flags, 
FILE_TYPE_BLENDER, FILE_TYPE_BLENDER_BACKUP))
+                               {
+                                       /* Do not recurse in real directories 
in this case, only in .blend libs. */
+                                       break;
+                               }
+
+                               /* We have a directory we want to list, add it 
to todo list! */
+                               BLI_join_dirfile(dir, sizeof(dir), root, 
(*filelist_buff)[i].relname);
+                               BLI_cleanup_dir(main_name, dir);
+                               td_dir = BLI_stack_push_r(todo_dirs);
+                               td_dir->level = recursion_level + 1;
+                               td_dir->dir = BLI_strdup(dir);
+                               break;
+                       }
+
                        /* those pointers are given to new_filelist... */
                        f->path = NULL;
                        f->poin = NULL;
@@ -1437,9 +1486,9 @@ static void filelist_readjob_list_lib(const char *root, 
struct direntry **files,
 
        BLO_blendhandle_close(libfiledata);
 
+       BLI_assert(*files == NULL);
        *num_files = nnames + 1;
-       *files = malloc(*num_files * sizeof(**files));
-       memset(*files, 0, *num_files * sizeof(**files));
+       *files = calloc(*num_files, sizeof(**files));
 
        (*files)[nnames].relname = BLI_strdup(FILENAME_PARENT);
        (*files)[nnames].type |= S_IFDIR;
@@ -1640,101 +1689,60 @@ static void filelist_readjob_main_rec(struct FileList 
*filelist)
 }
 #endif
 
-static void filelist_readjob_dir_lib_rec(
+static void filelist_readjob_dir_lib(
         const bool do_lib, const char *main_name,
-        FileList *filelist, int *filelist_buffsize, const char *dir, const 
char *filter_glob, const int recursion_level,
+        FileList *filelist, int *filelist_buffsize, BLI_Stack *todo_dirs, 
const char *filter_glob,
         short *stop, short *do_update, float *progress, int *done_files, 
ThreadMutex *lock)
 {
-       /* only used if recursing, will contain all non-immediate children 
then. */
-       struct direntry *file, *files = NULL;
-       bool is_lib = do_lib;
-       int num_files = 0;
-       int i;
-
-       if (!filelist) {
-               return;
-       }
-
-       if (do_lib) {
-               filelist_readjob_list_lib(dir, &files, &num_files);
-       }
-       if (!files) {
-               is_lib = false;
-               num_files = BLI_filelist_dir_contents(dir, &files);
-       }
-
-       if (!files) {
-               return;
-       }
-
-       /* We only set filtypes for our own level, sub ones will be set by 
subcalls. */
-       filelist_setfiletypes(dir, files, num_files, filter_glob);
+       while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) {
+               /* only used if recursing, will contain all non-immediate 
children then. */
+               struct direntry *files = NULL;
+               TodoDir td_dir;
+               bool is_lib = do_lib;
+               int num_files = 0;
 
-       if (do_lib) {
-               /* Promote blend files from mere file status to prestigious 
directory one! */
-               for (i = 0, file = files; i < num_files; i++, file++) {
-                       if (BLO_has_bfile_extension(file->relname)) {
-                               char name[FILE_MAX];
+               BLI_stack_pop(todo_dirs, &td_dir);
 
-                               BLI_join_dirfile(name, sizeof(name), dir, 
file->relname);
-
-                               /* prevent current file being used as 
acceptable dir */
-                               if (BLI_path_cmp(main_name, name) != 0) {
-                                       file->type &= ~S_IFMT;
-                                       file->type |= S_IFDIR;
-                               }
-                       }
+               if (do_lib) {
+                       filelist_readjob_list_lib(td_dir.dir, &files, 
&num_files);
+               }
+               if (!files) {
+                       is_lib = false;
+                       num_files = BLI_filelist_dir_contents(td_dir.dir, 
&files);
                }
-       }
-
-       BLI_mutex_lock(lock);
 
-       filelist_readjob_merge_sublist(&filelist->filelist, filelist_buffsize, 
&filelist->numfiles, filelist->dir,
-                                      dir, files, num_files, recursion_level > 
1);
+               if (!files) {
+                       continue;
+               }
 
-       (*done_files)++;
-       *progress = (float)(*done_files) / filelist->numfiles;
+               /* We only set filtypes for our own level, sub ones will be set 
by later iterations. */
+               filelist_setfiletypes(td_dir.dir, files, num_files, 
filter_glob, do_lib, main_name);
 
-       //~ printf("%f (%d / %d)\n", *progress, *done_files, 
filelist->numfiles);
+               BLI_mutex_lock(lock);
 
-       BLI_mutex_unlock(lock);
+               filelist_readjob_merge_sublist(&filelist->filelist, 
filelist_buffsize, &filelist->numfiles,
+                                              main_name, filelist->dir, 
td_dir.dir, files, num_files, done_files,
+                                              is_lib, td_dir.level > 1, 
td_dir.level, filelist->max_recursion, todo_dirs);
 
-       *do_update = true;
+               *progress = (float)(*done_files) / filelist->numfiles;
 
-       /* in case it's a lib we don't care anymore about max recursion 
level... */
-       if (!*stop && filelist->max_recursion && (do_lib || (recursion_level < 
filelist->max_recursion))) {
-               for (i = 0, file = files; i < num_files && !*stop; i++, file++) 
{
-                       char subdir[FILE_MAX];
+               //~ printf("%f (%d / %d)\n", *progress, *done_files, 
filelist->numfiles);
 
-                       if (FILENAME_IS_CURRPAR(file->relname)) {
-                               /* do not increase done_files here, we 
completly ignore those. */
-                               continue;
-                       }
-                       else if ((file->type & S_IFDIR) == 0) {
-                               (*done_files)++;
-                               continue;
-                       }
-                       else if (!is_lib && (recursion_level >= 
filelist->max_recursion) &&
-                                !ELEM(file->flags, FILE_TYPE_BLENDER, 
FILE_TYPE_BLENDER_BACKUP))
-                       {
-                               /* Do not recurse in real directories in this 
case, only in .blend libs. */
-                               continue;
-                       }
+               BLI_mutex_unlock(lock);
 
-                       BLI_join_dirfile(subdir, sizeof(subdir), dir, 
file->relname);
-                       BLI_cleanup_dir(main_name, subdir);
-                       filelist_readjob_dir_lib_rec(do_lib, main_name,
-                                                    filelist, 
filelist_buffsize, subdir, filter_glob, recursion_level + 1,
-                                                    stop, do_update, progress, 
done_files, lock);
-               }
+               *do_update = true;
+               BLI_filelist_free(files, num_files, NULL);
+               MEM_freeN(td_dir.dir);
        }
-       BLI_filelist_free(files, num_files, NULL);
 }
 
-static void filelist_readjob_dir(
+static void filelist_readjob_do(
+        const bool is_lib,
         FileList *filelist, const char *main_name, short *stop, short 
*do_update, float *progress, ThreadMutex *lock)
 {
-       char dir[FILE_MAX];
+       BLI_Stack *todo_dirs;
+       TodoDir *td_dir;
+       char dir[FILE_MAX_LIBEXTRA];
        char filter_glob[64];  /* TODO should be define! */
        int filelist_buffsize = 0;
        int done_files = 0;
@@ -1742,6 +1750,10 @@ static void filelist_readjob_dir(
        BLI_asser

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to