From 8be2a86ce176a7bd89f0ebf8d29aa4d0d15ba9be Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Sun, 1 Mar 2009 06:23:22 +0000 Subject: [PATCH] split dissolve_disk into dissolve_vert dissolve_disk as agreed. also made dissolve vert bmop use the error api, and put in some code to report it to the user in the xkey ui code. I'm not sure how this should work; I don't think we can have utility code in bmesh/ for reporting errors to the user, so it'll have to go in editors/mesh somewhere. --- source/blender/bmesh/bmesh.h | 7 ++- source/blender/bmesh/intern/bmesh_mods.c | 47 +++++++++++---- source/blender/bmesh/intern/bmesh_operators.c | 3 +- source/blender/bmesh/intern/bmesh_polygon.c | 23 ++++--- .../blender/bmesh/intern/editmesh_to_bmesh.c | 15 +++++ source/blender/bmesh/operators/dissolveops.c | 6 +- source/blender/bmesh/operators/extrudeops.c | 2 + source/blender/editors/mesh/editmesh_tools.c | 60 +++++++++---------- 8 files changed, 111 insertions(+), 52 deletions(-) diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 5b1753a9902..f581e4b1054 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -195,7 +195,12 @@ void BM_Collapse_Vert(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv, fl struct BMVert *BM_Split_Edge(struct BMesh *bm, struct BMVert *v, struct BMEdge *e, struct BMEdge **ne, float percent, int calcnorm); struct BMVert *BM_Split_Edge_Multi(struct BMesh *bm, struct BMEdge *e, int numcuts); BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf); -void BM_Dissolve_Disk(BMesh *bm, BMVert *v); + +/*dissolves vert surrounded by faces*/ +int BM_Dissolve_Disk(BMesh *bm, BMVert *v); + +/*dissolves vert, in more situations then BM_Dissolve_Disk.*/ +int BM_Dissolve_Vert(BMesh *bm, BMVert *v); /*Interpolation*/ void BM_Data_Interp_From_Verts(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, float fac); diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index ce59856f823..e7e0a2e5b24 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -40,19 +40,45 @@ * */ #if 1 -void BM_Dissolve_Disk(BMesh *bm, BMVert *v) { - BMFace *f, *f2; - BMEdge *e, *keepedge=NULL, *baseedge=NULL; - BMLoop *loop; - int done, len; +int BM_Dissolve_Vert(BMesh *bm, BMVert *v) { + BMIter iter; + BMEdge *e; + int len=0; + + if (!v) return 0; + + e = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v); + for (; e; e=BMIter_Step(&iter)) { + len++; + } + + if (len == 1) { + bmesh_ke(bm, v->edge); + bmesh_kv(bm, v); + return 1; + } if(BM_Nonmanifold_Vert(bm, v)) { if (!v->edge) bmesh_kv(bm, v); else if (!v->edge->loop) { bmesh_ke(bm, v->edge); bmesh_kv(bm, v); - } - return; + } else return 0; + + return 1; + } + + return BM_Dissolve_Disk(bm, v); +} + +int BM_Dissolve_Disk(BMesh *bm, BMVert *v) { + BMFace *f, *f2; + BMEdge *e, *keepedge=NULL, *baseedge=NULL; + BMLoop *loop; + int done, len; + + if(BM_Nonmanifold_Vert(bm, v)) { + return 0; } if(v->edge){ @@ -88,9 +114,6 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) { /*collapse the vertex*/ BM_Collapse_Vert(bm, v->edge, v, 1.0, 0); BM_Join_Faces(bm, f, f2, NULL, 0, 0); - } else if (len == 1) { - bmesh_ke(bm, v->edge); - bmesh_kv(bm, v); } if(keepedge){ @@ -106,7 +129,7 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) { /*return if couldn't join faces in manifold conditions.*/ //!disabled for testing why bad things happen - if (!f) return; + if (!f) return 0; } if(f){ @@ -126,6 +149,8 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) { /*join two remaining faces*/ BM_Join_Faces(bm, f, f2, NULL, 0, 0); } + + return 1; } #else void BM_Dissolve_Disk(BMesh *bm, BMVert *v){ diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index ca10129b4ab..3e2c3d9c4aa 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -800,6 +800,7 @@ void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, char *msg) bmop_error *err = MEM_callocN(sizeof(bmop_error), "bmop_error"); err->errorcode = errcode; + if (!msg) msg = bmop_error_messages[errcode]; err->msg = msg; err->op = owner; @@ -825,7 +826,7 @@ int BMO_PopError(BMesh *bm, char **msg, BMOperator **op) if (errorcode) { bmop_error *err = bm->errorstack.first; - BLI_remlink(&bm->errorstack, &bm->errorstack.first); + BLI_remlink(&bm->errorstack, bm->errorstack.first); MEM_freeN(err); } diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 73f713c5591..f4fcd607d27 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -339,11 +339,10 @@ int linecrosses(float *v1, float *v2, float *v3, float *v4) return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5; } -int goodline(float (*projectverts)[3], int v1i, int v2i, int nvert) +int goodline(float (*projectverts)[3], int v1i, int v2i, int nvert, float *outv) { - /*the hardcoded stuff here, 200000, 0.999, and 1.0001 may be problems + /*the hardcoded stuff here, 0.999 and 1.0001, may be problems in the future, not sure. - joeedh*/ - static float outv[3] = {2000.0f, 2000.0f, 0.0f}; float v1[3], v2[3], p[3], vv1[3], vv2[3], mid[3], a[3], b[3]; int i = 0, lcount=0; @@ -398,7 +397,7 @@ int goodline(float (*projectverts)[3], int v1i, int v2i, int nvert) * */ -static BMLoop *find_ear(BMFace *f, float (*verts)[3], int nvert) +static BMLoop *find_ear(BMFace *f, float (*verts)[3], int nvert, float *outv) { BMVert *v1, *v2, *v3; BMLoop *bestear = NULL, *l; @@ -415,12 +414,13 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], int nvert) if (BM_Edge_Exist(v1, v3)) isear = 0; - if (isear && !goodline(verts, v1->head.eflag2, v3->head.eflag2, nvert)) isear = 0; + if (isear && !goodline(verts, v1->head.eflag2, v3->head.eflag2, + nvert, outv)) isear = 0; if(isear){ angle = VecAngle3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]); - if(!bestear || ABS(angle-40.0) < bestangle){ + if(!bestear || ABS(angle-40.0f) < bestangle){ bestear = l; - bestangle = ABS(40.0-angle); + bestangle = ABS(40.0f-angle); } } l = (BMLoop*)(l->head.next); @@ -450,6 +450,7 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new { int i, done, nvert; BMLoop *l, *newl, *nextloop; + float outv[3] = {-1.0e30f, -1.0e30f, -1.0e30f}; /*copy vertex coordinates to vertspace array*/ i = 0; @@ -458,9 +459,15 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new VECCOPY(projectverts[i], l->v->co); l->v->head.eflag2 = i; /*warning, abuse! never duplicate in tools code! never you hear?*/ /*actually, get rid of this completely, use a new structure for this....*/ i++; + + outv[0] = MAX2(outv[0], l->v->co[0])+1.0f; + outv[1] = MAX2(outv[1], l->v->co[1])+1.0f; + outv[2] = MAX2(outv[2], l->v->co[2])+1.0f; + l = (BMLoop*)(l->head.next); }while(l != f->loopbase); + //bmesh_update_face_normal(bm, f, projectverts); compute_poly_normal(f->no, projectverts, f->len); @@ -472,7 +479,7 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new done = 0; while(!done && f->len > 3){ done = 1; - l = find_ear(f, projectverts, nvert); + l = find_ear(f, projectverts, nvert, outv); if(l) { done = 0; f = bmesh_sfme(bm, f, ((BMLoop*)(l->head.prev))->v, ((BMLoop*)(l->head.next))->v, &newl); diff --git a/source/blender/bmesh/intern/editmesh_to_bmesh.c b/source/blender/bmesh/intern/editmesh_to_bmesh.c index 12b5f55f9ee..dfe97297161 100644 --- a/source/blender/bmesh/intern/editmesh_to_bmesh.c +++ b/source/blender/bmesh/intern/editmesh_to_bmesh.c @@ -259,8 +259,23 @@ static void fuse_fgon(BMesh *bm, BMFace *f) static BM_fgonconvert(BMesh *bm, EditMesh *em, int numCol, int numTex) { EditFace *efa; + BMFace *f; + BMIter iter; struct fgonsort *sortblock, *sb, *sb1; int a, b, amount=0; + + /* + for (efa=em->faces.first; efa; efa=efa->next) { + f = editface_to_BMFace(bm, em, efa, numCol, numTex); + } + + for (f=bm->polys.first; f; f=f->head.next) { + fuse_fgon(bm, f); + } + + return;*/ + + EM_fgon_flags(em); /*zero out efa->tmp, we store fgon index here*/ for(efa = em->faces.first; efa; efa = efa->next){ diff --git a/source/blender/bmesh/operators/dissolveops.c b/source/blender/bmesh/operators/dissolveops.c index c9e29c9f94a..c4a59116b00 100644 --- a/source/blender/bmesh/operators/dissolveops.c +++ b/source/blender/bmesh/operators/dissolveops.c @@ -85,7 +85,11 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op) len = 0; for (v=BMIter_New(&iter, bm, BM_VERTS, NULL); v; v=BMIter_Step(&iter)) { if (BMO_TestFlag(bm, v, VERT_MARK)) { - BM_Dissolve_Disk(bm, v); + if (!BM_Dissolve_Vert(bm, v)) { + BMO_RaiseError(bm, op, + BMERR_DISSOLVEDISK_FAILED, NULL); + return; + } found = 1; len++; } diff --git a/source/blender/bmesh/operators/extrudeops.c b/source/blender/bmesh/operators/extrudeops.c index 81776d673e7..dcc5d70e04e 100644 --- a/source/blender/bmesh/operators/extrudeops.c +++ b/source/blender/bmesh/operators/extrudeops.c @@ -33,6 +33,8 @@ void extrude_edge_context_exec(BMesh *bm, BMOperator *op) #if 1 for (e=BMIter_New(&iter, bm, BM_EDGES, NULL);e;e=BMIter_Step(&iter)) { + if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue; + found = 0; f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e); for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 3bc59fe9094..7a617e6d340 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1102,15 +1102,30 @@ static void erase_vertices(EditMesh *em, ListBase *l) } } -void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event) +/* Note, these values must match delete_mesh() event values */ +static EnumPropertyItem prop_mesh_delete_types[] = { + {10,"VERT", "Vertices", ""}, + {1, "EDGE", "Edges", ""}, + {2, "FACE", "Faces", ""}, + {3, "ALL", "All", ""}, + {4, "EDGE_FACE","Edges & Faces", ""}, + {5, "ONLY_FACE","Only Faces", ""}, + {6, "EDGE_LOOP","Edge Loop", ""}, + {7, "COLLAPSE","Collapse", ""}, + {0, NULL, NULL, NULL} +}; + +static int delete_mesh_exec(bContext *C, wmOperator *op) { + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= ((Mesh *)obedit->data)->edit_mesh; EditFace *efa, *nextvl; EditVert *eve,*nextve; EditEdge *eed,*nexted; int count; char *str="Erase"; + int event = RNA_enum_get(op->ptr, "type"); - if(event<1) return; if(event==10 ) { @@ -1121,19 +1136,27 @@ void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event) } else if(event==7) { BMesh *bm = editmesh_to_bmesh(em); - BMOperator op; + BMOperator bmop; EditMesh *em2; + char *errmsg; - BMO_Init_Op(&op, BMOP_DISSOLVE_VERTS); - BMO_HeaderFlag_To_Slot(bm, &op, BMOP_DISVERTS_VERTIN, + BMO_Init_Op(&bmop, BMOP_DISSOLVE_VERTS); + BMO_HeaderFlag_To_Slot(bm, &bmop, BMOP_DISVERTS_VERTIN, BM_SELECT, BM_VERT); - BMO_Exec_Op(bm, &op); + BMO_Exec_Op(bm, &bmop); - BMO_Finish_Op(bm, &op); + BMO_Finish_Op(bm, &bmop); + if (BMO_GetError(bm, &errmsg, NULL)) { + BKE_report(op->reports, RPT_ERROR, errmsg); + BMO_ClearStack(bm); + return OPERATOR_CANCELLED; + } + em2 = bmesh_to_editmesh(bm); set_editMesh(em, em2); MEM_freeN(em2); + BM_Free_Mesh(bm); } else if(event==6) { if(!EdgeLoopDelete(em, op)) @@ -1254,29 +1277,6 @@ void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event) EM_fgon_flags(em); // redo flags and indices for fgons -// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); -} - -/* Note, these values must match delete_mesh() event values */ -static EnumPropertyItem prop_mesh_delete_types[] = { - {10,"VERT", "Vertices", ""}, - {1, "EDGE", "Edges", ""}, - {2, "FACE", "Faces", ""}, - {3, "ALL", "All", ""}, - {4, "EDGE_FACE","Edges & Faces", ""}, - {5, "ONLY_FACE","Only Faces", ""}, - {6, "EDGE_LOOP","Edge Loop", ""}, - {7, "COLLAPSE","Collapse", ""}, - {0, NULL, NULL, NULL} -}; - -static int delete_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= ((Mesh *)obedit->data)->edit_mesh; - - delete_mesh(obedit,em, op,RNA_enum_get(op->ptr, "type")); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); return OPERATOR_FINISHED;