implement select nth, separate loose parts, and a few bug fixes

This code is from Andrew Wiggen (ender79) and reviewed by me.

His comments:

Implements some tools that were marked TODO:
- select nth
- separate loose parts

And also fixes a few bugs;
- extrude and move on normals causes faces to disappear until the move starts
- hiding verts/edges/faces does not deselect them
- deleting a selection sometimes deletes too much (e.g. a solid cube and a wire cube build of only edges, join them on a single edge, select only the faces of the solid cube and delete, some of the deselected edges from the wire cube were also being deleted)
This commit is contained in:
Howard Trickey
2011-08-28 17:15:24 +00:00
parent 9749a68f20
commit e1315ef15a
7 changed files with 427 additions and 269 deletions

View File

@@ -37,6 +37,7 @@
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <assert.h>
#include "MEM_guardedalloc.h"
@@ -298,7 +299,7 @@ void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char deli
void BLI_cleanup_path(const char *relabase, char *dir)
{
short a;
ptrdiff_t a;
char *start, *eind;
if (relabase) {
BLI_path_abs(dir, relabase);

View File

@@ -648,6 +648,11 @@ void BM_Hide(BMesh *bm, void *element, int hide)
{
BMHeader *h = element;
/*Follow convention of always deselecting before
hiding an element*/
if (hide)
BM_Select(bm, element, 0);
switch (h->type) {
case BM_VERT:
BM_Hide_Vert(bm, element, hide);

View File

@@ -231,7 +231,7 @@ static void *islandboundWalker_step(BMWalker *walker)
l = bmesh_radial_nextloop(l);
f = l->f;
e = l->e;
if(!BMO_TestFlag(walker->bm, f, walker->restrictflag)){
if(walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag)){
l = l->radial_next;
break;
}
@@ -301,7 +301,7 @@ static void *islandWalker_step(BMWalker *walker)
for (; l; l=BMIter_Step(&liter)) {
f = BMIter_New(&iter, walker->bm, BM_FACES_OF_EDGE, l->e);
for (; f; f=BMIter_Step(&iter)) {
if (!BMO_TestFlag(walker->bm, f, walker->restrictflag))
if (walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag))
continue;
if (BLI_ghash_haskey(walker->visithash, f)) continue;
@@ -310,7 +310,6 @@ static void *islandWalker_step(BMWalker *walker)
iwalk->cur = f;
BLI_ghash_insert(walker->visithash, f, NULL);
break;
}
}
@@ -318,13 +317,9 @@ static void *islandWalker_step(BMWalker *walker)
}
/* Island Walker:
/* Edge Loop Walker:
*
* Starts at a tool flagged-face and walks over the face region
*
* TODO:
*
* Add restriction flag/callback for wire edges.
* Starts at a tool-flagged edge and walks over the edge loop
*
*/

View File

@@ -516,10 +516,19 @@ static void delete_context(BMesh *bm, int type){
/*now go through and mark all remaining faces all edges for keeping.*/
for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
if(!BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e= BMIter_Step(&edges))
for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e= BMIter_Step(&edges)){
BMO_ClearFlag(bm, (BMHeader*)e, DEL_INPUT);
for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v= BMIter_Step(&verts))
}
for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v= BMIter_Step(&verts)){
BMO_ClearFlag(bm, (BMHeader*)v, DEL_INPUT);
}
}
}
/*also mark all the vertices of remaining edges for keeping.*/
for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
if(!BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)){
BMO_ClearFlag(bm, (BMHeader*)e->v1, DEL_INPUT);
BMO_ClearFlag(bm, (BMHeader*)e->v2, DEL_INPUT);
}
}
/*now delete marked faces*/

View File

