doxygen: add newline after \file
[blender.git] / source / blender / blenloader / intern / readfile.c
index c27e70c..8fcae12 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- *
  */
 
-/** \file blender/blenloader/intern/readfile.c
- *  \ingroup blenloader
+/** \file
+ * \ingroup blenloader
  */
 
 
 #include "BKE_collection.h"
 #include "BKE_colortools.h"
 #include "BKE_constraint.h"
-#include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_effect.h"
 #include "BKE_fcurve.h"
 #include "NOD_common.h"
 #include "NOD_socket.h"
 
+#include "BLO_blend_defs.h"
+#include "BLO_blend_validate.h"
 #include "BLO_readfile.h"
 #include "BLO_undofile.h"
-#include "BLO_blend_defs.h"
 
 #include "RE_engine.h"
 
@@ -941,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[]");
@@ -986,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)) {
@@ -1431,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;
@@ -1573,14 +1578,17 @@ static void change_idid_adr(ListBase *mainlist, FileData *basefd, void *old, voi
 /* lib linked proxy objects point to our local data, we need
  * to clear that pointer before reading the undo memfile since
  * the object might be removed, it is set again in reading
- * if the local object still exists */
+ * if the local object still exists.
+ * This is only valid for local proxy objects though, linked ones should not be affected here.
+ */
 void blo_clear_proxy_pointers_from_lib(Main *oldmain)
 {
        Object *ob = oldmain->object.first;
 
        for (; ob; ob = ob->id.next) {
-               if (ob->id.lib)
+               if (ob->id.lib != NULL && ob->proxy_from != NULL && ob->proxy_from->id.lib == NULL) {
                        ob->proxy_from = NULL;
+               }
        }
 }
 
@@ -3943,6 +3951,12 @@ static void direct_link_image(FileData *fd, Image *ima)
                }
                ima->rr = NULL;
        }
+       else {
+               for (int i = 0; i < TEXTARGET_COUNT; i++) {
+                       ima->gputexture[i] = newimaadr(fd, ima->gputexture[i]);
+               }
+               ima->rr = newimaadr(fd, ima->rr);
+       }
 
        /* undo system, try to restore render buffers */
        link_list(fd, &(ima->renderslots));
@@ -4177,7 +4191,7 @@ static const char *ptcache_data_struct[] = {
        "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
        "", // BPHYS_DATA_SIZE:
        "", // BPHYS_DATA_TIMES:
-       "BoidData" // case BPHYS_DATA_BOIDS:
+       "BoidData", // case BPHYS_DATA_BOIDS:
 };
 
 static void direct_link_pointcache_cb(FileData *fd, void *data)
@@ -4263,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);
@@ -4279,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) {
@@ -4357,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);
@@ -4704,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 */
@@ -4870,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;
                        }
 
@@ -5073,6 +5087,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                        SubsurfModifierData *smd = (SubsurfModifierData *)md;
 
                        smd->emCache = smd->mCache = NULL;
+                       smd->subdiv = NULL;
                }
                else if (md->type == eModifierType_Armature) {
                        ArmatureModifierData *amd = (ArmatureModifierData *)md;
@@ -5392,6 +5407,10 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                        BevelModifierData *bmd = (BevelModifierData *)md;
                        bmd->clnordata.faceHash = NULL;
                }
+               else if (md->type == eModifierType_Multires) {
+                       MultiresModifierData *mmd = (MultiresModifierData *)md;
+                       mmd->subdiv = NULL;
+               }
        }
 }
 
@@ -5636,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);
@@ -6011,7 +6030,7 @@ static void lib_link_scene(FileData *fd, Main *main)
                        sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
 
                        sce->toolsettings->gp_sculpt.guide.reference_object = newlibadr(fd, sce->id.lib, sce->toolsettings->gp_sculpt.guide.reference_object);
-                       
+
                        for (Base *base_legacy_next, *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) {
                                base_legacy_next = base_legacy->next;
 
@@ -6496,9 +6515,9 @@ static void direct_link_scene(FileData *fd, Scene *sce)
 
        if (sce->master_collection) {
                sce->master_collection = newdataadr(fd, sce->master_collection);
-               direct_link_collection(fd, sce->master_collection);
                /* Needed because this is an ID outside of Main. */
-               sce->master_collection->id.py_instance = NULL;
+               direct_link_id(fd, &sce->master_collection->id);
+               direct_link_collection(fd, sce->master_collection);
        }
 
        /* insert into global old-new map for reading without UI (link_global accesses it again) */
@@ -6568,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) {
@@ -6768,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);
@@ -6780,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
@@ -6870,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;
@@ -6954,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) {
@@ -6965,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;
@@ -7044,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) {
@@ -7441,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) {
@@ -7457,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;
@@ -7548,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);
 
@@ -7630,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);
@@ -8682,7 +8706,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
        oldnewmap_clear(fd->datamap);
 
        if (wrong_id) {
-               BKE_libblock_free(main, id);
+               BKE_id_free(main, id);
        }
 
        return (bhead);
@@ -8757,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);
                }
        }
 
@@ -8868,6 +8892,10 @@ static void lib_link_all(FileData *fd, Main *main)
        lib_link_workspaces(fd, main);
 
        lib_link_library(fd, main);    /* only init users */
+
+       /* We could integrate that to mesh/curve/lattice lib_link, but this is really cheap process,
+        * so simpler to just use it directly in this single call. */
+       BLO_main_validate_shapekeys(main, NULL);
 }
 
 static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi)
@@ -8983,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__);
 
@@ -9474,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);
@@ -9521,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);
        }
 }
@@ -9843,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);
@@ -10341,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);
 
@@ -10836,7 +10880,6 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                FileData *fd = mainptr->curlib->filedata;
 
                                if (fd == NULL) {
-
                                        /* printf and reports for now... its important users know this */
 
                                        /* if packed file... */
@@ -10861,30 +10904,6 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                        library_parent_filepath(mainptr->curlib));
                                                fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
                                        }
-                                       /* allow typing in a new lib path */
-                                       if (G.debug_value == -666) {
-                                               while (fd == NULL) {
-                                                       char newlib_path[FILE_MAX] = {0};
-                                                       printf("Missing library...'\n");
-                                                       printf("\tcurrent file: %s\n", BKE_main_blendfile_path_from_global());
-                                                       printf("\tabsolute lib: %s\n", mainptr->curlib->filepath);
-                                                       printf("\trelative lib: %s\n", mainptr->curlib->name);
-                                                       printf("  enter a new path:\n");
-
-                                                       if (scanf("%1023s", newlib_path) > 0) {  /* Warning, keep length in sync with FILE_MAX! */
-                                                               BLI_strncpy(mainptr->curlib->name, newlib_path, sizeof(mainptr->curlib->name));
-                                                               BLI_strncpy(mainptr->curlib->filepath, newlib_path, sizeof(mainptr->curlib->filepath));
-                                                               BLI_cleanup_path(BKE_main_blendfile_path_from_global(), mainptr->curlib->filepath);
-
-                                                               fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
-
-                                                               if (fd) {
-                                                                       fd->mainlist = mainlist;
-                                                                       printf("found: '%s', party on macuno!\n", mainptr->curlib->filepath);
-                                                               }
-                                                       }
-                                               }
-                                       }
 
                                        if (fd) {
                                                /* share the mainlist, so all libraries are added immediately in a
@@ -10908,7 +10927,6 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
 #ifdef USE_GHASH_BHEAD
                                                read_file_bhead_idname_map_create(fd);
 #endif
-
                                        }
                                        else {
                                                mainptr->curlib->filedata = NULL;
@@ -10952,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;