[Bf-blender-cvs] [041e2d3] layers: Base list refcount with Bastien Montagne

Dalai Felinto noreply at git.blender.org
Thu Nov 24 18:07:58 CET 2016


Commit: 041e2d3e28c549beb1a40a7ee70597f6a9fc1d7a
Author: Dalai Felinto
Date:   Thu Nov 24 18:07:19 2016 +0100
Branches: layers
https://developer.blender.org/rB041e2d3e28c549beb1a40a7ee70597f6a9fc1d7a

Base list refcount with Bastien Montagne

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

M	source/blender/blenkernel/BKE_scene.h
M	source/blender/blenkernel/intern/scene.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_scene.c

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

diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 9c46252..89e25b9 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -98,10 +98,12 @@ void BKE_scene_base_flag_to_objects(struct Scene *scene);
 void BKE_scene_base_flag_from_objects(struct Scene *scene);
 
 /* base functions */
+void         BKE_scene_layer_base_unref(struct SceneLayer *sl, struct Base *base);
 struct Base *BKE_scene_layer_base_find_by_name(struct SceneLayer *sl, const char *name);
 struct Base *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob);
 struct Base *BKE_scene_layer_collection_base_find(struct LayerCollection *lc, struct Object *ob);
 struct Base *BKE_scene_layer_base_add(struct SceneLayer *sl, struct LayerCollection *lc, struct Object *ob);
+void         BKE_scene_layer_base_unlink(struct Scene *scene, struct LayerCollection *lc, struct Base *base);
 void         BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
 void         BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase);
 
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 1cb628a..b739fc4 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -104,7 +104,7 @@
 #include "bmesh.h"
 
 /* prototypes */
-static void layer_collections_free(ListBase *lb);
+static void layer_collections_free(SceneLayer *sl, ListBase *lb);
 
 const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER";
 const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME";
@@ -502,9 +502,8 @@ void BKE_scene_free(Scene *sce)
 
 	for (sl = sce->layers.first; sl; sl = sl->next) {
 		sl->basact = NULL;
+		layer_collections_free(sl, &sl->collections);
 		BLI_freelistN(&sl->base);
-
-		layer_collections_free(&sl->collections);
 	}
 	BLI_freelistN(&sce->layers);
 }
@@ -910,6 +909,7 @@ static Base *scene_layer_base_add(SceneLayer *sl, Object *ob)
 	b->object = ob;
 	b->flag = ob->flag;
 	b->lay = ob->lay;
+	b->refcount = 1;
 
 	return b;
 }
@@ -922,12 +922,22 @@ Base *BKE_scene_layer_base_add(SceneLayer *sl, LayerCollection *lc, Object *ob)
 		base = scene_layer_base_add(sl, ob);
 	}
 
-	/* only bump id count for collection */
+	/* Only bump id count for collection, but refcount we do it for both */
 	id_us_plus(&ob->id);
 	BLI_addtail(&lc->elements, BLI_genericNodeN(base));
+	base->refcount++;
 	return base;
 }
 
+void BKE_scene_layer_base_unlink(Scene *scene, LayerCollection *lc, Base *base)
+{
+	SceneLayer *sl = BKE_scene_layer_from_collection(scene, lc);
+	LinkData *ld = BLI_findptr(&lc->elements, base, offsetof(LinkData, data));
+
+	BLI_remlink(&lc->elements, ld);
+	BKE_scene_layer_base_unref(sl, base);
+}
+
 /**
  * Sets the active scene, mainly used when running in background mode (``--scene`` command line argument).
  * This is also called to set the scene directly, bypassing windowing code.
@@ -2211,17 +2221,43 @@ LayerCollection *BKE_scene_add_collection(SceneLayer *sl, LayerCollection *lc_pa
 	return lc_new;
 }
 
-static void layer_collection_free(LayerCollection *lc)
+void BKE_scene_layer_base_unref(SceneLayer* sl, Base *base)
+{
+	base->refcount--;
+	/* It only exists in the SceneLayer */
+	if (base->refcount == 1) {
+
+#ifdef LAYERS_RIGID_BODY
+		/* remove rigid body constraint from world before removing object */
+		if (base->object->rigidbody_constraint)
+			BKE_rigidbody_remove_constraint(sce, base->object);
+		/* remove rigid body object from world before removing object */
+		if (base->object->rigidbody_object)
+			BKE_rigidbody_remove_object(sce, base->object);
+#endif
+		if (sl->basact == base)
+			sl->basact = NULL;
+
+		BLI_remlink(&sl->base, base);
+		MEM_freeN(base);
+	}
+}
+
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
 {
+	for (LinkData *ld = lc->elements.first; ld; ld = ld->next) {
+		BKE_scene_layer_base_unref(sl, ld->data);
+	}
+
 	BLI_freelistN(&lc->elements);
 	BLI_freelistN(&lc->overrides);
-	layer_collections_free(&lc->collections);
+	layer_collections_free(sl, &lc->collections);
 }
 
