[Bf-blender-cvs] [cba447966ec] master: Fix T61683: Linking the instance of a collection crashes Blender.

Bastien Montagne noreply at git.blender.org
Tue Feb 19 13:50:04 CET 2019


Commit: cba447966ec51db48459e57d838e8b4562b96c5e
Author: Bastien Montagne
Date:   Tue Feb 19 13:44:23 2019 +0100
Branches: master
https://developer.blender.org/rBcba447966ec51db48459e57d838e8b4562b96c5e

Fix T61683: Linking the instance of a collection crashes Blender.

Do not instance linked object immediately in scene, this was never a
good idea and is doomed to fail nowadays, with complex relations between
objects, collections and scenes.

Instead, this commit refactors a bit linking code to add loose objects
to current scene *after* everything has been imported, and ID pointers
have been properly remapped to new ones - i.e. once new linked data is
supposed to be fully valid, just like we were already doing with
collections.

As a bonus, it means we do not have to pass around scene, view3d etc. to
`BLO_library_link_named_part_ex()` and co.

===================================================================

M	source/blender/blenloader/BLO_readfile.h
M	source/blender/blenloader/intern/readfile.c
M	source/blender/windowmanager/intern/wm_files_link.c

===================================================================

diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index bddfdf6926f..c3a1c0e5185 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -133,8 +133,7 @@ struct Main *BLO_library_link_begin(struct Main *mainvar, BlendHandle **bh, cons
 struct ID *BLO_library_link_named_part(struct Main *mainl, BlendHandle **bh, const short idcode, const char *name);
 struct ID *BLO_library_link_named_part_ex(
         struct Main *mainl, BlendHandle **bh,
-        const short idcode, const char *name, const int flag,
-        struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, const struct View3D *v3d);
+        const short idcode, const char *name, const int flag);
 void BLO_library_link_end(
         struct Main *mainl, BlendHandle **bh, int flag,
         struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, const struct View3D *v3d);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 745fccdcbad..7f8c224114d 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -10320,9 +10320,8 @@ static void add_loose_objects_to_scene(
 
 	/* Give all objects which are LIB_TAG_INDIRECT a base, or for a collection when *lib has been set. */
 	for (Object *ob = mainvar->object.first; ob; ob = ob->id.next) {
-		if ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0) {
-			bool do_it = false;
-
+		bool do_it = (ob->id.tag & LIB_TAG_DOIT) != 0;
+		if (do_it || ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0)) {
 			if (!is_link) {
 				if (ob->id.us == 0) {
 					do_it = true;
@@ -10336,6 +10335,7 @@ static void add_loose_objects_to_scene(
 
 			if (do_it) {
 				CLAMP_MIN(ob->id.us, 0);
+				ob->mode = OB_MODE_OBJECT;
 
 				Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION);
 				BKE_collection_object_add(bmain, active_collection, ob);
@@ -10348,8 +10348,6 @@ static void add_loose_objects_to_scene(
 				BKE_scene_object_base_flag_sync_from_base(base);
 
 				if (flag & FILE_AUTOSELECT) {
-					/* Note that link_object_postprocess() already checks for FILE_AUTOSELECT flag,
-					 * but it will miss objects from non-instantiated collections... */
 					if (base->flag & BASE_SELECTABLE) {
 						base->flag |= BASE_SELECTED;
 						BKE_scene_object_base_flag_sync_from_base(base);
@@ -10412,6 +10410,7 @@ static void add_collections_to_scene(
 				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.tag & LIB_TAG_DOIT) == 0 &&
 					    (ob->id.lib == lib) &&
 					    (object_in_any_scene(bmain, ob) == 0))
 					{
@@ -10500,38 +10499,6 @@ static ID *link_named_part(
 	return id;
 }
 
-static void link_object_postprocess(
-        ID *id, Main *bmain, Scene *scene, ViewLayer *view_layer, const View3D *v3d, const int flag)
-{
-	if (scene) {
-		/* link to scene */
-		Base *base;
-		Object *ob;
-		Collection *collection;
-
-		ob = (Object *)id;
-		ob->mode = OB_MODE_OBJECT;
-
-		collection = get_collection_active(bmain, scene, view_layer, flag);
-		BKE_collection_object_add(bmain, collection, ob);
-		base = BKE_view_layer_base_find(view_layer, ob);
-		BKE_scene_object_base_flag_sync_from_base(base);
-
-		/* Link at active local view (view3d if available in context. */
-		if (v3d != NULL) {
-			base->local_view_bits |= v3d->local_view_uuid;
-		}
-
-		if (flag & FILE_AUTOSELECT) {
-			if (base->flag & BASE_SELECTABLE) {
-				base->flag |= BASE_SELECTED;
-				BKE_scene_object_base_flag_sync_from_base(base);
-			}
-			/* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
-		}
-	}
-}
-
 /**
  * Simple reader for copy/paste buffers.
  */
@@ -10568,13 +10535,13 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh)
 }
 
 static ID *link_named_part_ex(
-        Main *mainl, FileData *fd, const short idcode, const char *name, const int flag,
-        Main *bmain, Scene *scene, ViewLayer *view_layer, const View3D *v3d)
+        Main *mainl, FileData *fd, const short idcode, const char *name, const int flag)
 {
 	ID *id = link_named_part(mainl, fd, idcode, name, flag);
 
-	if (id && (GS(id->name) == ID_OB)) {    /* loose object: give a base */
-		link_object_postprocess(id, bmain, scene, view_layer, v3d, flag);
+	if (id && (GS(id->name) == ID_OB)) {
+		/* Tag as loose object needing to be instantiated somewhere... */
+		id->tag |= LIB_TAG_DOIT;
 	}
 	else if (id && (GS(id->name) == ID_GR)) {
 		/* tag as needing to be instantiated or linked */
@@ -10614,11 +10581,10 @@ ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcod
  */
 ID *BLO_library_link_named_part_ex(
         Main *mainl, BlendHandle **bh,
-        const short idcode, const char *name, const int flag,
-        Main *bmain, Scene *scene, ViewLayer *view_layer, const View3D *v3d)
+        const short idcode, const char *name, const int flag)
 {
 	FileData *fd = (FileData *)(*bh);
-	return link_named_part_ex(mainl, fd, idcode, name, flag, bmain, scene, view_layer, v3d);
+	return link_named_part_ex(mainl, fd, idcode, name, flag);
 }
 
 static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id)
@@ -10798,7 +10764,8 @@ static void library_link_end(
 		/* printf("library_append_end, scene is NULL (objects wont get bases)\n"); */
 	}
 
-	/* clear collection instantiating tag */
+	/* Clear objects and collections instantiating tag. */
+	BKE_main_id_tag_listbase(&(mainvar->object), LIB_TAG_DOIT, false);
 	BKE_main_id_tag_listbase(&(mainvar->collection), LIB_TAG_DOIT, false);
 
 	/* patch to prevent switch_endian happens twice */
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index b64cf0f2d15..3b27d2199b6 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -253,9 +253,7 @@ static void wm_link_do(
 				continue;
 			}
 
-			new_id = BLO_library_link_named_part_ex(
-			        mainl, &bh, item->idcode, item->name, flag, bmain,
-			        scene, view_layer, v3d);
+			new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag);
 
 			if (new_id) {
 				/* If the link is successful, clear item's libs 'todo' flags.



More information about the Bf-blender-cvs mailing list