select nth (face/edge/vertex) - depending on which was last selected, useful for colapsing every other edge for eg.

This commit is contained in:
Campbell Barton 2009-12-22 19:01:51 +00:00
parent 8c72e18354
commit d74bbcdd85
6 changed files with 278 additions and 0 deletions

@ -456,6 +456,7 @@ class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
layout.separator()
layout.operator("mesh.select_random", text="Random...")
layout.operator("mesh.select_nth", text="Select Nth...")
layout.operator("mesh.edges_select_sharp", text="Sharp Edges")
layout.operator("mesh.faces_select_linked_flat", text="Linked Flat Faces")
layout.operator("mesh.faces_select_interior", text="Interior Faces")

@ -150,6 +150,8 @@ void EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type)
void EM_make_hq_normals(struct EditMesh *em);
void EM_solidify(struct EditMesh *em, float dist);
int EM_deselect_nth(struct EditMesh *em, int nth);
/* editmesh_mods.c */
extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs;

@ -2447,3 +2447,233 @@ void EM_solidify(EditMesh *em, float dist)
MEM_freeN(vert_angles);
}
/* 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
}
int EM_deselect_nth(EditMesh *em, int nth)
{
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;
}

@ -2081,6 +2081,11 @@ static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring
EM_selectmode_flush(em);
// if (EM_texFaceCheck())
/* sets as active, useful for other tools */
if(select && em->selectmode & SCE_SELECT_EDGE) {
EM_store_selection(em, eed, EDITEDGE);
}
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
}
}
@ -4535,3 +4540,41 @@ void MESH_OT_solidify(wmOperatorType *ot)
prop= RNA_def_float(ot->srna, "thickness", 0.01f, -FLT_MAX, FLT_MAX, "thickness", "", -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -10, 10, 0.1, 4);
}
static int mesh_select_nth_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
int nth = RNA_int_get(op->ptr, "nth");
if(EM_deselect_nth(em, nth) == 0) {
BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face.");
return OPERATOR_CANCELLED;
}
BKE_mesh_end_editmesh(obedit->data, em);
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
void MESH_OT_select_nth(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Select Nth";
ot->description= "";
ot->idname= "MESH_OT_select_nth";
/* api callbacks */
ot->exec= mesh_select_nth_exec;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
}

@ -164,6 +164,7 @@ void MESH_OT_mark_sharp(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
void MESH_OT_flip_normals(struct wmOperatorType *ot);
void MESH_OT_solidify(struct wmOperatorType *ot);
void MESH_OT_select_nth(struct wmOperatorType *ot);
extern EditEdge *findnearestedge(ViewContext *vc, int *dist);

@ -152,6 +152,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_loopcut);
WM_operatortype_append(MESH_OT_solidify);
WM_operatortype_append(MESH_OT_select_nth);
}
int ED_operator_editmesh_face_select(bContext *C)