Fix embedded IDs not being enough/properly initialized.

Among other things, they were missing library pointer, session uuid
initialization, etc.

Fix T74546: Corrupted nodegroups crash blender when copy pasting or
appending them.

Fix (unreported) asserts when undoing some production scenes (from
coffee run e.g.).

Initialy caused by rB0aac74f18f2d.
This commit is contained in:
Bastien Montagne 2020-05-15 17:57:13 +02:00
parent 0541906162
commit 9632a06201
Notes: blender-bot 2023-02-14 00:13:36 +01:00
Referenced by issue #74546, Corrupted nodegroups crash blender when copy pasting or appending them
1 changed files with 38 additions and 25 deletions

View File

@ -2777,18 +2777,22 @@ static void direct_link_id_override_property_cb(FileData *fd, void *data)
link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb);
}
static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int tag);
static void direct_link_id_common(
FileData *fd, Library *current_library, ID *id, ID *id_old, const int tag);
static void direct_link_nodetree(FileData *fd, bNodeTree *ntree);
static void direct_link_collection(FileData *fd, Collection *collection);
static void direct_link_id_embedded_id(FileData *fd, ID *id, ID *id_old)
static void direct_link_id_embedded_id(FileData *fd, Library *current_library, ID *id, ID *id_old)
{
/* Handle 'private IDs'. */
bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
if (nodetree != NULL && *nodetree != NULL) {
*nodetree = newdataadr(fd, *nodetree);
direct_link_id_common(
fd, (ID *)*nodetree, id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL, 0);
direct_link_id_common(fd,
current_library,
(ID *)*nodetree,
id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL,
0);
direct_link_nodetree(fd, *nodetree);
}
@ -2797,6 +2801,7 @@ static void direct_link_id_embedded_id(FileData *fd, ID *id, ID *id_old)
if (scene->master_collection != NULL) {
scene->master_collection = newdataadr(fd, scene->master_collection);
direct_link_id_common(fd,
current_library,
&scene->master_collection->id,
id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL,
0);
@ -2861,18 +2866,40 @@ static int direct_link_id_restore_recalc(const FileData *fd,
return recalc;
}
static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int tag)
static void direct_link_id_common(
FileData *fd, Library *current_library, ID *id, ID *id_old, const int tag)
{
if (fd->memfile == NULL) {
/* When actually reading a file , we do want to reset/re-generate session uuids.
* In undo case, we want to re-use existing ones. */
id->session_uuid = MAIN_ID_SESSION_UUID_UNSET;
}
BKE_lib_libblock_session_uuid_ensure(id);
id->lib = current_library;
id->us = ID_FAKE_USERS(id);
id->icon_id = 0;
id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */
id->orig_id = NULL;
id->py_instance = NULL;
/* Initialize with provided tag. */
id->tag = tag;
if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
/* For placeholder we only need to set the tag and properly init generic ID fieds above, no
* further data to read. */
return;
}
/*link direct data of ID properties*/
if (id->properties) {
id->properties = newdataadr(fd, id->properties);
/* this case means the data was written incorrectly, it should not happen */
IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
id->py_instance = NULL;
/* Initialize with provided tag. */
id->tag = tag;
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
/* NOTE: It is important to not clear the recalc flags for undo/redo.
@ -2905,7 +2932,7 @@ static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int ta
}
/* Handle 'private IDs'. */
direct_link_id_embedded_id(fd, id, id_old);
direct_link_id_embedded_id(fd, current_library, id, id_old);
}
/** \} */
@ -9270,19 +9297,8 @@ static const char *dataname(short id_code)
static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *id_old)
{
if (fd->memfile == NULL) {
/* When actually reading a file , we do want to reset/re-generate session uuids.
* In undo case, we want to re-use existing ones. */
id->session_uuid = MAIN_ID_SESSION_UUID_UNSET;
}
BKE_lib_libblock_session_uuid_ensure(id);
id->lib = main->curlib;
id->us = ID_FAKE_USERS(id);
id->icon_id = 0;
id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */
id->orig_id = NULL;
/* Read part of datablock that is common between real and embedded datablocks. */
direct_link_id_common(fd, main->curlib, id, id_old, tag);
if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
/* For placeholder we only need to set the tag, no further data to read. */
@ -9290,9 +9306,6 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *
return true;
}
/* Read part of datablock that is common between real and embedded datablocks. */
direct_link_id_common(fd, id, id_old, tag);
/* XXX Very weakly handled currently, see comment in read_libblock() before trying to
* use it for anything new. */
bool success = true;