diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index a393d4f4f98..d2a489d60fa 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -308,6 +308,15 @@ void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL(); * Properly delete a single ID from given \a bmain database. */ void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL(); +/** + * Like BKE_id_delete, but with extra corner-case options. + * + * \param extra_remapping_flags Additional `ID_REMAP_` flags to pass to remapping code when + * ensuring that deleted IDs are not used by any other ID in given `bmain`. Typical example would + * be e.g. `ID_REMAP_FORCE_UI_POINTERS`, required when default UI-handling callbacks of remapping + * code won't be working (e.g. from readfile code). */ +void BKE_id_delete_ex(struct Main *bmain, void *idv, const int extra_remapping_flags) + ATTR_NONNULL(1, 2); /** * Properly delete all IDs tagged with \a LIB_TAG_DOIT, in given \a bmain database. * diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index c4200938cb9..19bd8f57f49 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -199,7 +199,9 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */ } } -static size_t id_delete(Main *bmain, const bool do_tagged_deletion) +static size_t id_delete(Main *bmain, + const bool do_tagged_deletion, + const int extra_remapping_flags) { const int tag = LIB_TAG_DOIT; ListBase *lbarray[INDEX_ID_MAX]; @@ -211,6 +213,8 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) const int free_flag = LIB_ID_FREE_NO_UI_USER | (do_tagged_deletion ? LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_USER_REFCOUNT : 0); + const int remapping_flags = (ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE | + ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | extra_remapping_flags); ListBase tagged_deleted_ids = {NULL}; base_count = set_listbasepointers(bmain, lbarray); @@ -261,11 +265,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) * links, this can lead to nasty crashing here in second, actual deleting loop. * Also, this will also flag users of deleted data that cannot be unlinked * (object using deleted obdata, etc.), so that they also get deleted. */ - BKE_libblock_remap_multiple_locked(bmain, - id_remapper, - ID_REMAP_FLAG_NEVER_NULL_USAGE | - ID_REMAP_FORCE_NEVER_NULL_USAGE | - ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS); + BKE_libblock_remap_multiple_locked(bmain, id_remapper, remapping_flags); BKE_id_remapper_clear(id_remapper); } @@ -329,11 +329,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) * links, this can lead to nasty crashing here in second, actual deleting loop. * Also, this will also flag users of deleted data that cannot be unlinked * (object using deleted obdata, etc.), so that they also get deleted. */ - BKE_libblock_remap_multiple_locked(bmain, - remapper, - (ID_REMAP_FLAG_NEVER_NULL_USAGE | - ID_REMAP_FORCE_NEVER_NULL_USAGE | - ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS)); + BKE_libblock_remap_multiple_locked(bmain, remapper, remapping_flags); } BKE_id_remapper_free(remapper); } @@ -371,7 +367,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) return num_datablocks_deleted; } -void BKE_id_delete(Main *bmain, void *idv) +void BKE_id_delete_ex(Main *bmain, void *idv, const int extra_remapping_flags) { BLI_assert_msg((((ID *)idv)->tag & LIB_TAG_NO_MAIN) == 0, "Cannot be used with IDs outside of Main"); @@ -379,12 +375,17 @@ void BKE_id_delete(Main *bmain, void *idv) BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); ((ID *)idv)->tag |= LIB_TAG_DOIT; - id_delete(bmain, false); + id_delete(bmain, false, extra_remapping_flags); +} + +void BKE_id_delete(Main *bmain, void *idv) +{ + BKE_id_delete_ex(bmain, idv, 0); } size_t BKE_id_multi_tagged_delete(Main *bmain) { - return id_delete(bmain, true); + return id_delete(bmain, true, 0); } /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenloader/intern/blend_validate.cc b/source/blender/blenloader/intern/blend_validate.cc index b8ab1dd2c4c..f04fdee2288 100644 --- a/source/blender/blenloader/intern/blend_validate.cc +++ b/source/blender/blenloader/intern/blend_validate.cc @@ -24,6 +24,7 @@ #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_remap.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_report.h" @@ -196,7 +197,10 @@ bool BLO_main_validate_shapekeys(Main *bmain, ReportList *reports) "Shapekey %s has an invalid 'from' pointer (%p), it will be deleted", shapekey->id.name, shapekey->from); - BKE_id_delete(bmain, shapekey); + /* NOTE: also need to remap UI data ID pointers here, since `bmain` is not the current + * `G_MAIN`, default UI-handling remapping callback (defined by call to + * `BKE_library_callback_remap_editor_id_reference_set`) won't work on exoected data here. */ + BKE_id_delete_ex(bmain, shapekey, ID_REMAP_FORCE_UI_POINTERS); } return is_valid;