diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2019-08-12 12:54:37 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2019-08-12 12:54:37 +0300 |
commit | 761aeb48990fe3e8729de5c0826a873fb68b5497 (patch) | |
tree | d170e31d7ecf13bdeee21f3c212495379e59545b | |
parent | 35a9a85b27087f253100e7c66e8878a3ab015449 (diff) |
Fix crashes caused by library placeholders.
This fixes inconsistencies in materials between objects and obdata
due to placeholders generation for missing libdata.
Note that we cannot do that when generating the obdata placeholder,
as not all objects using it might be already loaded...
So this has to be done near the end of the reading/linking process.
Reported here by Blender Studio.
Reviewers: brecht
Subscribers: jbakker, zeddb
Tags: #datablocks_and_libraries
Differential Revision: https://developer.blender.org/D5428
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 737a70615ae..9a4fde8cc42 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8940,6 +8940,37 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle) /** \name Read Library Data Block * \{ */ +static ID *create_placeholder(Main *mainvar, const short idcode, const char *idname, const int tag) +{ + ListBase *lb = which_libbase(mainvar, idcode); + ID *ph_id = BKE_libblock_alloc_notest(idcode); + + *((short *)ph_id->name) = idcode; + BLI_strncpy(ph_id->name + 2, idname, sizeof(ph_id->name) - 2); + BKE_libblock_init_empty(ph_id); + ph_id->lib = mainvar->curlib; + ph_id->tag = tag | LIB_TAG_MISSING; + ph_id->us = ID_FAKE_USERS(ph_id); + ph_id->icon_id = 0; + + BLI_addtail(lb, ph_id); + id_sort_by_name(lb, ph_id); + + return ph_id; +} + +static void placeholders_ensure_valid(Main *bmain) +{ + /* Placeholder ObData IDs won't have any material, we have to update their objects for that, + * otherwise the inconsistency between both will lead to crashes (especially in Eevee?). */ + for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) { + ID *obdata = ob->data; + if (obdata != NULL && obdata->tag & LIB_TAG_MISSING) { + test_object_materials(bmain, ob, obdata); + } + } +} + static const char *dataname(short id_code) { switch (id_code) { @@ -9775,6 +9806,8 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) ntreeUpdateAllNew(bfd->main); } + placeholders_ensure_valid(bfd->main); + BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); /* Now that all our data-blocks are loaded, @@ -11259,25 +11292,6 @@ static void add_collections_to_scene(Main *mainvar, } } -static ID *create_placeholder(Main *mainvar, const short idcode, const char *idname, const int tag) -{ - ListBase *lb = which_libbase(mainvar, idcode); - ID *ph_id = BKE_libblock_alloc_notest(idcode); - - *((short *)ph_id->name) = idcode; - BLI_strncpy(ph_id->name + 2, idname, sizeof(ph_id->name) - 2); - BKE_libblock_init_empty(ph_id); - ph_id->lib = mainvar->curlib; - ph_id->tag = tag | LIB_TAG_MISSING; - ph_id->us = ID_FAKE_USERS(ph_id); - ph_id->icon_id = 0; - - BLI_addtail(lb, ph_id); - id_sort_by_name(lb, ph_id); - - return ph_id; -} - /* returns true if the item was found * but it may already have already been appended/linked */ static ID *link_named_part( @@ -11559,6 +11573,8 @@ static void library_link_end(Main *mainl, /* After all data has been read and versioned, uses LIB_TAG_NEW. */ ntreeUpdateAllNew(mainvar); + placeholders_ensure_valid(mainvar); + BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false); fix_relpaths_library(BKE_main_blendfile_path(mainvar), |