diff options
Diffstat (limited to 'source/blender/blenkernel/intern/library_remap.c')
-rw-r--r-- | source/blender/blenkernel/intern/library_remap.c | 177 |
1 files changed, 142 insertions, 35 deletions
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 24626c6ead7..f8c193fe108 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -186,8 +186,8 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0; #ifdef DEBUG_PRINT - printf("In %s: Remapping %s (%p) to %s (%p) (skip_indirect: %d)\n", - id->name, old_id->name, old_id, new_id ? new_id->name : "<NONE>", new_id, skip_indirect); + printf("In %s: Remapping %s (%p) to %s (%p) (is_indirect: %d, skip_indirect: %d)\n", + id->name, old_id->name, old_id, new_id ? new_id->name : "<NONE>", new_id, is_indirect, skip_indirect); #endif if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) { @@ -201,6 +201,14 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id { if (is_indirect) { id_remap_data->skipped_indirect++; + if (is_obj) { + Object *ob = (Object *)id; + if (ob->data == *id_p && ob->proxy != NULL) { + /* And another 'Proudly brought to you by Proxy Hell' hack! + * This will allow us to avoid clearing 'LIB_EXTERN' flag of obdata of proxies... */ + id_remap_data->skipped_direct++; + } + } } else if (is_never_null || is_obj_editmode) { id_remap_data->skipped_direct++; @@ -241,7 +249,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id return IDWALK_RET_NOP; } -/* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */ +/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */ static void libblock_remap_data_preprocess_scene_base_unlink( IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect) { @@ -318,7 +326,7 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data) } } -static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain, Object *old_ob, Object *new_ob) +static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *old_ob, Object *new_ob) { if (old_ob->flag & OB_FROMGROUP) { /* Note that for Scene's BaseObject->flag, either we: @@ -337,6 +345,13 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain, new_ob->flag |= OB_FROMGROUP; } } + if (old_ob->type == OB_MBALL) { + for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) { + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + } + } } static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmain), Scene *sce, ID *old_id) @@ -419,6 +434,7 @@ ATTR_NONNULL(1) static void libblock_remap_data( IDRemap id_remap_data; ListBase *lb_array[MAX_LIBARRAY]; int i; + const int foreach_id_flags = (remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ? IDWALK_NO_INDIRECT_PROXY_DATA_USAGE : IDWALK_NOP; if (r_id_remap_data == NULL) { r_id_remap_data = &id_remap_data; @@ -439,7 +455,7 @@ ATTR_NONNULL(1) static void libblock_remap_data( #endif r_id_remap_data->id = id; libblock_remap_data_preprocess(r_id_remap_data); - BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); + BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags); } else { i = set_listbasepointers(bmain, lb_array); @@ -456,7 +472,7 @@ ATTR_NONNULL(1) static void libblock_remap_data( r_id_remap_data->id = id_curr; libblock_remap_data_preprocess(r_id_remap_data); BKE_library_foreach_ID_link( - NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); + NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags); } } } @@ -546,7 +562,7 @@ void BKE_libblock_remap_locked( */ switch (GS(old_id->name)) { case ID_OB: - libblock_remap_data_postprocess_object_fromgroup_update(bmain, (Object *)old_id, (Object *)new_id); + libblock_remap_data_postprocess_object_update(bmain, (Object *)old_id, (Object *)new_id); break; case ID_GR: if (!new_id) { /* Only affects us in case group was unlinked. */ @@ -656,8 +672,7 @@ void BKE_libblock_relink_ex( switch (GS(old_id->name)) { case ID_OB: { - libblock_remap_data_postprocess_object_fromgroup_update( - bmain, (Object *)old_id, (Object *)new_id); + libblock_remap_data_postprocess_object_update(bmain, (Object *)old_id, (Object *)new_id); break; } case ID_GR: @@ -672,7 +687,7 @@ void BKE_libblock_relink_ex( else { /* No choice but to check whole objects/groups. */ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { - libblock_remap_data_postprocess_object_fromgroup_update(bmain, ob, NULL); + libblock_remap_data_postprocess_object_update(bmain, ob, NULL); } for (Group *grp = bmain->group.first; grp; grp = grp->id.next) { libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, NULL); @@ -723,38 +738,19 @@ void BKE_libblock_relink_to_newid(ID *id) BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0); } -void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id, const bool do_id_user) +void BKE_libblock_free_data(ID *id, const bool do_id_user) { if (id->properties) { IDP_FreeProperty_ex(id->properties, do_id_user); MEM_freeN(id->properties); } + + /* XXX TODO remove animdata handling from each type's freeing func, and do it here, like for copy! */ } -/** - * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c - * - * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv. - * (only applies to main database) - * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to - * \a id. - */ -void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) +void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag)) { - ID *id = idv; - short type = GS(id->name); - ListBase *lb = which_libbase(bmain, type); - - DAG_id_type_tag(bmain, type); - -#ifdef WITH_PYTHON - BPY_id_release(id); -#endif - - if (do_id_user) { - BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); - } - + const short type = GS(id->name); switch (type) { case ID_SCE: BKE_scene_free((Scene *)id); @@ -860,6 +856,117 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b BKE_cachefile_free((CacheFile *)id); break; } +} + + +void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag) +{ + ID *id = idv; + + if (use_flag_from_idtag) { + if ((id->tag & LIB_TAG_NO_MAIN) != 0) { + flag |= LIB_ID_FREE_NO_MAIN; + } + else { + flag &= ~LIB_ID_FREE_NO_MAIN; + } + + if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) { + flag |= LIB_ID_FREE_NO_USER_REFCOUNT; + } + else { + flag &= ~LIB_ID_FREE_NO_USER_REFCOUNT; + } + + if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) { + flag |= LIB_ID_FREE_NOT_ALLOCATED; + } + else { + flag &= ~LIB_ID_FREE_NOT_ALLOCATED; + } + } + + BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL); + BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0); + BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0); + + const short type = GS(id->name); + + if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) { + DAG_id_type_tag(bmain, type); + } + +#ifdef WITH_PYTHON + BPY_id_release(id); +#endif + + if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) { + BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); + } + + BKE_libblock_free_datablock(id, flag); + + /* avoid notifying on removed data */ + if (bmain) { + BKE_main_lock(bmain); + } + + if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) { + if (free_notifier_reference_cb) { + free_notifier_reference_cb(id); + } + + if (remap_editor_id_reference_cb) { + remap_editor_id_reference_cb(id, NULL); + } + } + + if ((flag & LIB_ID_FREE_NO_MAIN) == 0) { + ListBase *lb = which_libbase(bmain, type); + BLI_remlink(lb, id); + } + + BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0); + + if (bmain) { + BKE_main_unlock(bmain); + } + + if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) { + MEM_freeN(id); + } +} + +void BKE_id_free(Main *bmain, void *idv) +{ + BKE_id_free_ex(bmain, idv, 0, true); +} + +/** + * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c + * + * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv. + * (only applies to main database) + * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to + * \a id. + */ +void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) +{ + ID *id = idv; + short type = GS(id->name); + ListBase *lb = which_libbase(bmain, type); + + DAG_id_type_tag(bmain, type); + +#ifdef WITH_PYTHON + BPY_id_release(id); +#endif + + if (do_id_user) { + BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); + } + + BKE_libblock_free_datablock(id, 0); /* avoid notifying on removed data */ BKE_main_lock(bmain); @@ -876,7 +983,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b BLI_remlink(lb, id); - BKE_libblock_free_data(bmain, id, do_id_user); + BKE_libblock_free_data(id, do_id_user); BKE_main_unlock(bmain); MEM_freeN(id); |