Fix for convert_exec()

"Keep original" option now works for all objects' types
This commit is contained in:
2010-03-07 05:04:22 +00:00
parent 8e35d91985
commit 3ad1bfa69e
2 changed files with 176 additions and 80 deletions

View File

@@ -1036,7 +1036,7 @@ void mesh_to_curve(Scene *scene, Object *ob)
int totedge = dm->getNumEdges(dm);
int totface = dm->getNumFaces(dm);
int totedges = 0;
int i;
int i, needsFree = 0;
/* only to detect edge polylines */
EdgeHash *eh = BLI_edgehash_new();
@@ -1176,9 +1176,17 @@ void mesh_to_curve(Scene *scene, Object *ob)
((Mesh *)ob->data)->id.us--;
ob->data= cu;
ob->type= OB_CURVE;
/* curve objects can't contain DM in usual cases, we could free memory */
needsFree= 1;
}
dm->needsFree = needsFree;
dm->release(dm);
if (needsFree) {
ob->derivedFinal = NULL;
}
}
void mesh_delete_material_index(Mesh *me, int index)

View File

@@ -1191,11 +1191,36 @@ static int convert_poll(bContext *C)
return (!scene->id.lib && obact && scene->obedit != obact && (obact->flag & SELECT) && !(obact->id.lib));
}
/* Helper for convert_exec */
static Base *duplibase_for_convert(Scene *scene, Base *base, Object *ob)
{
Object *obn;
Base *basen;
if (ob == NULL) {
ob= base->object;
}
obn= copy_object(ob);
obn->recalc |= OB_RECALC;
basen= MEM_mallocN(sizeof(Base), "duplibase");
*basen= *base;
BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
basen->object= obn;
basen->flag |= SELECT;
obn->flag |= SELECT;
base->flag &= ~SELECT;
ob->flag &= ~SELECT;
return basen;
}
static int convert_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Base *basen=NULL, *basact=NULL, *basedel=NULL;
Object *ob, *ob1, *obact= CTX_data_active_object(C);
Object *ob, *ob1, *newob, *obact= CTX_data_active_object(C);
DerivedMesh *dm;
Curve *cu;
Nurb *nu;
@@ -1203,7 +1228,7 @@ static int convert_exec(bContext *C, wmOperator *op)
Mesh *me;
int target= RNA_enum_get(op->ptr, "target");
int keep_original= RNA_boolean_get(op->ptr, "keep_original");
int a;
int a, mballConverted= 0;
/* don't forget multiple users! */
@@ -1216,67 +1241,86 @@ static int convert_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
ob= base->object;
if(ob->flag & OB_DONE)
continue;
if(ob->flag & OB_DONE) {
if (ob->type != target) {
base->flag &= ~SELECT;
ob->flag &= ~SELECT;
}
}
else if (ob->type==OB_MESH && target == OB_CURVE) {
ob->flag |= OB_DONE;
ob1= copy_object(ob);
ob1->recalc |= OB_RECALC;
if (keep_original) {
basen= duplibase_for_convert(scene, base, NULL);
newob= basen->object;
basen= MEM_mallocN(sizeof(Base), "duplibase");
*basen= *base;
BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
basen->object= ob1;
basen->flag |= SELECT;
base->flag &= ~SELECT;
ob->flag &= ~SELECT;
/* decrement original mesh's usage count */
me= newob->data;
me->id.us--;
mesh_to_curve(scene, ob1);
/* make a new copy of the mesh */
newob->data= copy_mesh(me);
} else {
newob = ob;
}
if(ob1->type==OB_CURVE)
object_free_modifiers(ob1); /* after derivedmesh calls! */
mesh_to_curve(scene, newob);
if(newob->type==OB_CURVE)
object_free_modifiers(newob); /* after derivedmesh calls! */
}
else if(ob->type==OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */
ob->flag |= OB_DONE;
basedel = base;
ob1= copy_object(ob);
ob1->recalc |= OB_RECALC;
if (keep_original) {
basen= duplibase_for_convert(scene, base, NULL);
newob= basen->object;
basen= MEM_mallocN(sizeof(Base), "duplibase");
*basen= *base;
BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
basen->object= ob1;
basen->flag |= SELECT;
base->flag &= ~SELECT;
ob->flag &= ~SELECT;
/* decrement original mesh's usage count */
me= newob->data;
me->id.us--;
/* decrement original mesh's usage count */
me= ob1->data;
me->id.us--;
/* make a new copy of the mesh */
ob1->data= copy_mesh(me);
/* make a new copy of the mesh */
newob->data= copy_mesh(me);
} else {
newob = ob;
}
/* make new mesh data from the original copy */
/* note: get the mesh from the original, not from the copy in some
* cases this doesnt give correct results (when MDEF is used for eg)
*/
dm= mesh_get_derived_final(scene, ob, CD_MASK_MESH);
dm= mesh_get_derived_final(scene, newob, CD_MASK_MESH);
/* dm= mesh_create_derived_no_deform(ob1, NULL); this was called original (instead of get_derived). man o man why! (ton) */
DM_to_mesh(dm, ob1->data);
DM_to_mesh(dm, newob->data);
dm->release(dm);
object_free_modifiers(ob1); /* after derivedmesh calls! */
object_free_modifiers(newob); /* after derivedmesh calls! */
}
else if(ob->type==OB_FONT) {
ob->flag |= OB_DONE;
ob->type= OB_CURVE;
cu= ob->data;
if (keep_original) {
basen= duplibase_for_convert(scene, base, NULL);
newob= basen->object;
/* decrement original curve's usage count */
((Curve *)newob->data)->id.us--;
/* make a new copy of the curve */
newob->data= copy_curve(ob->data);
} else {
newob= ob;
}
cu= newob->data;
if (!cu->disp.first)
makeDispListCurveTypes(scene, newob, 0);
newob->type= OB_CURVE;
if(cu->vfont) {
cu->vfont->id.us--;
@@ -1293,13 +1337,16 @@ static int convert_exec(bContext *C, wmOperator *op)
if(cu->vfontbi) {
cu->vfontbi->id.us--;
cu->vfontbi= 0;
}
/* other users */
if(cu->id.us>1) {
for(ob1= G.main->object.first; ob1; ob1=ob1->id.next) {
if(ob1->data==cu) {
ob1->type= OB_CURVE;
ob1->recalc |= OB_RECALC;
}
if (!keep_original) {
/* other users */
if(cu->id.us>1) {
for(ob1= G.main->object.first; ob1; ob1=ob1->id.next) {
if(ob1->data==ob->data) {
ob1->type= OB_CURVE;
ob1->recalc |= OB_RECALC;
}
}
}
}
@@ -1308,46 +1355,76 @@ static int convert_exec(bContext *C, wmOperator *op)
nu->charidx= 0;
if(target == OB_MESH)
curvetomesh(scene, ob);
curvetomesh(scene, newob);
}
else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
ob->flag |= OB_DONE;
if(target == OB_MESH)
curvetomesh(scene, ob);
if(target == OB_MESH) {
if (keep_original) {
basen= duplibase_for_convert(scene, base, NULL);
newob= basen->object;
/* decrement original curve's usage count */
((Curve *)newob->data)->id.us--;
/* make a new copy of the curve */
newob->data= copy_curve(ob->data);
} else {
newob= ob;
}
curvetomesh(scene, newob);
}
}
else if(ob->type==OB_MBALL) {
ob= find_basis_mball(scene, ob);
if(ob->disp.first && !(ob->flag & OB_DONE)) {
Object *baseob;
if (target != OB_MESH) {
ob->flag |= OB_DONE;
basedel = base;
continue;
}
ob1= copy_object(ob);
ob1->recalc |= OB_RECALC;
base->flag &= ~SELECT;
ob->flag &= ~SELECT;
basen= MEM_mallocN(sizeof(Base), "duplibase");
*basen= *base;
BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
basen->object= ob1;
basen->flag |= SELECT;
basedel->flag &= ~SELECT;
ob->flag &= ~SELECT;
mb= ob1->data;
baseob= find_basis_mball(scene, ob);
if (ob != baseob) {
/* if motherball is converting it would be marked as done later */
ob->flag |= OB_DONE;
}
if (!baseob->disp.first) {
makeDispListMBall(scene, baseob);
}
if(!(baseob->flag & OB_DONE)) {
baseob->flag |= OB_DONE;
basen= duplibase_for_convert(scene, base, baseob);
newob= basen->object;
mb= newob->data;
mb->id.us--;
ob1->data= add_mesh("Mesh");
ob1->type= OB_MESH;
me= ob1->data;
newob->data= add_mesh("Mesh");
newob->type= OB_MESH;
me= newob->data;
me->totcol= mb->totcol;
if(ob1->totcol) {
if(newob->totcol) {
me->mat= MEM_dupallocN(mb->mat);
for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
for(a=0; a<newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
}
mball_to_mesh(&ob->disp, ob1->data);
mball_to_mesh(&baseob->disp, newob->data);
if (obact->type == OB_MBALL) {
basact= basen;
}
mballConverted= 1;
}
else
continue;
@@ -1358,8 +1435,6 @@ static int convert_exec(bContext *C, wmOperator *op)
/* If the original object is active then make this object active */
if(basen) {
if(ob == obact) {
ED_base_object_activate(C, basen);
/* store new active base to update BASACT */
basact= basen;
}
@@ -1376,24 +1451,37 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
/* delete object should renew depsgraph */
if(!keep_original)
if(!keep_original) {
if (mballConverted) {
Base *base= scene->base.first, *tmpbase;
while (base) {
ob= base->object;
tmpbase= base;
base= base->next;
if (ob->type == OB_MBALL) {
ED_base_object_free_and_unlink(scene, tmpbase);
}
}
}
/* delete object should renew depsgraph */
DAG_scene_sort(scene);
}
// XXX ED_object_enter_editmode(C, 0);
// XXX exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
if (basact) {
/* active base was changed */
ED_base_object_activate(C, basact);
BASACT= basact;
}
DAG_scene_sort(scene);
WM_event_add_notifier(C, NC_SCENE|NC_OBJECT|ND_DRAW, scene); /* is NC_SCENE needed ? */
return OPERATOR_FINISHED;
}