Fix T51902: Severe problem with relocating linked libraries when using proxies.
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 26 Jun 2017 16:55:30 +0000 (18:55 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 26 Jun 2017 16:55:30 +0000 (18:55 +0200)
Fix is a bit ugly, but cannot think of another solution for now, at
least this **should** not break anything else.

And now I go find myself a very remote, high and lonely mountain, climb
to its top, roar "I hate proxies!" a few times, and relax hearing the echos...

source/blender/blenkernel/BKE_library_query.h
source/blender/blenkernel/BKE_library_remap.h
source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/library_remap.c
source/blender/windowmanager/intern/wm_files_link.c

index 6cf18e28e17f7142e9ec39e6cacf3c831e808f72..d6e7d98f3719c3e483143f0e00ea0b4da79e5fe4 100644 (file)
@@ -83,6 +83,8 @@ enum {
        IDWALK_NOP      = 0,
        IDWALK_READONLY = (1 << 0),
        IDWALK_RECURSE  = (1 << 1),  /* Also implies IDWALK_READONLY. */
+
+       IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8),  /* Ugly special case :(((( */
 };
 
 /* Loop over all of the ID's this datablock links to. */
index 53d438a0fddce8dd595d3db190f64fc274990635..fd37fd762f4318e9d521ba3303e7cf33c8311351 100644 (file)
@@ -46,6 +46,11 @@ enum {
        /* This tells the callback func to force setting IDs using target one with a 'never NULL' pointer to NULL.
         * WARNING! Use with extreme care, this will leave database in broken state and can cause crashes very easily! */
        ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
+       /* Do not consider proxy/_group pointers of local objects as indirect usages...
+        * Our oh-so-beloved proxies again... Do not consider data used by local proxy object as indirect usage.
+        * This is needed e.g. in reload scenario, since we have to ensure remapping of Armature data of local proxy
+        * is also performed. Usual nightmare... */
+       ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
 };
 
 /* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */
index 931002e6bbc4a4a7c051fde8210e8fbb50a4746f..d1f0c87183d86d2763cad1546f192dae340b5af1 100644 (file)
@@ -512,7 +512,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
 
                                /* Object is special, proxies make things hard... */
                                const int data_cb_flag = data.cb_flag;
-                               const int proxy_cb_flag = (object->proxy || object->proxy_group) ? IDWALK_CB_INDIRECT_USAGE : 0;
+                               const int proxy_cb_flag = ((data.flag & IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 && (object->proxy || object->proxy_group)) ?
+                                                             IDWALK_CB_INDIRECT_USAGE : 0;
 
                                /* object data special case */
                                data.cb_flag |= proxy_cb_flag;
index 01ad4fb86ce6747f04109f58392ad863a1f5b6ac..5e5ba44f0399c5d3f4d32b63ed344a4578a7fb6a 100644 (file)
@@ -419,6 +419,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
        IDRemap id_remap_data;
        ListBase *lb_array[MAX_LIBARRAY];
        int i;
+       const int foreach_id_flags = (remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ? IDWALK_NO_INDIRECT_PROXY_DATA_USAGE : IDWALK_NOP;
 
        if (r_id_remap_data == NULL) {
                r_id_remap_data = &id_remap_data;
@@ -439,7 +440,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
 #endif
                r_id_remap_data->id = id;
                libblock_remap_data_preprocess(r_id_remap_data);
-               BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+               BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags);
        }
        else {
                i = set_listbasepointers(bmain, lb_array);
@@ -456,7 +457,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
                                        r_id_remap_data->id = id_curr;
                                        libblock_remap_data_preprocess(r_id_remap_data);
                                        BKE_library_foreach_ID_link(
-                                                   NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+                                                   NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags);
                                }
                        }
                }
index 3b733f9558c3be6b845a7668c9ec7730a21cc7ad..f19c999a4f1f6495d705e916712efc1de6009316 100644 (file)
@@ -608,7 +608,8 @@ static void lib_relocate_do(
        }
 
        /* Note that in reload case, we also want to replace indirect usages. */
-       const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
+       const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
+                                 (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
        for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) {
                WMLinkAppendDataItem *item = itemlink->link;
                ID *old_id = item->customdata;