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. ;)
This commit is contained in:
Bastien Montagne 2019-06-10 11:06:16 +02:00
parent f11929c145
commit 8aa87972ca
Notes: blender-bot 2023-02-14 06:20:47 +01:00
Referenced by issue #65996, metaballs converted to meshes appear to render at an incorrect isosurface
Referenced by issue #65696, Sequencer fails to create a new sound sequence strip via Python
Referenced by issue #65295, Regression: Converting a curve to mesh does not take the use of a bevel object into account when you have Keep Original checked in the Redo Panel.
Referenced by issue #53498, baking normal map using cycles does not support custom vertex normals on the baking target mesh
1 changed files with 22 additions and 7 deletions

View File

@ -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;