diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2016-12-19 18:28:41 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2016-12-19 18:31:06 +0300 |
commit | bd42987399f1e2decf259cce21a91e39c7a0a50d (patch) | |
tree | df1d08fd0f61b68ae8b3eafc7ff677185f9ec947 /source | |
parent | e30d94bb3bdb333a514f0771e63ff2543c0a1969 (diff) |
Fix (unreported) linked datablocks going through do_versions several times.
When linking data-blocks from same library in several steps, the already
linked data-blocks of same lib would go again through versionning code...
Note: only fixed for libraries, I can't imagine how this could happen
with local data...
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 50 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_ID.h | 3 |
2 files changed, 47 insertions, 6 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 03c5d083456..a154d283f07 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8112,7 +8112,10 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short if (bhead->code == ID_ID) { return blo_nextbhead(fd, bhead); } - + + /* That way, we know which datablock needs do_versions (required currently for linking). */ + id->tag |= LIB_TAG_NEW; + /* need a name for the mallocN, just for debugging and sane prints on leaks */ allocname = dataname(GS(id->name)); @@ -8578,7 +8581,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) blo_join_main(&mainlist); lib_link_all(fd, bfd->main); + //do_versions_after_linking(fd, NULL, bfd->main); // XXX: not here (or even in this function at all)! this causes crashes on many files - Aligorith (July 04, 2010) + BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); + lib_verify_nodetree(bfd->main, true); fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ @@ -10142,6 +10148,9 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene mainl = NULL; /* blo_join_main free's mainl, cant use anymore */ lib_link_all(*fd, mainvar); + + BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false); + lib_verify_nodetree(mainvar, false); fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */ @@ -10212,6 +10221,32 @@ static int mainvar_id_tag_any_check(Main *mainvar, const short tag) return false; } +static void split_main_newid(Main *mainptr, Main *main_newid) +{ + /* We only copy the necessary subset of data in this temp main. */ + main_newid->versionfile = mainptr->versionfile; + main_newid->subversionfile = mainptr->subversionfile; + BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name)); + main_newid->curlib = mainptr->curlib; + + ListBase *lbarray[MAX_LIBARRAY]; + ListBase *lbarray_newid[MAX_LIBARRAY]; + int i = set_listbasepointers(mainptr, lbarray); + set_listbasepointers(main_newid, lbarray_newid); + while (i--) { + BLI_listbase_clear(lbarray_newid[i]); + + for (ID *id = lbarray[i]->first, *idnext; id; id = idnext) { + idnext = id->next; + + if (id->tag & LIB_TAG_NEW) { + BLI_remlink(lbarray[i], id); + BLI_addtail(lbarray_newid[i], id); + } + } + } +} + static void read_libraries(FileData *basefd, ListBase *mainlist) { Main *mainl = mainlist->first; @@ -10381,14 +10416,19 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) } /* do versions, link, and free */ + Main main_newid = {0}; for (mainptr = mainl->next; mainptr; mainptr = mainptr->next) { - /* some mains still have to be read, then - * versionfile is still zero! */ + /* some mains still have to be read, then versionfile is still zero! */ if (mainptr->versionfile) { + /* We need to split out IDs already existing, or they will go again through do_versions - bad, very bad! */ + split_main_newid(mainptr, &main_newid); + if (mainptr->curlib->filedata) // can be zero... with shift+f1 append - do_versions(mainptr->curlib->filedata, mainptr->curlib, mainptr); + do_versions(mainptr->curlib->filedata, mainptr->curlib, &main_newid); else - do_versions(basefd, NULL, mainptr); + do_versions(basefd, NULL, &main_newid); + + add_main_to_main(mainptr, &main_newid); } if (mainptr->curlib->filedata) diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 59fd0c7832c..9a8f3da3396 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -336,7 +336,8 @@ enum { /* tag datablock has having actually increased usercount for the extra virtual user. */ LIB_TAG_EXTRAUSER_SET = 1 << 7, - /* RESET_AFTER_USE tag newly duplicated/copied IDs. */ + /* RESET_AFTER_USE tag newly duplicated/copied IDs. + * Also used internally in readfile.c to mark datablocks needing do_versions. */ LIB_TAG_NEW = 1 << 8, /* RESET_BEFORE_USE free test flag. * TODO make it a RESET_AFTER_USE too. */ |