@@ -63,7 +63,6 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
if (!me || !me->totvert) return; /*sanity check*/
mvert = me->mvert;
vt = MEM_mallocN(sizeof(void**)*me->totvert, "mesh to bmesh vtable");
CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
@@ -125,7 +124,7 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
for (i=0; i<me->totvert; i++, mvert++) {
for (i=0, mvert = me->mvert; i<me->totvert; i++, mvert++) {
v = BM_Make_Vert(bm, keyco&&set_key ? keyco[i] : mvert->co, NULL);
normal_short_to_float_v3(v->no, mvert->no);

View File

@@ -1646,20 +1646,318 @@ void MESH_OT_select_less(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/* not that optimal!, should be nicer with bmesh */
static void tag_face_edges(BMesh* bm, BMFace *f)
{
BMLoop *l;
BMIter iter;
BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
BM_SetIndex(l->e, 1);
}
}
static int tag_face_edges_test(BMesh* bm, BMFace *f)
{
BMLoop *l;
BMIter iter;
BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
if(BM_GetIndex(l->e) != 0)
return 1;
}
return 0;
}
static void em_deselect_nth_face(BMEditMesh *em, int nth, BMFace *f_act)
{
BMFace *f;
BMEdge *e;
BMIter iter;
BMesh *bm = em->bm;
int index;
int ok= 1;
if(f_act==NULL) {
return;
}
/* to detect loose edges, we put f2 flag on 1 */
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
BM_SetIndex(e, 0);
}
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
BM_SetIndex(f, 0);
}
BM_SetIndex(f_act, 1);
while(ok) {
ok = 0;
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
index= BM_GetIndex(f);
if(index==1) { /* initialize */
tag_face_edges(bm, f);
}
if (index)
BM_SetIndex(f, index+1);
}
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
if(BM_GetIndex(f)==0 && tag_face_edges_test(bm, f)) {
BM_SetIndex(f, 1);
ok= 1; /* keep looping */
}
}
}
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
index= BM_GetIndex(f);
if(index > 0 && index % nth) {
BM_Select(bm, f, 0);
}
}
EDBM_select_flush(em, SCE_SELECT_FACE);
}
/* not that optimal!, should be nicer with bmesh */
static void tag_edge_verts(BMesh *bm, BMEdge *e)
{
BM_SetIndex(e->v1, 1);
BM_SetIndex(e->v2, 1);
}
static int tag_edge_verts_test(BMesh *bm, BMEdge *e)
{
return (BM_GetIndex(e->v1) || BM_GetIndex(e->v2)) ? 1:0;
}
static void em_deselect_nth_edge(BMEditMesh *em, int nth, BMEdge *e_act)
{
BMEdge *e;
BMVert *v;
BMIter iter;
BMesh *bm = em->bm;
int index;
int ok= 1;
if(e_act==NULL) {
return;
}
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
BM_SetIndex(v, 0);
}
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
BM_SetIndex(e, 0);
}
BM_SetIndex(e_act, 1);
while(ok) {
ok = 0;
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
index= BM_GetIndex(e);
if (index==1) { /* initialize */
tag_edge_verts(bm, e);
}
if (index)
BM_SetIndex(e, index+1);
}
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
if (BM_GetIndex(e)==0 && tag_edge_verts_test(bm, e)) {
BM_SetIndex(e, 1);
ok = 1; /* keep looping */
}
}
}
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
index= BM_GetIndex(e);
if (index > 0 && index % nth)
BM_Select(bm, e, 0);
}
EDBM_select_flush(em, SCE_SELECT_EDGE);
}
static void em_deselect_nth_vert(BMEditMesh *em, int nth, BMVert *v_act)
{
BMEdge *e;
BMVert *v;
BMIter iter;
BMesh *bm = em->bm;
int ok= 1;
if(v_act==NULL) {
return;
}
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
BM_SetIndex(v, 0);
}
BM_SetIndex(v_act, 1);
while(ok) {
ok = 0;
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
int index = BM_GetIndex(v);
if (index != 0)
BM_SetIndex(v, index+1);
}
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
int indexv1= BM_GetIndex(e->v1);
int indexv2= BM_GetIndex(e->v2);
if (indexv1 == 2 && indexv2 == 0) {
BM_SetIndex(e->v2, 1);
ok = 1; /* keep looping */
}
else if (indexv2 == 2 && indexv1 == 0) {
BM_SetIndex(e->v1, 1);
ok = 1; /* keep looping */
}
}
}
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
int index= BM_GetIndex(v);
if(index && index % nth) {
BM_Select(bm, v, 0);
}
}
EDBM_select_flush(em, SCE_SELECT_VERTEX);
}
BMFace *EM_get_actFace(BMEditMesh *em, int sloppy)
{
if (em->bm->act_face) {
return em->bm->act_face;
} else if (sloppy) {
BMIter iter;
BMFace *f= NULL;
BMEditSelection *ese;
/* Find the latest non-hidden face from the BMEditSelection */
ese = em->bm->selected.last;
for (; ese; ese=ese->prev){
if(ese->type == BM_FACE) {
f = (BMFace *)ese->data;
if (BM_TestHFlag(f, BM_HIDDEN)) f= NULL;
else break;
}
}
/* Last attempt: try to find any selected face */
if (f==NULL) {
BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
if (BM_TestHFlag(f, BM_SELECT))
break;
}
}
return f; /* can still be null */
}
return NULL;
}
static void deselect_nth_active(BMEditMesh *em, BMVert **v_p, BMEdge **e_p, BMFace **f_p)
{
BMVert *v;
BMEdge *e;
BMFace *f;
BMIter iter;
BMEditSelection *ese;
*v_p= NULL;
*e_p= NULL;
*f_p= NULL;
EDBM_selectmode_flush(em);
ese= (BMEditSelection*)em->bm->selected.last;
if(ese) {
switch(ese->type) {
case BM_VERT:
*v_p= (BMVert *)ese->data;
return;
case BM_EDGE:
*e_p= (BMEdge *)ese->data;
return;
case BM_FACE:
*f_p= (BMFace *)ese->data;
return;
}
}
if(em->selectmode & SCE_SELECT_VERTEX) {
BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
if (BM_TestHFlag(v, BM_SELECT)) {
*v_p = v;
return;
}
}
}
else if(em->selectmode & SCE_SELECT_EDGE) {
BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
if (BM_TestHFlag(e, BM_SELECT)) {
*e_p = e;
return;
}
}
}
else if(em->selectmode & SCE_SELECT_FACE) {
f= EM_get_actFace(em, 1);
if(f) {
*f_p= f;
return;
}
}
}
static int EM_deselect_nth(BMEditMesh *em, int nth)
{
BMVert *v;
BMEdge *e;
BMFace *f;
deselect_nth_active(em, &v, &e, &f);
if(v) {
em_deselect_nth_vert(em, nth, v);
return 1;
}
else if(e) {
em_deselect_nth_edge(em, nth, e);
return 1;
}
else if(f) {
em_deselect_nth_face(em, nth, f);
return 1;
}
return 0;
}
static int mesh_select_nth_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
// BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
// int nth = RNA_int_get(op->ptr, "nth");
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
int nth= RNA_int_get(op->ptr, "nth");
#if 0 //BMESH_TODO
if(EM_deselect_nth(em, nth) == 0) {
BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face.");
return OPERATOR_CANCELLED;
}
#else
BKE_report(op->reports, RPT_ERROR, "Unimplemented");
#endif
DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
@@ -1685,243 +1983,6 @@ void MESH_OT_select_nth(wmOperatorType *ot)
RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
}
#if 0 //BMESH_TODO, select nth tool
/* not that optimal!, should be nicer with bmesh */
static void tag_face_edges(EditFace *efa)
{
if(efa->v4)
efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;
else
efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
}
static int tag_face_edges_test(EditFace *efa)
{
if(efa->v4)
return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l || efa->e4->tmp.l) ? 1:0;
else
return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l) ? 1:0;
}
void em_deselect_nth_face(EditMesh *em, int nth, EditFace *efa_act)
{
EditFace *efa;
EditEdge *eed;
int ok= 1;
if(efa_act==NULL) {
return;
}
/* to detect loose edges, we put f2 flag on 1 */
for(eed= em->edges.first; eed; eed= eed->next) {
eed->tmp.l= 0;
}
for (efa= em->faces.first; efa; efa= efa->next) {
efa->tmp.l = 0;
}
efa_act->tmp.l = 1;
while(ok) {
ok = 0;
for (efa= em->faces.first; efa; efa= efa->next) {
if(efa->tmp.l==1) { /* initialize */
tag_face_edges(efa);
}
if(efa->tmp.l)
efa->tmp.l++;
}
for (efa= em->faces.first; efa; efa= efa->next) {
if(efa->tmp.l==0 && tag_face_edges_test(efa)) {
efa->tmp.l= 1;
ok = 1; /* keep looping */
}
}
}
for (efa= em->faces.first; efa; efa= efa->next) {
if(efa->tmp.l > 0 && efa->tmp.l % nth) {
EM_select_face(efa, 0);
}
}
for (efa= em->faces.first; efa; efa= efa->next) {
if(efa->f & SELECT) {
EM_select_face(efa, 1);
}
}
EM_nvertices_selected(em);
EM_nedges_selected(em);
EM_nfaces_selected(em);
}
/* not that optimal!, should be nicer with bmesh */
static void tag_edge_verts(EditEdge *eed)
{
eed->v1->tmp.l= eed->v2->tmp.l= 1;
}
static int tag_edge_verts_test(EditEdge *eed)
{
return (eed->v1->tmp.l || eed->v2->tmp.l) ? 1:0;
}
void em_deselect_nth_edge(EditMesh *em, int nth, EditEdge *eed_act)
{
EditEdge *eed;
EditVert *eve;
int ok= 1;
if(eed_act==NULL) {
return;
}
for(eve= em->verts.first; eve; eve= eve->next) {
eve->tmp.l= 0;
}
for (eed= em->edges.first; eed; eed= eed->next) {
eed->tmp.l = 0;
}
eed_act->tmp.l = 1;
while(ok) {
ok = 0;
for (eed= em->edges.first; eed; eed= eed->next) {
if(eed->tmp.l==1) { /* initialize */
tag_edge_verts(eed);
}
if(eed->tmp.l)
eed->tmp.l++;
}
for (eed= em->edges.first; eed; eed= eed->next) {
if(eed->tmp.l==0 && tag_edge_verts_test(eed)) {
eed->tmp.l= 1;
ok = 1; /* keep looping */
}
}
}
for (eed= em->edges.first; eed; eed= eed->next) {
if(eed->tmp.l > 0 && eed->tmp.l % nth) {
EM_select_edge(eed, 0);
}
}
for (eed= em->edges.first; eed; eed= eed->next) {
if(eed->f & SELECT) {
EM_select_edge(eed, 1);
}
}
{
/* grr, should be a function */
EditFace *efa;
for (efa= em->faces.first; efa; efa= efa->next) {
if(efa->v4) {
if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT );
else efa->f &= ~SELECT;
}
else {
if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT );
else efa->f &= ~SELECT;
}
}
}
EM_nvertices_selected(em);
EM_nedges_selected(em);
EM_nfaces_selected(em);
}
void em_deselect_nth_vert(EditMesh *em, int nth, EditVert *eve_act)
{
EditVert *eve;
EditEdge *eed;
int ok= 1;
if(eve_act==NULL) {
return;
}
for (eve= em->verts.first; eve; eve= eve->next) {
eve->tmp.l = 0;
}
eve_act->tmp.l = 1;
while(ok) {
ok = 0;
for (eve= em->verts.first; eve; eve= eve->next) {
if(eve->tmp.l)
eve->tmp.l++;
}
for (eed= em->edges.first; eed; eed= eed->next) {
if(eed->v1->tmp.l==2 && eed->v2->tmp.l==0) { /* initialize */
eed->v2->tmp.l= 1;
ok = 1; /* keep looping */
}
else if(eed->v2->tmp.l==2 && eed->v1->tmp.l==0) { /* initialize */
eed->v1->tmp.l= 1;
ok = 1; /* keep looping */
}
}
}
for (eve= em->verts.first; eve; eve= eve->next) {
if(eve->tmp.l > 0 && eve->tmp.l % nth) {
eve->f &= ~SELECT;
}
}
EM_deselect_flush(em);
EM_nvertices_selected(em);
// EM_nedges_selected(em); // flush does these
// EM_nfaces_selected(em); // flush does these
}
#endif
static int EM_deselect_nth(BMEditMesh *em, int nth)
{
#if 1 /*BMESH_TODO*/
(void)em;
(void)nth;
#else
EditSelection *ese;
ese = ((EditSelection*)em->selected.last);
if(ese) {
if(ese->type == EDITVERT) {
em_deselect_nth_vert(em, nth, (EditVert*)ese->data);
return 1;
}
if(ese->type == EDITEDGE) {
em_deselect_nth_edge(em, nth, (EditEdge*)ese->data);
return 1;
}
}
else {
EditFace *efa_act = EM_get_actFace(em, 0);
if(efa_act) {
em_deselect_nth_face(em, nth, efa_act);
return 1;
}
}
return 0;
#endif
return 1;
}
void em_setup_viewcontext(bContext *C, ViewContext *vc)
{
view3d_set_viewcontext(C, vc);

View File

@@ -692,7 +692,13 @@ static int mesh_extrude_region_exec(bContext *C, wmOperator *op)
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
EDBM_Extrude_Mesh(scene, obedit, em, op, NULL);
/*This normally happens when pushing undo but modal operators
like this one don't push undo data until after modal mode is
done.*/
EDBM_RecalcNormals(em);
BMEdit_RecalcTesselation(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
return OPERATOR_FINISHED;
@@ -1100,14 +1106,15 @@ static int delete_mesh_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
if (type != 12) {
delete_mesh(C, obedit, op, type, scene);
if (delete_mesh(C, obedit, op, type, scene) == OPERATOR_CANCELLED)
return OPERATOR_CANCELLED;
EDBM_clear_flag_all(em, BM_SELECT);
} else {
if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
return OPERATOR_CANCELLED;
DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
}
WM_event_add_notifier(C, NC_GEOM|ND_DATA|ND_SELECT, obedit);
return OPERATOR_FINISHED;
@@ -1594,6 +1601,8 @@ void EDBM_hide_mesh(BMEditMesh *em, int swap)
BM_Hide(em->bm, h, 1);
}
EDBM_selectmode_flush(em);
/*original hide flushing comment (OUTDATED):
hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
/* - vertex hidden, always means edge is hidden too
@@ -1643,7 +1652,12 @@ void EDBM_reveal_mesh(BMEditMesh *em)
int i, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
int sels[3] = {1, !(em->selectmode & SCE_SELECT_VERTEX), !(em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE))};
for (i=0; i<3; i++) {
/*Reveal all hidden elements. Handle the reveal in order of faces,
edges, and finally vertices. This is important because revealing
edges may reveal faces, and revealing verts may reveal edges and
faces. Revealing edges or faces in an earlier pass would keep them
from getting selected in the later passes.*/
for (i=2; i>=0; i--) {
BM_ITER(ele, &iter, em->bm, types[i], NULL) {
if (BM_TestHFlag(ele, BM_HIDDEN)) {
BM_Hide(em->bm, ele, 0);
@@ -3047,7 +3061,7 @@ static int select_axis_exec(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
BMEditSelection *ese = em->bm->selected.last;
int axis= RNA_int_get(op->ptr, "axis");
int axis= RNA_enum_get(op->ptr, "axis");
int mode= RNA_enum_get(op->ptr, "mode"); /* -1==aligned, 0==neg, 1==pos*/
if(ese==NULL)
@@ -3098,6 +3112,12 @@ void MESH_OT_select_axis(wmOperatorType *ot)
{-1, "ALIGNED", 0, "Aligned Axis", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem axis_items_xyz[] = {
{0, "X_AXIS", 0, "X Axis", ""},
{1, "Y_AXIS", 0, "Y Axis", ""},
{2, "Z_AXIS", 0, "Z Axis", ""},
{0, NULL, 0, NULL, NULL}};
/* identifiers */
ot->name= "Select Axis";
ot->description= "Select all data in the mesh on a single axis.";
@@ -3112,7 +3132,7 @@ void MESH_OT_select_axis(wmOperatorType *ot)
/* properties */
RNA_def_enum(ot->srna, "mode", axis_mode_items, 0, "Axis Mode", "Axis side to use when selecting");
RNA_def_int(ot->srna, "axis", 0, 0, 2, "Axis", "Select the axis to compare each vertex on", 0, 2);
RNA_def_enum(ot->srna, "axis", axis_items_xyz, 0, "Axis", "Select the axis to compare each vertex on");
}
static int solidify_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
@@ -3515,7 +3535,7 @@ static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase, wmO
EDBM_CallOpf(em, wmop, "dupe geom=%hvef dest=%p", BM_SELECT, bmnew);
EDBM_CallOpf(em, wmop, "del geom=%hvef context=%i", BM_SELECT, DEL_FACES);
/*clean up any loose edges*/
BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
if (BM_TestHFlag(e, BM_HIDDEN))
@@ -3534,7 +3554,7 @@ static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase, wmO
if (BM_Vert_EdgeCount(v) != 0)
BM_Select(em->bm, v, 0); /*deselect*/
}
EDBM_CallOpf(em, wmop, "del geom=%hvef context=%i", BM_SELECT, DEL_VERTS);
BM_Compute_Normals(bmnew);
@@ -3552,10 +3572,78 @@ static int mesh_separate_material(Main *UNUSED(bmain), Scene *UNUSED(scene), Bas
return 0;
}
//BMESH_TODO
static int mesh_separate_loose(Main *UNUSED(bmain), Scene *UNUSED(scene), Base *UNUSED(editbase), wmOperator *UNUSED(wmop))
static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop)
{
return 0;
int i;
BMVert *v;
BMEdge *e;
BMVert *v_seed;
BMWalker walker;
BMIter iter;
int result = 0;
Object *obedit = editbase->object;
Mesh *me = obedit->data;
BMEditMesh *em = me->edit_btmesh;
BMesh *bm = em->bm;
int max_iter = bm->totvert;
/*Clear all selected vertices*/
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
BM_Select(bm, v, 0);
}
/*Flush the selection to clear edge/face selections to match
selected vertices*/
EDBM_select_flush(em, SCE_SELECT_VERTEX);
/*A "while(true)" loop should work here as each iteration should
select and remove at least one vertex and when all vertices
are selected the loop will break out. But guard against bad
behavior by limiting iterations to the number of vertices in the
original mesh.*/
for(i=0; i<max_iter; i++)
{
/* Get a seed vertex to start the walk */
v_seed = NULL;
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
v_seed = v;
break;
}
/* No vertices available, can't do anything */
if (v_seed == NULL)
{
break;
}
/*Select the seed explicitly, in case it has no edges*/
BM_Select(bm, v_seed, 1);
/*Walk from the single vertex, selecting everything connected
to it*/
BMW_Init(&walker, bm, BMW_SHELL, 0, 0);
e = BMW_Begin(&walker, v_seed);
for (; e; e=BMW_Step(&walker)) {
BM_Select(bm, e->v1, 1);
BM_Select(bm, e->v2, 1);
}
BMW_End(&walker);
/*Flush the selection to get edge/face selections matching
the vertex selection*/
EDBM_select_flush(em, SCE_SELECT_VERTEX);
if (bm->totvert == bm->totvertsel)
{
/*Every vertex selected, nothing to separate, work is done*/
break;
}
/*Move selection into a separate object*/
result |= mesh_separate_selected(bmain, scene, editbase, wmop);
}
return result;
}
static int mesh_separate_exec(bContext *C, wmOperator *op)