Commit: 591f4549c958bc65fb02ef0011ec1d5ed475dc9a
Author: Bastien Montagne
Date:   Mon Oct 12 15:20:51 2015 +0200
Branches: master
https://developer.blender.org/rB591f4549c958bc65fb02ef0011ec1d5ed475dc9a

WM linking code rework.

New code loops much less, does re-open & close .blend files for each data type,
and is much much more flexible - it is also ready for id-remap & co work being 
done in branches.

Main idea is to store libraries & datablocks to link in a dedicated struct, in 
a way
that avoids too much looping, and also allows to search for a single datablock 
in several libraries.

Here again, no change is expected in current behavior of link/append tool, 
please report
if anything goes different!

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

M       source/blender/windowmanager/intern/wm_operators.c

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

diff --git a/source/blender/windowmanager/intern/wm_operators.c 
b/source/blender/windowmanager/intern/wm_operators.c
index aed1473..ac77b88 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -59,10 +59,13 @@
 #include "PIL_time.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_bitmap.h"
 #include "BLI_dial.h"
 #include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_linklist.h"
 #include "BLI_linklist_stack.h"
 #include "BLI_math.h"
+#include "BLI_memarena.h"
 #include "BLI_utildefines.h"
 #include "BLI_ghash.h"
 
@@ -2604,106 +2607,150 @@ static int wm_link_append_invoke(bContext *C, 
wmOperator *op, const wmEvent *UNU
 
 static short wm_link_append_flag(wmOperator *op)
 {
+       PropertyRNA *prop;
        short flag = 0;
 
-       if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT;
-       if (RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY;
-       if (RNA_struct_find_property(op->ptr, "relative_path") && 
RNA_boolean_get(op->ptr, "relative_path")) flag |= FILE_RELPATH;
-       if (RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK;
-       if (RNA_boolean_get(op->ptr, "instance_groups")) flag |= 
FILE_GROUP_INSTANCE;
+       if (RNA_boolean_get(op->ptr, "autoselect"))
+               flag |= FILE_AUTOSELECT;
+       if (RNA_boolean_get(op->ptr, "active_layer"))
+               flag |= FILE_ACTIVELAY;
+       if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && 
RNA_property_boolean_get(op->ptr, prop))
+               flag |= FILE_RELPATH;
+       if (RNA_boolean_get(op->ptr, "link"))
+               flag |= FILE_LINK;
+       if (RNA_boolean_get(op->ptr, "instance_groups"))
+               flag |= FILE_GROUP_INSTANCE;
 
        return flag;
 }
 
-/* Helper.
- *     if `name` is non-NULL, we assume a single-item link/append.
- *     else if `*todo_libraries` is NULL we assume first-run.
- */
-static void wm_link_append_do_libgroup(
-        bContext *C, wmOperator *op, const char *root, const char *libname, 
char *group, char *name,
-        const short flag, GSet **todo_libraries)
+typedef struct WMLinkAppendDataItem {
+       char *name;
+       BLI_bitmap *libraries;  /* All libs (from WMLinkAppendData.libraries) 
to try to load this ID from. */
+       int idcode;
+
+       ID *new_id;
+       void *customdata;
+} WMLinkAppendDataItem;
+
+typedef struct WMLinkAppendData {
+       LinkNodePair libraries;
+       LinkNodePair items;
+       int num_libraries;
+       int num_items;
+       short flag;
+
+       /* Internal 'private' data */
+       MemArena *memarena;
+} WMLinkAppendData;
+
+static WMLinkAppendData *wm_link_append_data_new(const int flag)
 {
-       Main *bmain = CTX_data_main(C);
-       Main *mainl;
-       BlendHandle *bh;
-       Library *lib;
+       MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+       WMLinkAppendData *lapp_data = BLI_memarena_calloc(ma, 
sizeof(*lapp_data));
 
-       char path[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
-       int idcode;
-       const bool is_first_run = (*todo_libraries == NULL);
+       lapp_data->flag = flag;
+       lapp_data->memarena = ma;
 
-       BLI_assert(group);
-       idcode = BKE_idcode_from_name(group);
+       return lapp_data;
+}
 
-       bh = BLO_blendhandle_from_file(libname, op->reports);
+static void wm_link_append_data_free(WMLinkAppendData *lapp_data)
+{
+       BLI_memarena_free(lapp_data->memarena);
+}
 
-       if (bh == NULL) {
-               /* unlikely since we just browsed it, but possible
-                * error reports will have been made by 
BLO_blendhandle_from_file() */
-               return;
-       }
+/* WARNING! *Never* call wm_link_append_data_library_add() after having added 
some items! */
 
-       /* here appending/linking starts */
-       mainl = BLO_library_link_begin(bmain, &bh, libname);
-       lib = mainl->curlib;
-       BLI_assert(lib);
+static void wm_link_append_data_library_add(WMLinkAppendData *lapp_data, const 
char *libname)
+{
+       size_t len = strlen(libname) + 1;
+       char *libpath = BLI_memarena_alloc(lapp_data->memarena, len);
 
-       if (mainl->versionfile < 250) {
-               BKE_reportf(op->reports, RPT_WARNING,
-                           "Linking or appending from a very old .blend file 
format (%d.%d), no animation conversion will "
-                           "be done! You may want to re-save your lib file 
with current Blender",
-                           mainl->versionfile, mainl->subversionfile);
-       }
+       BLI_strncpy(libpath, libname, len);
+       BLI_linklist_append_arena(&lapp_data->libraries, libpath, 
lapp_data->memarena);
+       lapp_data->num_libraries++;
+}
 
-       if (name) {
-               BLO_library_link_named_part_ex(mainl, &bh, name, idcode, flag, 
CTX_data_scene(C), CTX_wm_view3d(C));
-       }
-       else {
-               if (is_first_run) {
-                       *todo_libraries = BLI_gset_new(BLI_ghashutil_strhash_p, 
BLI_ghashutil_strcmp, __func__);
-               }
+static WMLinkAppendDataItem *wm_link_append_data_item_add(
+        WMLinkAppendData *lapp_data, const char *idname, const int idcode, 
void *customdata)
+{
+       WMLinkAppendDataItem *item = BLI_memarena_alloc(lapp_data->memarena, 
sizeof(*item));
+       size_t len = strlen(idname) + 1;
 
-               RNA_BEGIN (op->ptr, itemptr, "files")
-               {
-                       char curr_libname[FILE_MAX];
-                       int curr_idcode;
+       item->name = BLI_memarena_alloc(lapp_data->memarena, len);
+       BLI_strncpy(item->name, idname, len);
+       item->idcode = idcode;
+       item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, 
lapp_data->num_libraries);
 
-                       RNA_string_get(&itemptr, "name", relname);
+       item->new_id = NULL;
+       item->customdata = customdata;
 
-                       BLI_join_dirfile(path, sizeof(path), root, relname);
+       BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena);
+       lapp_data->num_items++;
 
-                       if (BLO_library_path_explode(path, curr_libname, 
&group, &name)) {
-                               if (!group || !name) {
-                                       continue;
-                               }
+       return item;
+}
 
-                               curr_idcode = BKE_idcode_from_name(group);
+static void wm_link_do(
+        WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene 
*scene, View3D *v3d)
+{
+       Main *mainl;
+       BlendHandle *bh;
+       Library *lib;
 
-                               if ((idcode == curr_idcode) && 
(BLI_path_cmp(curr_libname, libname) == 0)) {
-                                       BLO_library_link_named_part_ex(mainl, 
&bh, name, idcode, flag, CTX_data_scene(C), CTX_wm_view3d(C));
-                               }
-                               else if (is_first_run) {
-                                       BLI_join_dirfile(path, sizeof(path), 
curr_libname, group);
-                                       if (!BLI_gset_haskey(*todo_libraries, 
path)) {
-                                               
BLI_gset_insert(*todo_libraries, BLI_strdup(path));
-                                       }
-                               }
-                       }
+       const int flag = lapp_data->flag;
+
+       LinkNode *liblink, *itemlink;
+       int lib_idx, item_idx;
+
+       BLI_assert(lapp_data->num_items && lapp_data->num_libraries);
+
+       for (lib_idx = 0, liblink = lapp_data->libraries.list; liblink; 
lib_idx++, liblink = liblink->next) {
+               char *libname = liblink->link;
+
+               bh = BLO_blendhandle_from_file(libname, reports);
+
+               if (bh == NULL) {
+                       /* Unlikely since we just browsed it, but possible
+                        * Error reports will have been made by 
BLO_blendhandle_from_file() */
+                       continue;
                }
-               RNA_END;
-       }
-       BLO_library_link_end(mainl, &bh, flag, CTX_data_scene(C), 
CTX_wm_view3d(C));
 
-       BLO_blendhandle_close(bh);
+               /* here appending/linking starts */
+               mainl = BLO_library_link_begin(bmain, &bh, libname);
+               lib = mainl->curlib;
+               BLI_assert(lib);
+               UNUSED_VARS_NDEBUG(lib);
+
+               if (mainl->versionfile < 250) {
+                       BKE_reportf(reports, RPT_WARNING,
+                                   "Linking or appending from a very old 
.blend file format (%d.%d), no animation conversion will "
+                                   "be done! You may want to re-save your lib 
file with current Blender",
+                                   mainl->versionfile, mainl->subversionfile);
+               }
 
-       /* mark all library linked objects to be updated */
-       BKE_main_lib_objects_recalc_all(bmain);
-       IMB_colormanagement_check_file_config(bmain);
+               /* For each lib file, we try to link all items belonging to 
that lib,
+                * and tag those successful to not try to load them again with 
the other libs. */
+               for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; 
item_idx++, itemlink = itemlink->next) {
+                       WMLinkAppendDataItem *item = itemlink->link;
+                       ID *new_id;
 
-       /* append, rather than linking */
-       if ((flag & FILE_LINK) == 0) {
-               BLI_assert(BLI_findindex(&bmain->library, lib) != -1);
-               BKE_library_make_local(bmain, lib, true);
+                       if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) {
+                               continue;
+                       }
+
+                       new_id = BLO_library_link_named_part_ex(mainl, &bh, 
item->name, item->idcode, flag, scene, v3d);
+                       if (new_id) {
+                               /* If the link is sucessful, clear item's libs 
'todo' flags.
+                                * This avoids trying to link same item with 
other libraries to come. */
+                               BLI_BITMAP_SET_ALL(item->libraries, false, 
lapp_data->num_libraries);
+                               item->new_id = new_id;
+                       }
+               }
+
+               BLO_library_link_end(mainl, &bh, flag, scene, v3d);
+               BLO_blendhandle_close(bh);
        }
 }
 
@@ -2712,13 +2759,12 @@ static int wm_link_append_exec(bContext *C, wmOperator 
*op)
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        PropertyRNA *prop;
+       WMLinkAppendData *lapp_data;
        char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX], 