-static void layer_collections_free(ListBase *lb)
+static void layer_collections_free(SceneLayer *sl, ListBase *lb)
 {
 	for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
-		layer_collection_free(lc);
+		layer_collection_free(sl, lc);
 	}
 	BLI_freelistN(lb);
 }
@@ -2237,7 +2273,7 @@ bool BKE_scene_remove_collection(SceneLayer *sl, LayerCollection *lc_parent, Lay
 	}
 
 	BLI_remlink(lb, lc);
-	layer_collection_free(lc);
+	layer_collection_free(sl, lc);
 	MEM_freeN(lc);
 
 	/* TODO only change active_collection if necessary */
@@ -2281,7 +2317,7 @@ bool BKE_scene_remove_layer(Main *bmain, Scene *scene, SceneLayer *sl)
 
 	BLI_freelistN(&sl->base);
 
-	layer_collections_free(&sl->collections);
+	layer_collections_free(sl, &sl->collections);
 
 	MEM_freeN(sl);
 
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9f87925..9a45f24 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5507,6 +5507,7 @@ static void direct_link_layer_collections(FileData *fd , ListBase *lb)
 
 		for (LinkData *ld = lc->elements.first; ld; ld = ld->next) {
 			ld->data = newdataadr(fd, ld->data);
+			((Base *)ld->data)->refcount++;
 		}
 
 		direct_link_layer_collections(fd, &lc->collections);
@@ -5758,7 +5759,11 @@ static void direct_link_scene(FileData *fd, Scene *sce)
 	for (sl = sce->layers.first; sl; sl = sl->next) {
 		sl->obedit = NULL;
 		sl->basact = newdataadr(fd, sl->basact);
+
 		link_list(fd, &(sl->base));
+		for (Base *base = sl->base.first; base; base = base->next) {
+			base->refcount++;
+		}
 
 		/* recursively direct link the layer collections */
 		direct_link_layer_collections(fd, &(sl->collections));
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 60aa0b1..75da920 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -75,6 +75,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
 			Base *base = scene->base.first;
 			while (base) {
 				Base *base_new = MEM_dupallocN(base);
+				base_new->refcount++;
 				BLI_addtail(&sl->base, base_new);
 
 				if (base == scene->basact) {
@@ -86,6 +87,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
 				for (int i = 0; i < 20; i++) {
 					if ((base->lay & (1 << i)) != 0) {
 						BLI_addtail(&collections[i]->elements, BLI_genericNodeN(base_new));
+						base_new->refcount++;
 					}
 				}
 				base = base->next;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index cc1ef4d..e121af8 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -74,8 +74,9 @@ typedef struct Base {
 	struct Base *next, *prev;
 	unsigned int lay DNA_DEPRECATED_LAYERS;	/* deprecated in 2.8 */
 	unsigned int selcol;
-	int flag;
+	short flag;
 	short sx, sy;
+	short refcount;
 	struct Object *object;
 } Base;
 
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index dcb8ce2..e594b68 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -657,6 +657,31 @@ static Base *rna_LayerCollection_object_link(ID *id, LayerCollection *lc, Main *
 	return base;
 }
 
+static void rna_LayerCollection_object_unlink(ID *id, LayerCollection *lc, ReportList *reports, Object *ob)
+{
+	Scene *scene = (Scene *)id;
+	SceneLayer *sl = BKE_scene_layer_from_collection(scene, lc);
+	Base *base = BKE_scene_layer_collection_base_find(lc, ob);
+
+	if (!base) {
+		BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in this collection '%s'", ob->id.name + 2, lc->name);
+		return;
+	}
+
+	if (((base->flag & SELECT) != 0) && sl->mode != OB_MODE_OBJECT) {
+		BKE_reportf(reports, RPT_ERROR, "Object '%s' must be in object mode to unlink", ob->id.name + 2);
+		return;
+	}
+
+	BKE_scene_layer_base_unlink(scene, lc, base);
+	id_us_min(&ob->id);
+
+	/* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
+	DAG_relations_tag_update(G.main);
+
+	WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
+}
+
 static int rna_Scene_layer_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
 {
 	SceneLayer *sl = (SceneLayer *)ptr->data;
@@ -5231,6 +5256,12 @@ static void rna_def_layer_collection_objects(BlenderRNA *brna, PropertyRNA *cpro
 	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
 	parm = RNA_def_pointer(func, "base", "ObjectBase", "", "The newly created base");
 	RNA_def_function_return(func, parm);
+
+	func = RNA_def_function(srna, "unlink", "rna_LayerCollection_object_unlink");
+	RNA_def_function_ui_description(func, "Unlink object from collection");
+	RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+	parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove from collection");
+	RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
 }
 
 static void rna_def_layer_nested_collections(BlenderRNA *brna, PropertyRNA *cprop)




More information about the Bf-blender-cvs mailing list