Fix (unreported) missing handling of 'never self' ID pointers in library_query and...
authorBastien Montagne <montagne29@wanadoo.fr>
Sun, 3 Mar 2019 20:56:38 +0000 (21:56 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Sun, 3 Mar 2019 20:56:38 +0000 (21:56 +0100)
Looks like something forgotten at some point, define in callback flags
was there, just not used at all.

Added most obvious cases now (we are probably still missing some), and
proper handling for it in remapping code (when we hit such case, we
'convert' new_id to NULL and go on with it).

Related (as in, exposed by) T62076, but not the actual cause of that bug.

source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/library_remap.c

index e30dd9c..cbc8588 100644 (file)
@@ -404,7 +404,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                        case ID_LI:
                        {
                                Library *lib = (Library *) id;
-                               CALLBACK_INVOKE(lib->parent, IDWALK_CB_NOP);
+                               CALLBACK_INVOKE(lib->parent, IDWALK_CB_NEVER_SELF);
                                break;
                        }
                        case ID_SCE:
@@ -414,7 +414,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
 
                                CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP);
                                CALLBACK_INVOKE(scene->world, IDWALK_CB_USER);
-                               CALLBACK_INVOKE(scene->set, IDWALK_CB_NOP);
+                               CALLBACK_INVOKE(scene->set, IDWALK_CB_NEVER_SELF);
                                CALLBACK_INVOKE(scene->clip, IDWALK_CB_USER);
                                CALLBACK_INVOKE(scene->r.bake.cage_object, IDWALK_CB_NOP);
                                if (scene->nodetree) {
@@ -425,7 +425,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                                        Sequence *seq;
                                        SEQP_BEGIN(scene->ed, seq)
                                        {
-                                               CALLBACK_INVOKE(seq->scene, IDWALK_CB_NOP);
+                                               CALLBACK_INVOKE(seq->scene, IDWALK_CB_NEVER_SELF);
                                                CALLBACK_INVOKE(seq->scene_camera, IDWALK_CB_NOP);
                                                CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER);
                                                CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER);
@@ -543,10 +543,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                                }
                                data.cb_flag = data_cb_flag;
 
-                               CALLBACK_INVOKE(object->parent, IDWALK_CB_NOP);
-                               CALLBACK_INVOKE(object->track, IDWALK_CB_NOP);
+                               CALLBACK_INVOKE(object->parent, IDWALK_CB_NEVER_SELF);
+                               CALLBACK_INVOKE(object->track, IDWALK_CB_NEVER_SELF);
                                /* object->proxy is refcounted, but not object->proxy_group... *sigh* */
-                               CALLBACK_INVOKE(object->proxy, IDWALK_CB_USER);
+                               CALLBACK_INVOKE(object->proxy, IDWALK_CB_NEVER_SELF);
                                CALLBACK_INVOKE(object->proxy_group, IDWALK_CB_NOP);
 
                                /* Special case!
@@ -555,7 +555,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                                if (object->proxy_from) {
                                        data.cb_flag = ID_IS_LINKED(object->proxy_from) ? IDWALK_CB_INDIRECT_USAGE : 0;
                                }
-                               CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_LOOPBACK);
+                               CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF);
                                data.cb_flag = data_cb_flag;
 
                                CALLBACK_INVOKE(object->poselib, IDWALK_CB_USER);
@@ -588,14 +588,14 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                                }
 
                                if (object->rigidbody_constraint) {
-                                       CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_CB_NOP);
-                                       CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_CB_NOP);
+                                       CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_CB_NEVER_SELF);
+                                       CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_CB_NEVER_SELF);
                                }
 
                                if (object->lodlevels.first) {
                                        LodLevel *level;
                                        for (level = object->lodlevels.first; level; level = level->next) {
-                                               CALLBACK_INVOKE(level->source, IDWALK_CB_NOP);
+                                               CALLBACK_INVOKE(level->source, IDWALK_CB_NEVER_SELF);
                                        }
                                }
 
@@ -631,7 +631,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                        case ID_ME:
                        {
                                Mesh *mesh = (Mesh *) id;
-                               CALLBACK_INVOKE(mesh->texcomesh, IDWALK_CB_USER);
+                               CALLBACK_INVOKE(mesh->texcomesh, IDWALK_CB_NEVER_SELF);
                                CALLBACK_INVOKE(mesh->key, IDWALK_CB_USER);
                                for (i = 0; i < mesh->totcol; i++) {
                                        CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER);
@@ -765,10 +765,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                                        CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
                                }
                                for (CollectionChild *child = collection->children.first; child; child = child->next) {
-                                       CALLBACK_INVOKE(child->collection, IDWALK_CB_USER);
+                                       CALLBACK_INVOKE(child->collection, IDWALK_CB_NEVER_SELF);
                                }
                                for (CollectionParent *parent = collection->parents.first; parent; parent = parent->next) {
-                                       CALLBACK_INVOKE(parent->collection, IDWALK_CB_NOP);
+                                       CALLBACK_INVOKE(parent->collection, IDWALK_CB_NEVER_SELF);
                                }
                                break;
                        }
index c4cd14e..0363029 100644 (file)
@@ -180,6 +180,11 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
        }
 
        if (*id_p && (*id_p == old_id)) {
+               /* Better remap to NULL than not remapping at all, then we can handle it as a regular remap-to-NULL case... */
+               if ((cb_flag & IDWALK_CB_NEVER_SELF) && (new_id == id_self)) {
+                       new_id = NULL;
+               }
+
                const bool is_reference = (cb_flag & IDWALK_CB_STATIC_OVERRIDE_REFERENCE) != 0;
                const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
                const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
@@ -189,7 +194,8 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
                const bool is_obj = (GS(id->name) == ID_OB);
                const bool is_obj_proxy = (is_obj && (((Object *)id)->proxy || ((Object *)id)->proxy_group));
                const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
-               const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
+               const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) &&
+                                           (new_id == NULL) &&
                                            (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
                const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_STATIC_OVERRIDE) != 0;
                const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;