From fbd28d375a758d81b925867efef4d02482d414c6 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 30 Jan 2017 21:34:23 +0100 Subject: Fix missing non-ID nodetrees in ID relationships built from library_query.c 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 | 9 ++++++--- source/blender/blenkernel/intern/library.c | 6 +++++- source/blender/blenkernel/intern/library_query.c | 22 +++++++++++++++------- source/blender/blenkernel/intern/library_remap.c | 8 ++++++++ source/blender/windowmanager/intern/wm_operators.c | 6 +++++- 5 files changed, 39 insertions(+), 12 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h index a7470107c24..c80eb7b0760 100644 --- a/source/blender/blenkernel/BKE_library_query.h +++ b/source/blender/blenkernel/BKE_library_query.h @@ -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), }; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index a06386f2f6a..bb426ac0279 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -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! */ diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index fa75c906fb1..28f66b52793 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -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) { diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index d7d566a9ec0..5fba7b75b1e 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -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 */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index ef69ed31ef6..36721d31ae9 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -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; -- cgit v1.2.3