From e0ff032711ec1a8cb85a2a9be9a6b0188d7f9db5 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 25 May 2020 15:11:36 +0200 Subject: Fix T76997: bad handling of embedded IDs in partial append. Code dealing with embedded data was pre-existing proper generic handling of those by `BKE_library_foreach_ID_link()` - and was never updated for scene's master collection it would seem... Note that such fix/refactor is a bit risky at this point in the release cycle, but on the other end previous situation was really broken. So finger crossed. :| --- source/blender/blenkernel/intern/lib_id.c | 37 ++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 9ef5c549235..9e8c8c36c63 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -128,8 +128,6 @@ static void lib_id_library_local_paths(Main *bmain, Library *lib, ID *id) */ static void lib_id_clear_library_data_ex(Main *bmain, ID *id) { - bNodeTree *ntree = NULL; - Key *key = NULL; const bool id_in_mainlist = (id->tag & LIB_TAG_NO_MAIN) == 0 && (id->flag & LIB_EMBEDDED_DATA) == 0; @@ -146,14 +144,11 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id) } } - /* Internal bNodeTree blocks inside data-blocks also stores id->lib, - * make sure this stays in sync. */ - if ((ntree = ntreeFromID(id))) { - lib_id_clear_library_data_ex(bmain, &ntree->id); - } - - /* Same goes for shapekeys. */ - if ((key = BKE_key_from_id(id))) { + /* Internal shape key blocks inside data-blocks also stores id->lib, + * make sure this stays in sync (note that we do not need any explicit handling for real EMBEDDED + * IDs here, this is down automatically in `lib_id_expand_local_cb()`. */ + Key *key = BKE_key_from_id(id); + if (key != NULL) { lib_id_clear_library_data_ex(bmain, &key->id); } } @@ -310,10 +305,23 @@ void BKE_id_clear_newpoin(ID *id) static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data) { + Main *bmain = cb_data->user_data; ID *id_self = cb_data->id_self; ID **id_pointer = cb_data->id_pointer; int const cb_flag = cb_data->cb_flag; + + if (cb_flag & IDWALK_CB_LOOPBACK) { + /* We should never have anything to do with loopback pointers here. */ + return IDWALK_RET_NOP; + } + if (cb_flag & IDWALK_CB_EMBEDDED) { + /* Embedded data-blocks need to be made fully local as well. */ + if (*id_pointer != NULL) { + BLI_assert(*id_pointer != id_self); + + lib_id_clear_library_data_ex(bmain, *id_pointer); + } return IDWALK_RET_NOP; } @@ -335,7 +343,7 @@ static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data) */ void BKE_lib_id_expand_local(Main *bmain, ID *id) { - BKE_library_foreach_ID_link(bmain, id, lib_id_expand_local_cb, NULL, IDWALK_READONLY); + BKE_library_foreach_ID_link(bmain, id, lib_id_expand_local_cb, bmain, IDWALK_READONLY); } /** @@ -393,6 +401,13 @@ void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags) if (ntree && ntree_new) { ID_NEW_SET(ntree, ntree_new); } + if (GS(id->name) == ID_SCE) { + Collection *master_collection = ((Scene *)id)->master_collection, + *master_collection_new = ((Scene *)id_new)->master_collection; + if (master_collection && master_collection_new) { + ID_NEW_SET(master_collection, master_collection_new); + } + } if (!lib_local) { BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE); -- cgit v1.2.3