From c2f7d4efc3f0fa421dd0ced473ed3024c9e0f907 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 4 Mar 2019 16:14:36 +0100 Subject: Fix T62134: duplicating a material won't update node group's node tree user count anymore. Yet again we have to twist and curl like insane worms to cope with IDs-not-in-main infamous issue... :( --- source/blender/blenkernel/intern/library_query.c | 43 ++++++++++++++++++------ 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'source/blender/blenkernel/intern/library_query.c') diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index cbc8588c45c..d4ded5458c1 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -144,6 +144,11 @@ typedef struct LibraryForeachIDData { BLI_LINKSTACK_DECLARE(ids_todo, ID *); } LibraryForeachIDData; +static void library_foreach_ID_link( + Main *bmain, ID *id, + LibraryIDLinkCallback callback, void *user_data, int flag, + LibraryForeachIDData *inherit_data); + static void library_foreach_idproperty_ID_link(LibraryForeachIDData *data, IDProperty *prop, int flag) { if (!prop) @@ -331,18 +336,16 @@ static void library_foreach_ID_as_subdata_link( } } else { - BKE_library_foreach_ID_link(NULL, id, callback, user_data, flag); + library_foreach_ID_link(NULL, id, callback, user_data, flag, data); } FOREACH_FINALIZE_VOID; } -/** - * Loop over all of the ID's this datablock links to. - * - * \note: May be extended to be recursive in the future. - */ -void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag) +static void library_foreach_ID_link( + Main *bmain, ID *id, + LibraryIDLinkCallback callback, void *user_data, int flag, + LibraryForeachIDData *inherit_data) { LibraryForeachIDData data; int i; @@ -372,9 +375,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) { data.self_id = id; - data.cb_flag = ID_IS_LINKED(id) ? IDWALK_CB_INDIRECT_USAGE : 0; - /* When an ID is not in Main database, it should never refcount IDs it is using. */ - data.cb_flag_clear = (id->tag & LIB_TAG_NO_MAIN) ? IDWALK_CB_USER | IDWALK_CB_USER_ONE : 0; + + /* inherit_data is non-NULL when this function is called for some sub-data ID + * (like root nodetree of a material). + * In that case, we do not want to generate those 'generic flags' from our current sub-data ID (the node tree), + * but re-use those generated for the 'owner' ID (the material)... */ + if (inherit_data == NULL) { + data.cb_flag = ID_IS_LINKED(id) ? IDWALK_CB_INDIRECT_USAGE : 0; + /* When an ID is not in Main database, it should never refcount IDs it is using. + * Exceptions: NodeTrees (yeeahhh!) directly used by Materials. */ + data.cb_flag_clear = (id->tag & LIB_TAG_NO_MAIN) ? IDWALK_CB_USER | IDWALK_CB_USER_ONE : 0; + } + else { + data.cb_flag = inherit_data->cb_flag; + data.cb_flag_clear = inherit_data->cb_flag_clear; + } if (bmain != NULL && bmain->relations != NULL && (flag & IDWALK_READONLY)) { /* Note that this is minor optimization, even in worst cases (like id being an object with lots of @@ -1037,6 +1052,14 @@ FOREACH_FINALIZE: #undef FOREACH_CALLBACK_INVOKE_ID #undef FOREACH_CALLBACK_INVOKE +/** + * Loop over all of the ID's this datablock links to. + */ +void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag) +{ + library_foreach_ID_link(bmain, id, callback, user_data, flag, NULL); +} + /** * re-usable function, use when replacing ID's */ -- cgit v1.2.3