Fix missing non-ID nodetrees in ID relationships built from library_query.c
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 30 Jan 2017 20:34:23 +0000 (21:34 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 30 Jan 2017 21:33:20 +0000 (22:33 +0100)
This shall fix both existing code (bpy mapping, and local/lib usages
checks), and new Main->relations generation.

source/blender/blenkernel/BKE_library_query.h
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/library_remap.c
source/blender/windowmanager/intern/wm_operators.c

index a7470107c24bde3b1c9ca6674ffcad5a996e2271..c80eb7b0760f09d68661d14ba2d4d24969435c21 100644 (file)
@@ -46,14 +46,17 @@ enum {
         */
        IDWALK_INDIRECT_USAGE = (1 << 2),
 
+       /** That ID is used as mere sub-data by its owner
+        * (only case currently: those f***ing nodetrees in materials etc.).
+        * This means callback shall not *do* anything, only use this as informative data if it needs it. */
+       IDWALK_PRIVATE = (1 << 3),
+
        /**
         * Adjusts #ID.us reference-count.
         * \note keep in sync with 'newlibadr_us' use in readfile.c
         */
        IDWALK_USER = (1 << 8),
-       /**
-        * Ensure #ID.us is at least 1 on use.
-        */
+       /** Ensure #ID.us is at least 1 on use. */
        IDWALK_USER_ONE = (1 << 9),
 };
 
index a06386f2f6a047d5e7c320af9bf197db0d090180..bb426ac0279fecae7c34309573bae8b6f0a9465d 100644 (file)
@@ -274,8 +274,12 @@ void BKE_id_clear_newpoin(ID *id)
 }
 
 static int id_expand_local_callback(
-        void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int UNUSED(cd_flag))
+        void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int cd_flag)
 {
+       if (cd_flag & IDWALK_PRIVATE) {
+               return IDWALK_RET_NOP;
+       }
+
        /* Can hapen that we get unlinkable ID here, e.g. with shapekey referring to itself (through drivers)...
         * Just skip it, shape key can only be either indirectly linked, or fully local, period.
         * And let's curse one more time that stupid useless shapekey ID type! */
index fa75c906fb19edf33cebdf08af6d31ad7ed50ca1..28f66b52793ce8b2e465508116c93bdfdf997b94 100644 (file)
@@ -85,6 +85,7 @@
 #define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0
 
 #define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, cb_flag) \
+       CHECK_TYPE(id_pp, ID **); \
        if (!((_data)->status & IDWALK_STOP)) { \
                const int _flag = (_data)->flag; \
                ID *old_id = *(id_pp); \
@@ -265,8 +266,13 @@ static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint)
 }
 
 static void library_foreach_ID_as_subdata_link(
-        ID *id, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
+        ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
 {
+       /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */
+       ID *id = *id_pp;
+       FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pp, IDWALK_PRIVATE);
+       BLI_assert(id == *id_pp);
+
        if (flag & IDWALK_RECURSE) {
                /* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in IDWALK_RECURSE case is
                 * troublesome, see T49553. */
@@ -278,6 +284,8 @@ static void library_foreach_ID_as_subdata_link(
        else {
                BKE_library_foreach_ID_link(id, callback, user_data, flag);
        }
+
+       FOREACH_FINALIZE_VOID;
 }
 
 /**
@@ -342,7 +350,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                CALLBACK_INVOKE(scene->clip, IDWALK_USER);
                                if (scene->nodetree) {
                                        /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
-                                       library_foreach_ID_as_subdata_link((ID *)scene->nodetree, callback, user_data, flag, &data);
+                                       library_foreach_ID_as_subdata_link((ID **)&scene->nodetree, callback, user_data, flag, &data);
                                }
                                /* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later,
                                 * since basact is just a pointer to one of those items. */
@@ -606,7 +614,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                }
                                if (material->nodetree) {
                                        /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
-                                       library_foreach_ID_as_subdata_link((ID *)material->nodetree, callback, user_data, flag, &data);
+                                       library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data);
                                }
                                CALLBACK_INVOKE(material->group, IDWALK_USER);
                                break;
@@ -617,7 +625,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                Tex *texture = (Tex *) id;
                                if (texture->nodetree) {
                                        /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
-                                       library_foreach_ID_as_subdata_link((ID *)texture->nodetree, callback, user_data, flag, &data);
+                                       library_foreach_ID_as_subdata_link((ID **)&texture->nodetree, callback, user_data, flag, &data);
                                }
                                CALLBACK_INVOKE(texture->ima, IDWALK_USER);
                                if (texture->env) {
@@ -650,7 +658,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                }
                                if (lamp->nodetree) {
                                        /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
-                                       library_foreach_ID_as_subdata_link((ID *)lamp->nodetree, callback, user_data, flag, &data);
+                                       library_foreach_ID_as_subdata_link((ID **)&lamp->nodetree, callback, user_data, flag, &data);
                                }
                                break;
                        }
@@ -690,7 +698,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                }
                                if (world->nodetree) {
                                        /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
-                                       library_foreach_ID_as_subdata_link((ID *)world->nodetree, callback, user_data, flag, &data);
+                                       library_foreach_ID_as_subdata_link((ID **)&world->nodetree, callback, user_data, flag, &data);
                                }
                                break;
                        }
@@ -834,7 +842,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                }
                                if (linestyle->nodetree) {
                                        /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
-                                       library_foreach_ID_as_subdata_link((ID *)linestyle->nodetree, callback, user_data, flag, &data);
+                                       library_foreach_ID_as_subdata_link((ID **)&linestyle->nodetree, callback, user_data, flag, &data);
                                }
 
                                for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) {
index d7d566a9ec0b9784cb6be2cd843459949edc3096..5fba7b75b1e72f9146271ff6dc1ffa5211502c31 100644 (file)
@@ -158,6 +158,10 @@ enum {
 
 static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id_p, int cb_flag)
 {
+       if (cb_flag & IDWALK_PRIVATE) {
+               return IDWALK_RET_NOP;
+       }
+
        IDRemap *id_remap_data = user_data;
        ID *old_id = id_remap_data->old_id;
        ID *new_id = id_remap_data->new_id;
@@ -687,6 +691,10 @@ void BKE_libblock_relink_ex(
 
 static int id_relink_to_newid_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cd_flag)
 {
+       if (cd_flag & IDWALK_PRIVATE) {
+               return IDWALK_RET_NOP;
+       }
+
        ID *id = *id_pointer;
        if (id) {
                /* See: NEW_ID macro */
index ef69ed31ef62fdfcac59097a82efaadff3068c8d..36721d31ae936253da71e8639cf8f54a3b7feca7 100644 (file)
@@ -3910,8 +3910,12 @@ static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
        }
 }
 
-static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int UNUSED(cd_flag))
+static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int cd_flag)
 {
+       if (cd_flag & IDWALK_PRIVATE) {
+               return IDWALK_RET_NOP;
+       }
+
        PreviewsIDEnsureData *data = userdata;
        ID *id = *idptr;