From 8aa87972cac3c9c3c5439b68b62e25c3fd4c4919 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 10 Jun 2019 11:06:16 +0200 Subject: Fix T65295: Convert curve to mesh fails with Keep Original. This code now expects to wrok from fully evaluated data, however when we keep original, we are actually working from data just copied from orig one. Ideally, we'd do a single depsgraph update/eval *after* we have created all new required data, but that is tricky to do properly in that code without risking breaking one thing or another. So for now, just going for the simple, if not optimal solution, and just repeatedly re-evaluating whole deg every time we duplicate an object to be converted. Yep, dummy, but simple and... safe. ;) --- source/blender/editors/object/object_add.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'source/blender/editors/object/object_add.c') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 2881163574b..0b9ced84a59 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -2009,7 +2009,7 @@ static bool convert_poll(bContext *C) /* Helper for convert_exec */ static Base *duplibase_for_convert( - Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob) + Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob) { Object *obn; Base *basen; @@ -2019,12 +2019,27 @@ static Base *duplibase_for_convert( } obn = BKE_object_copy(bmain, ob); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); BKE_collection_object_add_from(bmain, scene, ob, obn); basen = BKE_view_layer_base_find(view_layer, obn); ED_object_base_select(basen, BA_SELECT); ED_object_base_select(base, BA_DESELECT); + + /* XXX Doing that here is stupid, it means we update and re-evaluate the whole depsgraph every + * time we need to duplicate an object to convert it. Even worse, this is not 100% correct, since + * we do not yet have duplicated obdata. + * However, that is a safe solution for now. Proper, longer-term solution is to refactor + * convert_exec to: + * - duplicate all data it needs to in a first loop. + * - do a single update. + * - convert data in a second loop. */ + DEG_graph_tag_relations_update(depsgraph); + CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask; + CustomData_MeshMasks_update(&scene->customdata_mask, &CD_MASK_MESH); + BKE_scene_graph_update_tagged(depsgraph, bmain); + scene->customdata_mask = customdata_mask_prev; + return basen; } @@ -2131,7 +2146,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -2156,7 +2171,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -2186,7 +2201,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; /* decrement original curve's usage count */ @@ -2261,7 +2276,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (target == OB_MESH) { if (keep_original) { - basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); newob = basen->object; /* decrement original curve's usage count */ @@ -2296,7 +2311,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (!(baseob->flag & OB_DONE)) { baseob->flag |= OB_DONE; - basen = duplibase_for_convert(bmain, scene, view_layer, base, baseob); + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, baseob); newob = basen->object; mb = newob->data; -- cgit v1.2.3