relname[FILE_MAX];
        char *group, *name;
        int totfiles = 0;
        short flag;
 
-       GSet *todo_libraries = NULL;
-
        RNA_string_get(op->ptr, "filename", relname);
        RNA_string_get(op->ptr, "directory", root);
 
@@ -2726,15 +2772,15 @@ static int wm_link_append_exec(bContext *C, wmOperator 
*op)
 
        /* test if we have a valid data */
        if (!BLO_library_path_explode(path, libname, &group, &name)) {
-               BKE_report(op->reports, RPT_ERROR, "Not a library");
+               BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", 
path);
                return OPERATOR_CANCELLED;
        }
        else if (!group) {
-               BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+               BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", 
path);
                return OPERATOR_CANCELLED;
        }
        else if (BLI_path_cmp(bmain->name, libname) == 0) {
-               BKE_report(op->reports, RPT_ERROR, "Cannot use current file as 
library");
+               BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current 
file as library", path);
                return OPERATOR_CANCELLED;
        }
 
@@ -2744,55 +2790,112 @@ static int wm_link_append_exec(bContext *C, wmOperator 
*op)
                totfiles = RNA_property_collection_length(op->ptr, prop);
                if (totfiles == 0) {
                        if (!name) {
-                               BKE_report(op->reports, RPT_ERROR, "Nothing 
indicated");
+                               BKE_reportf(op->reports, RPT_ERROR, "'%s': 
nothing indicated", path);
                                return OPERATOR_CANCELLED;
                        }
                }
        }
        else if (!name) {
-               BKE_report(op->reports, RP

@@ 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