select nth (face/edge/vertex) - depending on which was last selected, useful for...
authorCampbell Barton <ideasman42@gmail.com>
Tue, 22 Dec 2009 19:01:51 +0000 (19:01 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 22 Dec 2009 19:01:51 +0000 (19:01 +0000)
release/scripts/ui/space_view3d.py
source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/editmesh_lib.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_ops.c

index 2ec0e44e184f3be7075b175e3dd1c606d6c4b67a..26a018f81cb972863e8593030a6542f7cfd31cbb 100644 (file)
@@ -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")
index aab364bf686770a2bd875576017bd1bac9cd12e9..174447c0f9fdeee7264604394bd4f48ece239839 100644 (file)
@@ -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;
 
index 1b90dbc3902ae40ac0b5de0eeb15bb6ef893735b..d99765bd199da2746629098518481af22486beec 100644 (file)
@@ -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;
+}
+
index d1dde75771d9610f01d38c3d088d7c4f9ab50e09..827b28f954bb54c11bef1da0500d3111c969040e 100644 (file)
@@ -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);
+}
+
index 7b7257ae9cb0a91029948d94a74195d4c3e08797..e8ec85d8bd08987024f6c9d23a5a5649de41eb45 100644 (file)
@@ -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);
index af25dbda16b9438a1785e9161c8cd0cd4acd10e1..11b5f3a903160f8518cda6961caeb24259176f16 100644 (file)
@@ -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)