Fix T92629: Crash on mesh separate after rB43bc494892c3.
rB43bc494892c3 switched `BKE_libblock_relink_to_newid` to use new ID remapping and libquery code. However, that new code does protect by default against remapping an objects's data pointer when that object is in Edit mode, since this is not a behavior that generic BKE code can handle (due to required editing data for most obdata types when in edit mode). So specific code that does create new IDs and need remapping in Edit mode has to pass specific exception flags to remaping code. This commit adds those remapping flags to `BKE_libblock_relink_to_newid` and add said exception flag to the remapping call from `ED_object_add_duplicate` when the object is in edit mode.
This commit is contained in:
parent
e85e126e3f
commit
8fbbd69946
Notes:
blender-bot
2023-02-14 01:11:05 +01:00
Referenced by issue #92629, Crash on mesh separate
|
@ -117,7 +117,8 @@ void BKE_libblock_relink_ex(struct Main *bmain,
|
|||
void *new_idv,
|
||||
const short remap_flags) ATTR_NONNULL(1, 2);
|
||||
|
||||
void BKE_libblock_relink_to_newid(struct Main *bmain, struct ID *id) ATTR_NONNULL();
|
||||
void BKE_libblock_relink_to_newid(struct Main *bmain, struct ID *id, const int remap_flag)
|
||||
ATTR_NONNULL();
|
||||
|
||||
typedef void (*BKE_library_free_notifier_reference_cb)(const void *);
|
||||
typedef void (*BKE_library_remap_editor_id_reference_cb)(struct ID *, struct ID *);
|
||||
|
|
|
@ -716,7 +716,7 @@ Collection *BKE_collection_duplicate(Main *bmain,
|
|||
collection_new->id.tag &= ~LIB_TAG_NEW;
|
||||
|
||||
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
|
||||
BKE_libblock_relink_to_newid(bmain, &collection_new->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &collection_new->id, 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
|
||||
|
|
|
@ -670,7 +670,7 @@ void BKE_libblock_relink_ex(
|
|||
DEG_relations_tag_update(bmain);
|
||||
}
|
||||
|
||||
static void libblock_relink_to_newid(Main *bmain, ID *id);
|
||||
static void libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag);
|
||||
static int id_relink_to_newid_looper(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
|
@ -683,31 +683,31 @@ static int id_relink_to_newid_looper(LibraryIDLinkCallbackData *cb_data)
|
|||
ID **id_pointer = cb_data->id_pointer;
|
||||
ID *id = *id_pointer;
|
||||
if (id) {
|
||||
const int remap_flag = POINTER_AS_INT(cb_data->user_data);
|
||||
/* See: NEW_ID macro */
|
||||
if (id->newid != NULL) {
|
||||
BKE_libblock_relink_ex(bmain,
|
||||
id_owner,
|
||||
id,
|
||||
id->newid,
|
||||
ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY);
|
||||
const int remap_flag_final = remap_flag | ID_REMAP_SKIP_INDIRECT_USAGE |
|
||||
ID_REMAP_SKIP_OVERRIDE_LIBRARY;
|
||||
BKE_libblock_relink_ex(bmain, id_owner, id, id->newid, (short)remap_flag_final);
|
||||
id = id->newid;
|
||||
}
|
||||
if (id->tag & LIB_TAG_NEW) {
|
||||
id->tag &= ~LIB_TAG_NEW;
|
||||
libblock_relink_to_newid(bmain, id);
|
||||
libblock_relink_to_newid(bmain, id, remap_flag);
|
||||
}
|
||||
}
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
static void libblock_relink_to_newid(Main *bmain, ID *id)
|
||||
static void libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag)
|
||||
{
|
||||
if (ID_IS_LINKED(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
id->tag &= ~LIB_TAG_NEW;
|
||||
BKE_library_foreach_ID_link(bmain, id, id_relink_to_newid_looper, NULL, 0);
|
||||
BKE_library_foreach_ID_link(
|
||||
bmain, id, id_relink_to_newid_looper, POINTER_FROM_INT(remap_flag), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -719,7 +719,7 @@ static void libblock_relink_to_newid(Main *bmain, ID *id)
|
|||
* Very specific usage, not sure we'll keep it on the long run,
|
||||
* currently only used in Object/Collection duplication code...
|
||||
*/
|
||||
void BKE_libblock_relink_to_newid(Main *bmain, ID *id)
|
||||
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag)
|
||||
{
|
||||
if (ID_IS_LINKED(id)) {
|
||||
return;
|
||||
|
@ -728,7 +728,7 @@ void BKE_libblock_relink_to_newid(Main *bmain, ID *id)
|
|||
BLI_assert(bmain->relations == NULL);
|
||||
|
||||
BKE_layer_collection_resync_forbid();
|
||||
libblock_relink_to_newid(bmain, id);
|
||||
libblock_relink_to_newid(bmain, id, remap_flag);
|
||||
BKE_layer_collection_resync_allow();
|
||||
BKE_main_collection_sync_remap(bmain);
|
||||
}
|
||||
|
|
|
@ -2878,7 +2878,7 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
|
||||
if (!is_subprocess) {
|
||||
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
|
||||
BKE_libblock_relink_to_newid(bmain, &obn->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &obn->id, 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
|
||||
|
|
|
@ -1925,7 +1925,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
|
|||
|
||||
if (!is_subprocess) {
|
||||
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
|
||||
BKE_libblock_relink_to_newid(bmain, &sce_copy->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &sce_copy->id, 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those
|
||||
|
|
|
@ -2145,7 +2145,7 @@ static void copy_object_set_idnew(bContext *C)
|
|||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
|
||||
BKE_libblock_relink_to_newid(bmain, &ob->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &ob->id, 0);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
|
@ -2378,7 +2378,7 @@ static void make_object_duplilist_real(bContext *C,
|
|||
Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
|
||||
|
||||
/* Remap new object to itself, and clear again newid pointer of orig object. */
|
||||
BKE_libblock_relink_to_newid(bmain, &ob_dst->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &ob_dst->id, 0);
|
||||
|
||||
DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
|
||||
|
||||
|
@ -3374,8 +3374,11 @@ Base *ED_object_add_duplicate(
|
|||
|
||||
ob = basen->object;
|
||||
|
||||
/* link own references to the newly duplicated data T26816. */
|
||||
BKE_libblock_relink_to_newid(bmain, &ob->id);
|
||||
/* Link own references to the newly duplicated data T26816.
|
||||
* Note that this function can be called from edit-mode code, in which case we may have to
|
||||
* enforce remapping obdata (by default this is forbidden in edit mode). */
|
||||
const int remap_flag = BKE_object_is_in_editmode(ob) ? ID_REMAP_FORCE_OBDATA_IN_EDITMODE : 0;
|
||||
BKE_libblock_relink_to_newid(bmain, &ob->id, remap_flag);
|
||||
|
||||
/* DAG_relations_tag_update(bmain); */ /* caller must do */
|
||||
|
||||
|
|
|
@ -1690,11 +1690,11 @@ static void libblock_relink_collection(Main *bmain,
|
|||
const bool do_collection)
|
||||
{
|
||||
if (do_collection) {
|
||||
BKE_libblock_relink_to_newid(bmain, &collection->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &collection->id, 0);
|
||||
}
|
||||
|
||||
for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) {
|
||||
BKE_libblock_relink_to_newid(bmain, &cob->ob->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &cob->ob->id, 0);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
|
||||
|
@ -1768,7 +1768,7 @@ static void single_object_users(
|
|||
single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
|
||||
|
||||
/* Will also handle the master collection. */
|
||||
BKE_libblock_relink_to_newid(bmain, &scene->id);
|
||||
BKE_libblock_relink_to_newid(bmain, &scene->id, 0);
|
||||
|
||||
/* Collection and object pointers in collections */
|
||||
libblock_relink_collection(bmain, scene->master_collection, false);
|
||||
|
|
|
@ -812,7 +812,7 @@ static void wm_append_do(WMLinkAppendData *lapp_data,
|
|||
|
||||
BLI_assert(!ID_IS_LINKED(id));
|
||||
|
||||
BKE_libblock_relink_to_newid(bmain, id);
|
||||
BKE_libblock_relink_to_newid(bmain, id, 0);
|
||||
}
|
||||
|
||||
/* Remove linked IDs when a local existing data has been reused instead. */
|
||||
|
|
Loading…
Reference in New Issue