diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2016-11-24 20:07:19 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2016-11-24 20:07:19 +0300 |
commit | 041e2d3e28c549beb1a40a7ee70597f6a9fc1d7a (patch) | |
tree | 0808cbd0af0b6d2e7528c2662e7dcfc5db189fc9 | |
parent | be976500fe6d8d7f6df15298ea806caaa42a0009 (diff) |
Base list refcount with Bastien Montagnelayers
-rw-r--r-- | source/blender/blenkernel/BKE_scene.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 56 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 5 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 31 |
6 files changed, 88 insertions, 11 deletions
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 9c462523c18..89e25b97e59 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 1cb628a4750..b739fc414a5 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 9f87925bce0..9a45f242287 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 60aa0b17a64..75da9200bba 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 cc1ef4dca32..e121af8166e 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 dcb8ce2892c..e594b68a31e 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) |