diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2016-11-23 19:44:28 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2016-11-23 20:26:06 +0300 |
commit | 75d6c0cae6426d0a37c45476b527a406eaffd08b (patch) | |
tree | 0fb8626f703519b1333fc6d9d574dccbd53c9d7a /source | |
parent | b3de810bf22ad0cbdec1b806bf6998ed64d849df (diff) |
Fix mem leak for recursive collections and get layer.bases and objects
to work
(also some base util functions, and a refactor to unify the functions
for nested and non nested collections)
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_scene.h | 17 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 130 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 101 |
3 files changed, 187 insertions, 61 deletions
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 4039ff909e7..865d6b31dc1 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -97,6 +97,15 @@ int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBas void BKE_scene_base_flag_to_objects(struct Scene *scene); void BKE_scene_base_flag_from_objects(struct Scene *scene); +/* base functions */ +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); +void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl); +void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase); + +void BKE_scene_layer_base_flag_to_objects(struct SceneLayer *sl); +void BKE_scene_layer_base_flag_from_objects(struct SceneLayer *sl); + void BKE_scene_set_background(struct Main *bmain, struct Scene *sce); struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name); @@ -126,13 +135,11 @@ void BKE_scene_update_tagged(struct EvaluationContext *eval_ctx, struct Main *bm void BKE_scene_update_for_newframe(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay); void BKE_scene_update_for_newframe_ex(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay, bool do_invisible_flush); +struct SceneLayer *BKE_scene_layer_from_collection(struct Scene *scene, struct LayerCollection *lc); struct SceneLayer *BKE_scene_add_layer(struct Scene *sce, const char *name); bool BKE_scene_remove_layer(struct Main *main, struct Scene *scene, struct SceneLayer *sl); -struct LayerCollection *BKE_scene_add_collection(struct SceneLayer *sl, const char *name); -bool BKE_scene_remove_nested_collection(struct SceneLayer *sl, struct LayerCollection *lc_parent, struct LayerCollection *lc); -struct SceneLayer *BKE_scene_layer_from_collection(struct Scene *scene, struct LayerCollection *lc); -bool BKE_scene_remove_collection(struct SceneLayer *sl, struct LayerCollection *lc); -struct LayerCollection *BKE_scene_add_nested_collection(struct SceneLayer *sl, struct LayerCollection *lc, const char *name); +struct LayerCollection *BKE_scene_add_collection(struct SceneLayer *sl, struct LayerCollection *lc_parent, const char *name); +bool BKE_scene_remove_collection(struct SceneLayer *sl, struct LayerCollection *lc_parent, struct LayerCollection *lc); struct LayerCollection *BKE_scene_layer_collection_active(struct SceneLayer *sl); int BKE_scene_layer_collection_count(struct SceneLayer *sl); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index f8319318e52..6ea9825b33e 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -103,6 +103,9 @@ #include "bmesh.h" +/* prototypes */ +static void layer_collections_free(ListBase *lb); + const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER"; const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME"; const char *RE_engine_id_CYCLES = "CYCLES"; @@ -501,11 +504,7 @@ void BKE_scene_free(Scene *sce) sl->basact = NULL; BLI_freelistN(&sl->base); - for (LayerCollection *lc = sl->collections.first; lc; lc = lc->next) { - BLI_freelistN(&lc->elements); - BLI_freelistN(&lc->overrides); - } - BLI_freelistN(&sl->collections); + layer_collections_free(&sl->collections); } BLI_freelistN(&sce->layers); } @@ -873,6 +872,24 @@ Base *BKE_scene_base_find(Scene *scene, Object *ob) return BLI_findptr(&scene->base, ob, offsetof(Base, object)); } +Base *BKE_scene_layer_base_find_by_name(struct SceneLayer *sl, const char *name) +{ + Base *base; + + for (base = sl->base.first; base; base = base->next) { + if (STREQ(base->object->id.name + 2, name)) { + break; + } + } + + return base; +} + +Base *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob) +{ + return BLI_findptr(&sl->base, ob, offsetof(Base, object)); +} + /** * 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. @@ -1219,6 +1236,25 @@ void BKE_scene_base_select(Scene *sce, Base *selbase) sce->basact = selbase; } +void BKE_scene_layer_base_deselect_all(SceneLayer *sl) +{ + Base *b; + + for (b = sl->base.first; b; b = b->next) { + b->flag &= ~SELECT; + b->object->flag = b->flag; + } +} + +void BKE_scene_layer_base_select(SceneLayer *sl, Base *selbase) +{ + selbase->flag |= SELECT; + selbase->object->flag = selbase->flag; + + sl->basact = selbase; +} + + /* checks for cycle, returns 1 if it's all OK */ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) { @@ -2123,72 +2159,47 @@ SceneLayer *BKE_scene_layer_from_collection(Scene *scene, LayerCollection *lc) return NULL; } -LayerCollection *BKE_scene_add_nested_collection(SceneLayer *sl, LayerCollection *lc, const char *name) +/* lc_parent is optional, to be used only for nested collections */ +LayerCollection *BKE_scene_add_collection(SceneLayer *sl, LayerCollection *lc_parent, const char *name) { + ListBase *lb = (lc_parent ? &lc_parent->collections : &sl->collections); LayerCollection *lc_new; lc_new = MEM_callocN(sizeof(LayerCollection), "new layer collection"); BLI_strncpy(lc_new->name, name, sizeof(lc_new->name)); BLI_uniquename(&sl->collections, lc_new, DATA_("Collection"), '.', offsetof(LayerCollection, name), sizeof(lc_new->name)); - BLI_addtail(&lc->collections, lc_new); + BLI_addtail(lb, lc_new); return lc_new; } -static void free_collection(LayerCollection *lc) +static void layer_collection_free(LayerCollection *lc) { BLI_freelistN(&lc->elements); BLI_freelistN(&lc->overrides); + layer_collections_free(&lc->collections); } -bool BKE_scene_remove_nested_collection(SceneLayer *sl, LayerCollection *lc_parent, LayerCollection *lc) +static void layer_collections_free(ListBase *lb) { - const int act = BLI_findindex(&lc_parent->collections, lc); - if (act == -1) { - return false; + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + layer_collection_free(lc); } - - BLI_remlink(&lc_parent->collections, lc); - free_collection(lc); - MEM_freeN(lc); - - /* TODO only change active_collection if necessary */ - sl->active_collection = 0; - - return true; + BLI_freelistN(lb); } -LayerCollection *BKE_scene_add_collection(SceneLayer *sl, const char *name) +/* lc_parent is optional, to be used only for nested collections */ +bool BKE_scene_remove_collection(SceneLayer *sl, LayerCollection *lc_parent, LayerCollection *lc) { - LayerCollection *lc; - - lc = MEM_callocN(sizeof(LayerCollection), "new layer collection"); - BLI_strncpy(lc->name, name, sizeof(lc->name)); - BLI_uniquename(&sl->collections, lc, DATA_("Collection"), '.', offsetof(LayerCollection, name), sizeof(lc->name)); - BLI_addtail(&sl->collections, lc); - - return lc; -} + ListBase *lb = (lc_parent ? &lc_parent->collections : &sl->collections); + const int act = BLI_findindex(lb, lc); -bool BKE_scene_remove_collection(SceneLayer *sl, LayerCollection *lc) -{ - const int act = BLI_findindex(&sl->collections, lc); if (act == -1) { return false; } - else if ( (sl->collections.first == sl->collections.last) && - (sl->collections.first == lc)) - { - /* ensure 1 layer is kept */ - return false; - } - BLI_remlink(&sl->collections, lc); - free_collection(lc); - MEM_freeN(lc); - - BLI_freelistN(&lc->elements); - BLI_freelistN(&lc->overrides); + BLI_remlink(lb, lc); + layer_collection_free(lc); MEM_freeN(lc); /* TODO only change active_collection if necessary */ @@ -2210,7 +2221,7 @@ SceneLayer *BKE_scene_add_layer(Scene *sce, const char *name) BLI_uniquename(&sce->layers, sl, DATA_("Layer"), '.', offsetof(SceneLayer, name), sizeof(sl->name)); /* Initial collection */ - BKE_scene_add_collection(sl, "Collection"); + BKE_scene_add_collection(sl, NULL, "Collection"); BLI_addtail(&sce->layers, sl); return sl; } @@ -2232,11 +2243,8 @@ bool BKE_scene_remove_layer(Main *bmain, Scene *scene, SceneLayer *sl) BLI_freelistN(&sl->base); - for (LayerCollection *lc = sl->collections.first; lc; lc = lc->next) { - free_collection(lc); - } + layer_collections_free(&sl->collections); - BLI_freelistN(&sl->collections); MEM_freeN(sl); /* TODO only change active_layer if necessary */ @@ -2478,6 +2486,26 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene) } } +void BKE_scene_layer_base_flag_to_objects(struct SceneLayer *sl) +{ + Base *base = sl->base.first; + + while (base) { + base->object->flag = base->flag; + base = base->next; + } +} + +void BKE_scene_layer_base_flag_from_objects(struct SceneLayer *sl) +{ + Base *base = sl->base.first; + + while (base) { + base->flag = base->object->flag; + base = base->next; + } +} + void BKE_scene_disable_color_management(Scene *scene) { ColorManagedDisplaySettings *display_settings = &scene->display_settings; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 117adb9ba21..9439c00e295 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -632,6 +632,29 @@ static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *o 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; + Base *base; + + for (base = sl->base.first; base; base = base->next) { + if (STREQLEN(base->object->id.name + 2, key, sizeof(base->object->id.name) - 2)) { + *r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBase, base); + return true; + } + } + + return false; +} + +static PointerRNA rna_Scene_layer_objects_get(CollectionPropertyIterator *iter) +{ + ListBaseIterator *internal = &iter->internal.listbase; + + /* we are actually iterating a Base list, so override get */ + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((Base *)internal->link)->object); +} + static void rna_Scene_skgen_etch_template_set(PointerRNA *ptr, PointerRNA value) { ToolSettings *ts = (ToolSettings *)ptr->data; @@ -1335,11 +1358,26 @@ static void rna_FFmpegSettings_codec_settings_update(Main *UNUSED(bmain), Scene } #endif +static PointerRNA rna_Scene_layer_active_object_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_Object, sl->basact ? sl->basact->object : NULL); +} + +static void rna_Scene_layer_active_object_set(PointerRNA *ptr, PointerRNA value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + if (value.data) + sl->basact = BKE_scene_layer_base_find(sl, (Object *)value.data); + else + sl->basact = NULL; +} + static LayerCollection *rna_LayerNestedCollection_new(ID *id, LayerCollection *lc, const char *name) { Scene *scene = (Scene *)id; SceneLayer *sl = BKE_scene_layer_from_collection(scene, lc); - LayerCollection *lc_new = BKE_scene_add_nested_collection(sl, lc, name); + LayerCollection *lc_new = BKE_scene_add_collection(sl, lc, name); DAG_id_tag_update(id, 0); WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); @@ -1354,7 +1392,7 @@ static void rna_LayerNestedCollection_remove( SceneLayer *sl = BKE_scene_layer_from_collection(scene, lc_parent); LayerCollection *lc = lc_ptr->data; - if (!BKE_scene_remove_nested_collection(sl, lc_parent, lc)) { + if (!BKE_scene_remove_collection(sl, lc_parent, lc)) { BKE_reportf(reports, RPT_ERROR, "Nested collection '%s' could not be removed from collection '%s'", lc->name, lc_parent->name ); return; @@ -1404,7 +1442,7 @@ static void rna_Layer_active_collection_set(PointerRNA *ptr, PointerRNA value) static LayerCollection *rna_LayerCollection_new(ID *id, SceneLayer *sl, const char *name) { - LayerCollection *lc = BKE_scene_add_collection(sl, name); + LayerCollection *lc = BKE_scene_add_collection(sl, NULL, name); DAG_id_tag_update(id, 0); WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); @@ -1418,7 +1456,7 @@ static void rna_LayerCollection_remove( Scene *scene = (Scene *)id; LayerCollection *lc = lc_ptr->data; - if (!BKE_scene_remove_collection(sl, lc)) { + if (!BKE_scene_remove_collection(sl, NULL, lc)) { BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' could not be removed from layer '%s'", lc->name, sl->name ); return; @@ -5103,6 +5141,44 @@ static void rna_def_gpu_fx(BlenderRNA *brna) /* Scene Layers */ +/* layer.bases */ +static void rna_def_layer_bases(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "LayerBases"); + srna = RNA_def_struct(brna, "LayerBases", NULL); + RNA_def_struct_sdna(srna, "SceneLayer"); + RNA_def_struct_ui_text(srna, "Layer Bases", "Collection of layer bases"); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ObjectBase"); + RNA_def_property_pointer_sdna(prop, NULL, "basact"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Active Base", "Active object base in the scene layer"); + RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL); +} + +/* layer.objects */ +static void rna_def_layer_objects(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "LayerObjects"); + srna = RNA_def_struct(brna, "LayerObjects", NULL); + RNA_def_struct_sdna(srna, "SceneLayer"); + RNA_def_struct_ui_text(srna, "Layer Objects", "Collection of layer objects"); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_pointer_funcs(prop, "rna_Scene_layer_active_object_get", "rna_Scene_layer_active_object_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Object", "Active object for this scene layer"); + RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL); +} + static void rna_def_layer_nested_collections(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; @@ -5235,7 +5311,22 @@ static void rna_def_scene_layer(BlenderRNA *brna) /* TODO engine */ /* TODO mode */ - /* TODO baselist (selected objects, ...) */ + + /* Bases/Objects */ + prop = RNA_def_property(srna, "object_bases", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "base", NULL); + RNA_def_property_struct_type(prop, "ObjectBase"); + RNA_def_property_ui_text(prop, "Bases", ""); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, + "rna_Scene_layer_object_bases_lookup_string", NULL); + rna_def_layer_bases(brna, prop); + + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "base", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Objects", ""); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_Scene_layer_objects_get", NULL, NULL, NULL, NULL); + rna_def_layer_objects(brna, prop); /* Nestled Data */ rna_def_layer_collection(brna); |