diff options
author | Joseph Eagar <joeedh@gmail.com> | 2009-08-22 08:45:19 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2009-08-22 08:45:19 +0400 |
commit | 8151a5168422d6b1f974d238f37707f7bc507db7 (patch) | |
tree | 91460edcb532deeb97646fe51f03e5fefe3ed290 /source | |
parent | 1aeb5a6925322faca0fe263c9cf822dfa545e3ab (diff) |
Shift-G (select similar) is now bmeshafied for face select mode.
The patch was by Wael El Oraiby, who did a great job on it.
Yay for Wael! Commit of patch #19242.
There's also some CCGSubSurf stuff mixed in with this, though it's
still not working right (fixed tons of bugs, just the main ones
for some reason are still there, despite their original causes
being fixed :-/).
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifiers_bmesh.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 70 | ||||
-rw-r--r-- | source/blender/bmesh/bmesh_operators.h | 9 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 17 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators_private.h | 1 | ||||
-rw-r--r-- | source/blender/bmesh/operators/utils.c | 261 | ||||
-rw-r--r-- | source/blender/editors/mesh/bmesh_select.c | 179 |
9 files changed, 366 insertions, 190 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index ca6dc9407ff..f1117a967fd 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -285,7 +285,7 @@ void dm_add_polys_from_iter(CustomData *ldata, CustomData *pdata, DerivedMesh *d CustomData *oldata, *opdata; MPoly *mpoly; MLoop *mloop; - int l, i, j, lasttype; + int p, l, i, j, lasttype; oldata = dm->getLoopDataLayout(dm); opdata = dm->getFaceDataLayout(dm); @@ -299,7 +299,7 @@ void dm_add_polys_from_iter(CustomData *ldata, CustomData *pdata, DerivedMesh *d CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, dm->getNumFaces(dm)); l = 0; - for (; !iter->done; iter->step(iter), mpoly++) { + for (p=0; !iter->done; iter->step(iter), mpoly++, p++) { mpoly->flag = iter->flags; mpoly->loopstart = l; mpoly->totloop = iter->len; @@ -314,7 +314,10 @@ void dm_add_polys_from_iter(CustomData *ldata, CustomData *pdata, DerivedMesh *d continue; e1 = iter->getCDData(iter, opdata->layers[i].type, j); - e2 = CustomData_get_layer_n(pdata, opdata->layers[i].type, j); + e2 = (char*)CustomData_get_n(pdata, opdata->layers[i].type, p, j); + + if (!e2) + continue; CustomData_copy_elements(opdata->layers[i].type, e1, e2, 1); @@ -340,7 +343,10 @@ void dm_add_polys_from_iter(CustomData *ldata, CustomData *pdata, DerivedMesh *d continue; e1 = liter->getLoopCDData(liter, oldata->layers[i].type, j); - e2 = CustomData_get_layer_n(ldata, oldata->layers[i].type, j); + e2 = CustomData_get_n(ldata, oldata->layers[i].type, l, j); + + if (!e2) + continue; CustomData_copy_elements(oldata->layers[i].type, e1, e2, 1); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 72c3e3b0188..9dc8edb932e 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1644,7 +1644,7 @@ void *CustomData_get_n(const CustomData *data, int type, int index, int n) if(layer_index < 0) return NULL; offset = layerType_getInfo(type)->size * index; - return (char *)data->layers[layer_index].data + offset; + return (char *)data->layers[layer_index+n].data + offset; } void *CustomData_get_layer(const CustomData *data, int type) diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index f69e0efcea6..74a6e920d69 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -193,6 +193,9 @@ BMEditMesh *CDDM_To_BMesh(DerivedMesh *dm, BMEditMesh *existing) verts[j] = vtable[dliter->vindex]; edges[j] = etable[dliter->eindex]; } + + if (j < 2) + break; f = BM_Make_Ngon(bm, verts[0], verts[1], edges, dfiter->len, 0); f->head.flag = MEFlags_To_BMFlags(dfiter->flags, BM_FACE); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index ba53bbe7767..34e517dcf3c 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1460,6 +1460,7 @@ struct cgdm_faceIter; typedef struct cgdm_loopIter { DMLoopIter head; int curloop; + int lindex; //loop index within the mesh, not the face CCGDerivedMesh *cgdm; struct cgdm_faceIter *fiter; } cgdm_loopIter; @@ -1493,7 +1494,7 @@ void cgdm_faceIterStep(void *self) fiter->head.flags = fiter->mface.flag; fiter->head.mat_nr = fiter->mface.mat_nr; - fiter->head.len = fiter->mface.v4 ? 4 : 3; + fiter->head.len = 4; } void *cgdm_faceIterCData(void *self, int type, int layer) @@ -1501,9 +1502,9 @@ void *cgdm_faceIterCData(void *self, int type, int layer) cgdm_faceIter *fiter = self; if (layer == -1) - return CustomData_get(&fiter->cgdm->dm.faceData, fiter->head.index, type); + return CustomData_get(&fiter->cgdm->dm.polyData, fiter->head.index, type); else - return CustomData_get_n(&fiter->cgdm->dm.faceData, type, fiter->head.index, layer); + return CustomData_get_n(&fiter->cgdm->dm.polyData, type, fiter->head.index, layer); } void cgdm_loopIterStep(void *self) @@ -1512,14 +1513,14 @@ void cgdm_loopIterStep(void *self) MFace *mf = &liter->fiter->mface; int i, v1, v2; - if (liter->head.index >= liter->fiter->head.len) { + liter->head.index++; + i = liter->head.index; + + if (liter->head.index >= 4) { liter->head.done = 1; return; } - liter->head.index++; - i = liter->head.index; - switch (i) { case 0: v1 = liter->fiter->mface.v1; @@ -1541,6 +1542,7 @@ void cgdm_loopIterStep(void *self) liter->head.vindex = v1; liter->head.eindex = GET_INT_FROM_POINTER(BLI_edgehash_lookup(liter->fiter->ehash, v1, v2)); + liter->lindex += 1; cgdm_getFinalVert((DerivedMesh*)liter->cgdm, v1, &liter->head.v); } @@ -1557,10 +1559,10 @@ void *cgdm_loopIterGetVCData(void *self, int type, int layer) void *cgdm_loopIterGetCData(void *self, int type, int layer) { cgdm_loopIter *liter = self; - - /*BMESH_TODO - yeek, this has to convert mface-style uv/mcols to loop-style*/ - return NULL; + + if (layer == -1) + return CustomData_get(&liter->cgdm->dm.loopData, liter->lindex, type); + else return CustomData_get_n(&liter->cgdm->dm.loopData, type, liter->lindex, layer); } DMLoopIter *cgdm_faceIterGetLIter(void *self) @@ -1587,6 +1589,8 @@ DMFaceIter *cgdm_newFaceIter(DerivedMesh *dm) MEdge medge; int i, totedge = cgdm_getNumEdges(dm); + fiter->cgdm = dm; + fiter->liter.cgdm = dm; fiter->ehash = BLI_edgehash_new(); for (i=0; i<totedge; i++) { @@ -1604,6 +1608,7 @@ DMFaceIter *cgdm_newFaceIter(DerivedMesh *dm) fiter->liter.head.getLoopCDData = cgdm_loopIterGetCData; fiter->liter.head.getVertCDData = cgdm_loopIterGetVCData; fiter->liter.head.step = cgdm_loopIterStep; + fiter->liter.lindex = -1; fiter->head.step(fiter); } @@ -2627,7 +2632,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CSubSurf *ss, int numTex, numCol; int gridInternalEdges; int index2; - float *w = NULL; + float *w = NULL, one = 1.0f; WeightTable wtable = {0}; V_DECLARE(w); /* MVert *mvert = NULL; - as yet unused */ @@ -2864,12 +2869,13 @@ static CCGDerivedMesh *getCCGDerivedMesh(CSubSurf *ss, loopindex2++; /*copy over poly data, e.g. mtexpoly*/ - CustomData_interp(&dm->polyData, &cgdm->dm.polyData, &origIndex, w, NULL, 1, index2); + CustomData_interp(&dm->polyData, &cgdm->dm.polyData, &origIndex, &one, NULL, 1, index2); /*generate tesselated face data used for drawing*/ ccg_loops_to_corners(&cgdm->dm.faceData, &cgdm->dm.loopData, &cgdm->dm.polyData, loopindex2-4, index2, index2, numTex, numCol); + faceNum++; index2++; } } @@ -2878,25 +2884,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CSubSurf *ss, edgeNum += numFinalEdges; } - for(index = 0; index < totvert; ++index) { - CCVert *v = cgdm->vertMap[index].vert; - int mapIndex = cgdm_getVertMapIndex(cgdm->ss, v); - int vidx; - - vidx = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v)); - - cgdm->vertMap[index].startVert = vertNum; - - /* set the vert base vert */ - *((int*) CCS_getVertUserData(ss, v)) = vertNum; - - DM_copy_vert_data(dm, &cgdm->dm, vidx, vertNum, 1); - - *vertOrigIndex = mapIndex; - ++vertOrigIndex; - ++vertNum; - } - edgeFlags = DM_get_edge_data_layer(&cgdm->dm, CD_FLAGS); for(index = 0; index < totedge; ++index) { CCEdge *e = cgdm->edgeMap[index].edge; @@ -2938,6 +2925,25 @@ static CCGDerivedMesh *getCCGDerivedMesh(CSubSurf *ss, edgeNum += numFinalEdges; } + + for(index = 0; index < totvert; ++index) { + CCVert *v = cgdm->vertMap[index].vert; + int mapIndex = cgdm_getVertMapIndex(cgdm->ss, v); + int vidx; + + vidx = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v)); + + cgdm->vertMap[index].startVert = vertNum; + + /* set the vert base vert */ + *((int*) CCS_getVertUserData(ss, v)) = vertNum; + + DM_copy_vert_data(dm, &cgdm->dm, vidx, vertNum, 1); + + *vertOrigIndex = mapIndex; + ++vertOrigIndex; + ++vertNum; + } #if 0 for(index = 0; index < totface; ++index) { CCFace *f = cgdm->faceMap[index].face; diff --git a/source/blender/bmesh/bmesh_operators.h b/source/blender/bmesh/bmesh_operators.h index 2db5a179c45..5879765de0b 100644 --- a/source/blender/bmesh/bmesh_operators.h +++ b/source/blender/bmesh/bmesh_operators.h @@ -22,6 +22,15 @@ enum { SUBD_STRAIGHT_CUT, }; +enum { + SIMFACE_MATERIAL = 201, + SIMFACE_IMAGE, + SIMFACE_AREA, + SIMFACE_PERIMETER, + SIMFACE_NORMAL, + SIMFACE_COPLANAR, +}; + extern BMOpDefine *opdefines[]; extern int bmesh_total_ops; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index ade680b62b2..e5e7da115c4 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -613,6 +613,22 @@ BMOpDefine def_splitop = { 0 }; +/* + Similar faces select + + Select similar faces (area/material/perimeter....). +*/ +BMOpDefine def_similarfaces = { + "similarfaces", + {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, /* output faces */ + {BMOP_OPSLOT_INT, "type"}, /* type of selection */ + {BMOP_OPSLOT_FLT, "thresh"}, /* threshold of selection */ + {0} /*null-terminating sentinel*/}, + bmesh_similarfaces_exec, + 0 +}; + BMOpDefine *opdefines[] = { &def_splitop, &def_dupeop, @@ -653,6 +669,7 @@ BMOpDefine *opdefines[] = { &def_collapse_uvs, &def_pointmerge, &def_collapse, + &def_similarfaces, }; int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*)); diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index d030ef81fe7..6cb8b2f9cf5 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -46,5 +46,6 @@ void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op); void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op); void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op); void bmesh_collapse_exec(BMesh *bm, BMOperator *op); +void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op); #endif diff --git a/source/blender/bmesh/operators/utils.c b/source/blender/bmesh/operators/utils.c index 3aef0b7b05b..a5446112c66 100644 --- a/source/blender/bmesh/operators/utils.c +++ b/source/blender/bmesh/operators/utils.c @@ -383,3 +383,264 @@ void bmesh_vertexsmooth_exec(BMesh *bm, BMOperator *op) V_FREE(cos); } + +/* +** compute the centroid of an ngon +** +** NOTE: This should probably go to bmesh_polygon.c and replace the function that compute its center +** basing on bounding box +*/ +static void ngon_center(float *v, BMesh *bm, BMFace *f) +{ + BMIter liter; + BMLoop *l; + v[0] = v[1] = v[2] = 0; + + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) { + VecAddf(v, v, l->v->co); + } + + if( f->len ) + { + v[0] /= f->len; + v[1] /= f->len; + v[2] /= f->len; + } +} + +/* +** compute the perimeter of an ngon +** +** NOTE: This should probably go to bmesh_polygon.c +*/ +static float ngon_perimeter(BMesh *bm, BMFace *f) +{ + BMIter liter; + BMLoop *l; + int num_verts = 0; + float v[3], sv[3]; + float perimeter = 0.0f; + + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) { + if( num_verts == 0 ) { + sv[0] = v[0] = l->v->co[0]; + sv[1] = v[1] = l->v->co[1]; + sv[2] = v[2] = l->v->co[2]; + num_verts++; + } else { + perimeter += VecLenf(v, l->v->co); + v[0] = l->v->co[0]; + v[1] = l->v->co[1]; + v[2] = l->v->co[2]; + num_verts++; + } + } + + perimeter += VecLenf(v, sv); + + return perimeter; +} + +/* +** compute the fake surface of an ngon +** This is done by decomposing the ngon into triangles who share the centroid of the ngon +** while this method is far from being exact, it should garantee an invariance. +** +** NOTE: This should probably go to bmesh_polygon.c +*/ +static float ngon_fake_area(BMesh *bm, BMFace *f) +{ + BMIter liter; + BMLoop *l; + int num_verts = 0; + float v[3], sv[3], c[3]; + float area = 0.0f; + + ngon_center(c, bm, f); + + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) { + if( num_verts == 0 ) { + sv[0] = v[0] = l->v->co[0]; + sv[1] = v[1] = l->v->co[1]; + sv[2] = v[2] = l->v->co[2]; + num_verts++; + } else { + area += AreaT3Dfl(v, c, l->v->co); + v[0] = l->v->co[0]; + v[1] = l->v->co[1]; + v[2] = l->v->co[2]; + num_verts++; + } + } + + area += AreaT3Dfl(v, c, sv); + + return area; +} + +/* +** extra face data (computed data) +*/ +typedef struct tmp_face_ext { + BMFace *f; /* the face */ + float c[3]; /* center */ + union { + float area; /* area */ + float perim; /* perimeter */ + float d; /* 4th component of plane (the first three being the normal) */ + struct Image *t; /* image pointer */ + }; +} tmp_face_ext; + +/* +** Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h +** We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces +*/ +void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op) +{ + BMIter fm_iter; + BMFace *fs, *fm; + BMOIter fs_iter; + int num_tex, num_sels = 0, num_total = 0, i = 0, idx = 0; + float angle = 0.0f; + tmp_face_ext *f_ext = NULL; + int *indices = NULL; + float t_no[3]; /* temporary normal */ + int type = BMO_Get_Int(op, "type"); + float thresh = BMO_Get_Float(op, "thresh"); + + num_total = BM_Count_Element(bm, BM_FACE); + + /* + ** The first thing to do is to iterate through all the the selected items and mark them since + ** they will be in the selection anyway. + ** This will increase performance, (especially when the number of originaly selected faces is high) + ** so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, + ** and n is the total number of faces + */ + BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) { + if (!BMO_TestFlag(bm, fs, FACE_MARK)) { /* is this really needed ? */ + BMO_SetFlag(bm, fs, FACE_MARK); + num_sels++; + } + } + + /* allocate memory for the selected faces indices and for all temporary faces */ + indices = (int*)malloc(sizeof(int) * num_sels); + f_ext = (tmp_face_ext*)malloc(sizeof(tmp_face_ext) * num_total); + + /* loop through all the faces and fill the faces/indices structure */ + BM_ITER(fm, &fm_iter, bm, BM_FACES_OF_MESH, NULL) { + f_ext[i].f = fm; + if (BMO_TestFlag(bm, fm, FACE_MARK)) { + indices[idx] = i; + idx++; + } + i++; + } + + /* + ** Save us some computation burden: In case of perimeter/area/coplanar selection we compute + ** only once. + */ + if( type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE ) { + for( i = 0; i < num_total; i++ ) { + switch( type ) { + case SIMFACE_PERIMETER: + /* set the perimeter */ + f_ext[i].perim = ngon_perimeter(bm, f_ext[i].f); + break; + + case SIMFACE_COPLANAR: + /* compute the center of the polygon */ + ngon_center(f_ext[i].c, bm, f_ext[i].f); + + /* normalize the polygon normal */ + VecCopyf(t_no, f_ext[i].f->no); + Normalize(t_no); + + /* compute the plane distance */ + f_ext[i].d = Inpf(t_no, f_ext[i].c); + break; + + case SIMFACE_AREA: + f_ext[i].area = ngon_fake_area(bm, f_ext[i].f); + break; + + case SIMFACE_IMAGE: + f_ext[i].t = NULL; + if( CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY) ) { + MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY); + f_ext[i].t = mtpoly->tpage; + } + break; + } + } + } + + /* now select the rest (if any) */ + //BM_ITER(fm, &fm_iter, bm, BM_FACES_OF_MESH, NULL) { + for( i = 0; i < num_total; i++ ) { + fm = f_ext[i].f; + if (!BMO_TestFlag(bm, fm, FACE_MARK)) { + //BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) { + int cont = 1; + for( idx = 0; idx < num_sels && cont == 1; idx++ ) { + fs = f_ext[indices[idx]].f; + switch( type ) { + case SIMFACE_MATERIAL: + if( fm->mat_nr == fs->mat_nr ) { + BMO_SetFlag(bm, fm, FACE_MARK); + cont = 0; + } + break; + + case SIMFACE_IMAGE: + if( f_ext[i].t == f_ext[indices[idx]].t ) { + BMO_SetFlag(bm, fm, FACE_MARK); + cont = 0; + } + break; + + case SIMFACE_NORMAL: + angle = VecAngle2(fs->no, fm->no); /* if the angle between the normals -> 0 */ + if( angle / 180.0 <= thresh ) { + BMO_SetFlag(bm, fm, FACE_MARK); + cont = 0; + } + break; + + case SIMFACE_COPLANAR: + angle = VecAngle2(fs->no, fm->no); /* angle -> 0 */ + if( angle / 180.0 <= thresh ) { /* and dot product difference -> 0 */ + if( fabs(f_ext[i].d - f_ext[indices[idx]].d) <= thresh ) { + BMO_SetFlag(bm, fm, FACE_MARK); + cont = 0; + } + } + break; + + case SIMFACE_AREA: + if( fabs(f_ext[i].area - f_ext[indices[idx]].area) <= thresh ) { + BMO_SetFlag(bm, fm, FACE_MARK); + cont = 0; + } + break; + + case SIMFACE_PERIMETER: + if( fabs(f_ext[i].perim - f_ext[indices[idx]].perim) <= thresh ) { + BMO_SetFlag(bm, fm, FACE_MARK); + cont = 0; + } + break; + } + } + } + } + + free(f_ext); + free(indices); + + /* transfer all marked faces to the output slot */ + BMO_Flag_To_Slot(bm, op, "faceout", FACE_MARK, BM_FACE); +} diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c index 8df10373809..cd14b5c1e33 100644 --- a/source/blender/editors/mesh/bmesh_select.c +++ b/source/blender/editors/mesh/bmesh_select.c @@ -649,13 +649,6 @@ static int unified_findnearest(ViewContext *vc, BMVert **eve, BMEdge **eed, BMFa /* FACES GROUP */ -#define SIMFACE_MATERIAL 201 -#define SIMFACE_IMAGE 202 -#define SIMFACE_AREA 203 -#define SIMFACE_PERIMETER 204 -#define SIMFACE_NORMAL 205 -#define SIMFACE_COPLANAR 206 - static EnumPropertyItem prop_simface_types[] = { {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, @@ -666,160 +659,40 @@ static EnumPropertyItem prop_simface_types[] = { {0, NULL, 0, NULL, NULL} }; +static int similar_face_select_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_edit_object(C); + BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh; + BMOperator bmop; -/* this as a way to compare the ares, perim of 2 faces thay will scale to different sizes -*0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */ -#define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b)) + /* get the type from RNA */ + int type = RNA_enum_get(op->ptr, "type"); -static int similar_face_select__internal(Scene *scene, EditMesh *em, int mode) -{ -#if 0 - EditFace *efa, *base_efa=NULL; - unsigned int selcount=0; /*count how many new faces we select*/ - - /*deselcount, count how many deselected faces are left, so we can bail out early - also means that if there are no deselected faces, we can avoid a lot of looping */ - unsigned int deselcount=0; - float thresh= scene->toolsettings->select_thresh; - short ok=0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if (!efa->h) { - if (efa->f & SELECT) { - efa->f1=1; - ok=1; - } else { - efa->f1=0; - deselcount++; /* a deselected face we may select later */ - } - } - } - - if (!ok || !deselcount) /* no data selected OR no more data to select */ - return 0; - - if (mode==SIMFACE_AREA) { - for(efa= em->faces.first; efa; efa= efa->next) { - efa->tmp.fp= EM_face_area(efa); - } - } else if (mode==SIMFACE_PERIMETER) { - for(efa= em->faces.first; efa; efa= efa->next) { - efa->tmp.fp= EM_face_perimeter(efa); - } - } - - for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) { - if (base_efa->f1) { /* This was one of the faces originaly selected */ - if (mode==SIMFACE_MATERIAL) { /* same material */ - for(efa= em->faces.first; efa; efa= efa->next) { - if ( - !(efa->f & SELECT) && - !efa->h && - base_efa->mat_nr == efa->mat_nr - ) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMFACE_IMAGE) { /* same image */ - MTFace *tf, *base_tf; + float thresh = scene->toolsettings->select_thresh; - base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data, - CD_MTFACE); + /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ + EDBM_InitOpf(em, &bmop, op, "similarfaces faces=%hf type=%d thresh=%f", BM_SELECT, type, thresh); - if(!base_tf) - return selcount; + /* execute the operator */ + BMO_Exec_Op(em->bm, &bmop); - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data, - CD_MTFACE); + /* clear the existing selection */ + EDBM_clear_flag_all(em, BM_SELECT); - if(base_tf->tpage == tf->tpage) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } else if (mode==SIMFACE_AREA || mode==SIMFACE_PERIMETER) { /* same area OR same perimeter, both use the same temp var */ - for(efa= em->faces.first; efa; efa= efa->next) { - if ( - (!(efa->f & SELECT) && !efa->h) && - SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp) - ) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } else if (mode==SIMFACE_NORMAL) { - float angle; - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - angle= VecAngle2(base_efa->n, efa->n); - if (angle/180.0<=thresh) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } else if (mode==SIMFACE_COPLANAR) { /* same planer */ - float angle, base_dot, dot; - base_dot= Inpf(base_efa->cent, base_efa->n); - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - angle= VecAngle2(base_efa->n, efa->n); - if (angle/180.0<=thresh) { - dot=Inpf(efa->cent, base_efa->n); - if (fabs(base_dot-dot) <= thresh) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; - } - } - } - } - } - } - } /* end base_efa loop */ - return selcount; -#endif -} + /* select the output */ + BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_ALL); -static int similar_face_select_exec(bContext *C, wmOperator *op) -{ -#if 0 - Scene *scene= CTX_data_scene(C); - Object *obedit= CTX_data_edit_object(C); - Mesh *me= obedit->data; - EditMesh *em= BKE_mesh_get_editmesh(me); + /* finish the operator */ + if( !EDBM_FinishOp(em, &bmop, op, 1) ) + return OPERATOR_CANCELLED; - int selcount = similar_face_select__internal(scene, em, RNA_int_get(op->ptr, "type")); - - if (selcount) { - /* here was an edge-mode only select flush case, has to be generalized */ - EM_selectmode_flush(em); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); - BKE_mesh_end_editmesh(me, em); - return OPERATOR_FINISHED; - } - - BKE_mesh_end_editmesh(me, em); -#endif - return OPERATOR_CANCELLED; + /* dependencies graph and notification stuff */ + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob); + + /* we succeeded */ + return OPERATOR_FINISHED; } /* ***************************************************** */ |