doxygen: add newline after \file
[blender.git] / source / blender / blenloader / intern / readfile.c
index 2723210..8fcae12 100644 (file)
@@ -17,8 +17,8 @@
  * All rights reserved.
  */
 
-/** \file blender/blenloader/intern/readfile.c
- *  \ingroup blenloader
+/** \file
+ * \ingroup blenloader
  */
 
 
@@ -933,13 +933,30 @@ static void decode_blender_header(FileData *fd)
 static bool read_file_dna(FileData *fd, const char **r_error_message)
 {
        BHead *bhead;
+       int subversion = 0;
 
        for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
-               if (bhead->code == DNA1) {
+               if (bhead->code == GLOB) {
+                       /* Before this, the subversion didn't exist in 'FileGlobal' so the subversion
+                        * value isn't accessible for the purpose of DNA versioning in this case. */
+                       if (fd->fileversion <= 242) {
+                               continue;
+                       }
+                       /* We can't use read_global because this needs 'DNA1' to be decoded,
+                        * however the first 4 chars are _always_ the subversion. */
+                       FileGlobal *fg = (void *)&bhead[1];
+                       BLI_STATIC_ASSERT(offsetof(FileGlobal, subvstr) == 0, "Must be first: subvstr");
+                       char num[5];
+                       memcpy(num, fg->subvstr, 4);
+                       num[4] = 0;
+                       subversion = atoi(num);
+               }
+               else if (bhead->code == DNA1) {
                        const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
 
                        fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true, r_error_message);
                        if (fd->filesdna) {
+                               blo_do_versions_dna(fd->filesdna, fd->fileversion, subversion);
                                fd->compflags = DNA_struct_get_compareflags(fd->filesdna, fd->memsdna);
                                /* used to retrieve ID names from (bhead+1) */
                                fd->id_name_offs = DNA_elem_offset(fd->filesdna, "ID", "char", "name[]");
@@ -978,10 +995,9 @@ static int *read_file_thumbnail(FileData *fd)
                                BLI_endian_switch_int32(&data[1]);
                        }
 
-                       int width = data[0];
-                       int height = data[1];
-
-                       if (!BLEN_THUMB_SAFE_MEMSIZE(width, height)) {
+                       const int width = data[0];
+                       const int height = data[1];
+                       if (!BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
                                break;
                        }
                        if (bhead->len < BLEN_THUMB_MEMSIZE_FILE(width, height)) {
@@ -1423,14 +1439,11 @@ BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
        fd_data = fd ? read_file_thumbnail(fd) : NULL;
 
        if (fd_data) {
-               int width = fd_data[0];
-               int height = fd_data[1];
-
-               /* Protect against buffer overflow vulnerability. */
-               if (BLEN_THUMB_SAFE_MEMSIZE(width, height)) {
+               const int width = fd_data[0];
+               const int height = fd_data[1];
+               if (BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
                        const size_t sz = BLEN_THUMB_MEMSIZE(width, height);
                        data = MEM_mallocN(sz, __func__);
-
                        if (data) {
                                BLI_assert((sz - sizeof(*data)) == (BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*fd_data) * 2)));
                                data->width = width;
@@ -4264,8 +4277,8 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
 
                        part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system
 
-                       part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
-                       part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
+                       part->instance_object = newlibadr(fd, part->id.lib, part->instance_object);
+                       part->instance_collection = newlibadr_us(fd, part->id.lib, part->instance_collection);
                        part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
                        part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
                        part->collision_group = newlibadr(fd, part->id.lib, part->collision_group);
@@ -4280,13 +4293,13 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
                                part->effector_weights = BKE_effector_add_weights(part->eff_group);
                        }
 
-                       if (part->dupliweights.first && part->dup_group) {
-                               for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
+                       if (part->instance_weights.first && part->instance_collection) {
+                               for (ParticleDupliWeight *dw = part->instance_weights.first; dw; dw = dw->next) {
                                        dw->ob = newlibadr(fd, part->id.lib, dw->ob);
                                }
                        }
                        else {
-                               BLI_listbase_clear(&part->dupliweights);
+                               BLI_listbase_clear(&part->instance_weights);
                        }
 
                        if (part->boids) {
@@ -4358,7 +4371,7 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
        if (!part->effector_weights)
                part->effector_weights = BKE_effector_add_weights(part->eff_group);
 
-       link_list(fd, &part->dupliweights);
+       link_list(fd, &part->instance_weights);
 
        part->boids = newdataadr(fd, part->boids);
        part->fluid = newdataadr(fd, part->fluid);
@@ -4705,7 +4718,7 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
        direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
 
        mesh->bb = NULL;
-       mesh->edit_btmesh = NULL;
+       mesh->edit_mesh = NULL;
        BKE_mesh_runtime_reset(mesh);
 
        /* happens with old files */
@@ -4871,10 +4884,10 @@ static void lib_link_object(FileData *fd, Main *main)
 
                        /* 2.8x drops support for non-empty dupli instances. */
                        if (ob->type == OB_EMPTY) {
-                               ob->dup_group = newlibadr_us(fd, ob->id.lib, ob->dup_group);
+                               ob->instance_collection = newlibadr_us(fd, ob->id.lib, ob->instance_collection);
                        }
                        else {
-                               ob->dup_group = NULL;
+                               ob->instance_collection = NULL;
                                ob->transflag &= ~OB_DUPLICOLLECTION;
                        }
 
@@ -5642,7 +5655,7 @@ static void direct_link_object(FileData *fd, Object *ob)
                BKE_object_empty_draw_type_set(ob, ob->empty_drawtype);
        }
 
-       ob->bb = NULL;
+       ob->runtime.bb = NULL;
        ob->derivedDeform = NULL;
        ob->derivedFinal = NULL;
        BKE_object_runtime_reset(ob);
@@ -6574,6 +6587,11 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
        gpd->adt = newdataadr(fd, gpd->adt);
        direct_link_animdata(fd, gpd->adt);
 
+       /* init stroke buffer */
+       gpd->runtime.sbuffer = NULL;
+       gpd->runtime.sbuffer_size = 0;
+       gpd->runtime.tot_cp_points = 0;
+
        /* relink palettes (old palettes deprecated, only to convert old files) */
        link_list(fd, &gpd->palettes);
        if (gpd->palettes.first != NULL) {
@@ -6774,8 +6792,8 @@ static void direct_link_area(FileData *fd, ScrArea *area)
 
                        blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
                }
-               else if (sl->spacetype == SPACE_IPO) {
-                       SpaceIpo *sipo = (SpaceIpo *)sl;
+               else if (sl->spacetype == SPACE_GRAPH) {
+                       SpaceGraph *sipo = (SpaceGraph *)sl;
 
                        sipo->ads = newdataadr(fd, sipo->ads);
                        BLI_listbase_clear(&sipo->runtime.ghost_curves);
@@ -6786,7 +6804,7 @@ static void direct_link_area(FileData *fd, ScrArea *area)
                        snla->ads = newdataadr(fd, snla->ads);
                }
                else if (sl->spacetype == SPACE_OUTLINER) {
-                       SpaceOops *soops = (SpaceOops *)sl;
+                       SpaceOutliner *soops = (SpaceOutliner *)sl;
 
                        /* use newdataadr_no_us and do not free old memory avoiding double
                         * frees and use of freed memory. this could happen because of a
@@ -6876,8 +6894,8 @@ static void direct_link_area(FileData *fd, ScrArea *area)
                        sseq->scopes.histogram_ibuf = NULL;
                        sseq->compositor = NULL;
                }
-               else if (sl->spacetype == SPACE_BUTS) {
-                       SpaceButs *sbuts = (SpaceButs *)sl;
+               else if (sl->spacetype == SPACE_PROPERTIES) {
+                       SpaceProperties *sbuts = (SpaceProperties *)sl;
 
                        sbuts->path = NULL;
                        sbuts->texuser = NULL;
@@ -6960,9 +6978,9 @@ static void lib_link_area(FileData *fd, ID *parent_id, ScrArea *area)
                                }
                                break;
                        }
-                       case SPACE_IPO:
+                       case SPACE_GRAPH:
                        {
-                               SpaceIpo *sipo = (SpaceIpo *)sl;
+                               SpaceGraph *sipo = (SpaceGraph *)sl;
                                bDopeSheet *ads = sipo->ads;
 
                                if (ads) {
@@ -6971,9 +6989,9 @@ static void lib_link_area(FileData *fd, ID *parent_id, ScrArea *area)
                                }
                                break;
                        }
-                       case SPACE_BUTS:
+                       case SPACE_PROPERTIES:
                        {
-                               SpaceButs *sbuts = (SpaceButs *)sl;
+                               SpaceProperties *sbuts = (SpaceProperties *)sl;
                                sbuts->pinid = newlibadr(fd, parent_id->lib, sbuts->pinid);
                                if (sbuts->pinid == NULL) {
                                        sbuts->flag &= ~SB_PIN_CONTEXT;
@@ -7050,7 +7068,7 @@ static void lib_link_area(FileData *fd, ID *parent_id, ScrArea *area)
                        }
                        case SPACE_OUTLINER:
                        {
-                               SpaceOops *so = (SpaceOops *)sl;
+                               SpaceOutliner *so = (SpaceOutliner *)sl;
                                so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
 
                                if (so->treestore) {
@@ -7447,8 +7465,8 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main
                                                }
                                        }
                                }
-                               else if (sl->spacetype == SPACE_IPO) {
-                                       SpaceIpo *sipo = (SpaceIpo *)sl;
+                               else if (sl->spacetype == SPACE_GRAPH) {
+                                       SpaceGraph *sipo = (SpaceGraph *)sl;
                                        bDopeSheet *ads = sipo->ads;
 
                                        if (ads) {
@@ -7463,8 +7481,8 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main
                                         */
                                        sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR;
                                }
-                               else if (sl->spacetype == SPACE_BUTS) {
-                                       SpaceButs *sbuts = (SpaceButs *)sl;
+                               else if (sl->spacetype == SPACE_PROPERTIES) {
+                                       SpaceProperties *sbuts = (SpaceProperties *)sl;
                                        sbuts->pinid = restore_pointer_by_name(id_map, sbuts->pinid, USER_IGNORE);
                                        if (sbuts->pinid == NULL) {
                                                sbuts->flag &= ~SB_PIN_CONTEXT;
@@ -7554,7 +7572,7 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main
                                        }
                                }
                                else if (sl->spacetype == SPACE_OUTLINER) {
-                                       SpaceOops *so = (SpaceOops *)sl;
+                                       SpaceOutliner *so = (SpaceOutliner *)sl;
 
                                        so->search_tse.id = restore_pointer_by_name(id_map, so->search_tse.id, USER_IGNORE);
 
@@ -7636,9 +7654,9 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main
  * Used to link a file (without UI) to the current UI.
  * Note that it assumes the old pointers in UI are still valid, so old Main is not freed.
  */
-void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene, ViewLayer *cur_view_layer)
+void blo_lib_link_restore(Main *oldmain, Main *newmain, wmWindowManager *curwm, Scene *curscene, ViewLayer *cur_view_layer)
 {
-       struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain);
+       struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain, true, oldmain);
 
        for (WorkSpace *workspace = newmain->workspaces.first; workspace; workspace = workspace->id.next) {
                ListBase *layouts = BKE_workspace_layouts_get(workspace);
@@ -8763,8 +8781,8 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
 
                /* themes for Node and Sequence editor were not using grid color, but back. we copy this over then */
                for (btheme = user->themes.first; btheme; btheme = btheme->next) {
-                       copy_v4_v4_char(btheme->tnode.grid, btheme->tnode.back);
-                       copy_v4_v4_char(btheme->tseq.grid, btheme->tseq.back);
+                       copy_v4_v4_char(btheme->space_node.grid, btheme->space_node.back);
+                       copy_v4_v4_char(btheme->space_sequencer.grid, btheme->space_sequencer.back);
                }
        }
 
@@ -8993,11 +9011,9 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
                const int *data = read_file_thumbnail(fd);
 
                if (data) {
-                       int width = data[0];
-                       int height = data[1];
-
-                       /* Protect against buffer overflow vulnerability. */
-                       if (BLEN_THUMB_SAFE_MEMSIZE(width, height)) {
+                       const int width = data[0];
+                       const int height = data[1];
+                       if (BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
                                const size_t sz = BLEN_THUMB_MEMSIZE(width, height);
                                bfd->main->blen_thumb = MEM_mallocN(sz, __func__);
 
@@ -9484,8 +9500,8 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
 {
        int a;
 
-       expand_doit(fd, mainvar, part->dup_ob);
-       expand_doit(fd, mainvar, part->dup_group);
+       expand_doit(fd, mainvar, part->instance_object);
+       expand_doit(fd, mainvar, part->instance_collection);
        expand_doit(fd, mainvar, part->eff_group);
        expand_doit(fd, mainvar, part->bb_ob);
        expand_doit(fd, mainvar, part->collision_group);
@@ -9531,7 +9547,7 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
                }
        }
 
-       for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
+       for (ParticleDupliWeight *dw = part->instance_weights.first; dw; dw = dw->next) {
                expand_doit(fd, mainvar, dw->ob);
        }
 }
@@ -9853,8 +9869,8 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        if (paf && paf->group)
                expand_doit(fd, mainvar, paf->group);
 
-       if (ob->dup_group)
-               expand_doit(fd, mainvar, ob->dup_group);
+       if (ob->instance_collection)
+               expand_doit(fd, mainvar, ob->instance_collection);
 
        if (ob->proxy)
                expand_doit(fd, mainvar, ob->proxy);
@@ -10351,43 +10367,61 @@ static void add_loose_objects_to_scene(
 
 static void add_collections_to_scene(
         Main *mainvar, Main *bmain,
-        Scene *scene, ViewLayer *view_layer, const View3D *v3d, Library *UNUSED(lib), const short flag)
+        Scene *scene, ViewLayer *view_layer, const View3D *v3d, Library *lib, const short flag)
 {
        Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION);
 
        /* Give all objects which are tagged a base. */
        for (Collection *collection = mainvar->collection.first; collection; collection = collection->id.next) {
-               if (collection->id.tag & LIB_TAG_DOIT) {
-                       if (flag & FILE_GROUP_INSTANCE) {
-                               /* Any indirect collection should not have been tagged. */
-                               BLI_assert((collection->id.tag & LIB_TAG_INDIRECT) == 0);
+               if ((flag & FILE_GROUP_INSTANCE) && (collection->id.tag & LIB_TAG_DOIT)) {
+                       /* Any indirect collection should not have been tagged. */
+                       BLI_assert((collection->id.tag & LIB_TAG_INDIRECT) == 0);
 
-                               /* BKE_object_add(...) messes with the selection. */
-                               Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
-                               ob->type = OB_EMPTY;
+                       /* BKE_object_add(...) messes with the selection. */
+                       Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
+                       ob->type = OB_EMPTY;
 
-                               BKE_collection_object_add(bmain, active_collection, ob);
-                               Base *base = BKE_view_layer_base_find(view_layer, ob);
+                       BKE_collection_object_add(bmain, active_collection, ob);
+                       Base *base = BKE_view_layer_base_find(view_layer, ob);
 
-                               if (v3d != NULL) {
-                                       base->local_view_bits |= v3d->local_view_uuid;
-                               }
+                       if (v3d != NULL) {
+                               base->local_view_bits |= v3d->local_view_uuid;
+                       }
 
-                               if (base->flag & BASE_SELECTABLE) {
-                                       base->flag |= BASE_SELECTED;
-                               }
+                       if (base->flag & BASE_SELECTABLE) {
+                               base->flag |= BASE_SELECTED;
+                       }
 
-                               BKE_scene_object_base_flag_sync_from_base(base);
-                               DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-                               view_layer->basact = base;
+                       BKE_scene_object_base_flag_sync_from_base(base);
+                       DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+                       view_layer->basact = base;
 
-                               /* Assign the collection. */
-                               ob->dup_group = collection;
-                               id_us_plus(&collection->id);
-                               ob->transflag |= OB_DUPLICOLLECTION;
-                               copy_v3_v3(ob->loc, scene->cursor.location);
+                       /* Assign the collection. */
+                       ob->instance_collection = collection;
+                       id_us_plus(&collection->id);
+                       ob->transflag |= OB_DUPLICOLLECTION;
+                       copy_v3_v3(ob->loc, scene->cursor.location);
+               }
+               else {
+                       bool do_add_collection = (collection->id.tag & LIB_TAG_DOIT) != 0;
+                       if (!do_add_collection) {
+                               /* We need to check that objects in that collections are already instantiated in a scene.
+                                * Otherwise, it's better to add the collection to the scene's active collection, than to
+                                * instantiate its objects in active scene's collection directly. See T61141.
+                                * Note that we only check object directly into that collection, not recursively into its children.
+                                */
+                               for (CollectionObject *coll_ob = collection->gobject.first; coll_ob != NULL; coll_ob = coll_ob->next) {
+                                       Object *ob = coll_ob->ob;
+                                       if ((ob->id.tag & LIB_TAG_PRE_EXISTING) == 0 &&
+                                           (ob->id.lib == lib) &&
+                                           (object_in_any_scene(bmain, ob) == 0))
+                                       {
+                                               do_add_collection = true;
+                                               break;
+                                       }
+                               }
                        }
-                       else {
+                       if (do_add_collection) {
                                /* Add collection as child of active collection. */
                                BKE_collection_child_add(bmain, active_collection, collection);
 
@@ -10936,7 +10970,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                        change_idid_adr(mainlist, basefd, id, *realid);
 
                                                        /* We cannot free old lib-ref placeholder ID here anymore, since we use its name
-                                                        * as key in loaded_ids hass. */
+                                                        * as key in loaded_ids has. */
                                                        BLI_addtail(&pending_free_ids, id);
                                                }
                                                id = idn;