Commit: b1dbda143da35d367ba7c4a05f81ee5b21b42999
Author: Campbell Barton
Date:   Fri Feb 6 15:46:38 2015 +1100
Branches: master
https://developer.blender.org/rBb1dbda143da35d367ba7c4a05f81ee5b21b42999

BMesh: Connect path, use select order

Could connect a pair of verts previously,
now connect all vertices along the path, running a second time closes the loop.

Can also be used for without faces to connect edges between selected points.

===================================================================

M       release/scripts/startup/bl_ui/space_view3d.py
M       source/blender/editors/mesh/editmesh_tools.c
M       source/blender/editors/mesh/mesh_intern.h
M       source/blender/editors/mesh/mesh_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py 
b/release/scripts/startup/bl_ui/space_view3d.py
index 845e568..89797b9 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2218,7 +2218,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
         layout.operator("mesh.rip_edge_move")
         layout.operator("mesh.split")
         layout.operator_menu_enum("mesh.separate", "type")
-        layout.operator("mesh.vert_connect", text="Connect")
+        layout.operator("mesh.vert_connect_path", text="Connect Vertex Path")
+        layout.operator("mesh.vert_connect", text="Connect Vertices")
         layout.operator("transform.vert_slide", text="Slide")
 
         layout.separator()
diff --git a/source/blender/editors/mesh/editmesh_tools.c 
b/source/blender/editors/mesh/editmesh_tools.c
index 5127844..93ebbbc 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -883,7 +883,6 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator 
*op)
        const int verts_len = bm->totvertsel;
        BMVert **verts;
 
-
        verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
        {
                BMIter iter;
@@ -954,7 +953,7 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
        /* identifiers */
        ot->name = "Vertex Connect";
        ot->idname = "MESH_OT_vert_connect";
-       ot->description = "Connect 2 vertices of a face by an edge, splitting 
the face in two";
+       ot->description = "Connect selected vertices of faces, splitting the 
face";
        
        /* api callbacks */
        ot->exec = edbm_vert_connect_exec;
@@ -964,6 +963,191 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+
+/**
+ * check that endpoints are verts and only have a single selected edge 
connected.
+ */
+static bool bm_vert_is_select_history_open(BMesh *bm)
+{
+       BMEditSelection *ele_a = bm->selected.first;
+       BMEditSelection *ele_b = bm->selected.last;
+       if ((ele_a->htype == BM_VERT) &&
+           (ele_b->htype == BM_VERT))
+       {
+               if ((BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert 
*)ele_a->ele, BM_ELEM_SELECT, true) == 1) &&
+                   (BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert 
*)ele_b->ele, BM_ELEM_SELECT, true) == 1))
+               {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static bool bm_vert_connect_pair(BMesh *bm, BMVert *v_a, BMVert *v_b)
+{
+       BMOperator bmop;
+       BMVert **verts;
+       const int totedge_orig = bm->totedge;
+
+       BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, "connect_vert_pair");
+
+       verts = BMO_slot_buffer_alloc(&bmop, bmop.slots_in, "verts", 2);
+       verts[0] = v_a;
+       verts[1] = v_b;
+
+       BM_vert_normal_update(verts[0]);
+       BM_vert_normal_update(verts[1]);
+
+       BMO_op_exec(bm, &bmop);
+       BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "edges.out", BM_EDGE, 
BM_ELEM_SELECT, true);
+       BMO_op_finish(bm, &bmop);
+       return (bm->totedge != totedge_orig);
+}
+
+static bool bm_vert_connect_select_history(BMesh *bm)
+{
+       /* Logic is as follows:
+        *
+        * - If there are any isolated/wire verts - connect as edges.
+        * - Otherwise connect faces.
+        * - If all edges have been created already, closed the loop.
+        */
+       if (BLI_listbase_count_ex(&bm->selected, 2) == 2 && (bm->totvertsel > 
2)) {
+               BMEditSelection *ese;
+               int tot = 0;
+               bool changed = false;
+               bool has_wire = false;
+               // bool all_verts;
+
+               /* ensure all verts have history */
+               for (ese = bm->selected.first; ese; ese = ese->next, tot++) {
+                       BMVert *v;
+                       if (ese->htype != BM_VERT) {
+                               break;
+                       }
+                       v = (BMVert *)ese->ele;
+                       if ((has_wire == false) && ((v->e == NULL) || 
BM_vert_is_wire(v))) {
+                               has_wire = true;
+                       }
+               }
+               // all_verts = (ese == NULL);
+
+               if (has_wire == false) {
+                       /* all verts have faces , connect verts via faces! */
+                       if (tot == bm->totvertsel) {
+                               BMEditSelection *ese_last;
+                               ese_last = bm->selected.first;
+                               ese = ese_last->next;
+
+                               do {
+
+                                       if (BM_edge_exists((BMVert 
*)ese_last->ele, (BMVert *)ese->ele)) {
+                                               /* pass, edge exists (and will 
be selected) */
+                                       }
+                                       else {
+                                               changed |= 
bm_vert_connect_pair(bm, (BMVert *)ese_last->ele, (BMVert *)ese->ele);
+                                       }
+                               } while ((ese_last = ese),
+                                        (ese = ese->next));
+
+                               if (changed) {
+                                       return true;
+                               }
+                       }
+
+                       if (changed == false) {
+                               /* existing loops: close the selection */
+                               if (bm_vert_is_select_history_open(bm)) {
+                                       changed |= bm_vert_connect_pair(
+                                               bm,
+                                               (BMVert *)((BMEditSelection 
*)bm->selected.first)->ele,
+                                               (BMVert *)((BMEditSelection 
*)bm->selected.last)->ele);
+
+                                       if (changed) {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+
+               else {
+                       /* no faces, simply connect the verts by edges */
+                       BMEditSelection *ese_prev;
+                       ese_prev = bm->selected.first;
+                       ese = ese_prev->next;
+
+
+                       do {
+                               if (BM_edge_exists((BMVert *)ese_prev->ele, 
(BMVert *)ese->ele)) {
+                                       /* pass, edge exists (and will be 
selected) */
+                               }
+                               else {
+                                       BMEdge *e;
+                                       e = BM_edge_create(bm, (BMVert 
*)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
+                                       BM_edge_select_set(bm, e, true);
+                                       changed = true;
+                               }
+                       } while ((ese_prev = ese),
+                                (ese = ese->next));
+
+                       if (changed == false) {
+                               /* existing loops: close the selection */
+                               if (bm_vert_is_select_history_open(bm)) {
+                                       BMEdge *e;
+                                       ese_prev = bm->selected.first;
+                                       ese = bm->selected.last;
+                                       e = BM_edge_create(bm, (BMVert 
*)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
+                                       BM_edge_select_set(bm, e, true);
+                               }
+                       }
+
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit = CTX_data_edit_object(C);
+       BMEditMesh *em = BKE_editmesh_from_object(obedit);
+       bool is_pair = (em->bm->totvertsel == 2);
+
+       /* when there is only 2 vertices, we can ignore selection order */
+       if (is_pair) {
+               return edbm_vert_connect_exec(C, op);
+       }
+
+       if (bm_vert_connect_select_history(em->bm)) {
+               EDBM_selectmode_flush(em);
+               EDBM_update_generic(em, true, true);
+
+               return OPERATOR_FINISHED;
+       }
+       else {
+               BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
+               return OPERATOR_CANCELLED;
+       }
+}
+
+void MESH_OT_vert_connect_path(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Vertex Connect Path";
+       ot->idname = "MESH_OT_vert_connect_path";
+       ot->description = "Connect vertices by their selection order, creating 
edges, splitting faces";
+
+       /* api callbacks */
+       ot->exec = edbm_vert_connect_path_exec;
+       ot->poll = ED_operator_editmesh;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
 static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
 {
        Object *obedit = CTX_data_edit_object(C);
diff --git a/source/blender/editors/mesh/mesh_intern.h 
b/source/blender/editors/mesh/mesh_intern.h
index 8f5ecae..8611872 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -175,6 +175,7 @@ void MESH_OT_normals_make_consistent(struct wmOperatorType 
*ot);
 void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
 void MESH_OT_vertices_smooth_laplacian(struct wmOperatorType *ot);
 void MESH_OT_vert_connect(struct wmOperatorType *ot);
+void MESH_OT_vert_connect_path(struct wmOperatorType *ot);
 void MESH_OT_vert_connect_concave(struct wmOperatorType *ot);
 void MESH_OT_vert_connect_nonplanar(struct wmOperatorType *ot);
 void MESH_OT_edge_split(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c 
b/source/blender/editors/mesh/mesh_ops.c
index 59d0de8..2855af0 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -163,6 +163,7 @@ void ED_operatortypes_mesh(void)
        WM_operatortype_append(MESH_OT_solidify);
        WM_operatortype_append(MESH_OT_select_nth);
        WM_operatortype_append(MESH_OT_vert_connect);
+       WM_operatortype_append(MESH_OT_vert_connect_path);
        WM_operatortype_append(MESH_OT_vert_connect_concave);
        WM_operatortype_append(MESH_OT_vert_connect_nonplanar);
        WM_operatortype_append(MESH_OT_knife_tool);
@@ -401,7 +402,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
        
        WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "MESH_OT_split", YKEY, KM_PRESS, 0, 0);
-       WM_keymap_add_item(keymap, "MESH_OT_vert_connect", JKEY, KM_PRESS, 0, 
0);
+       WM_keymap_add_item(keymap, "MESH_OT_vert_connect_path", JKEY, KM_PRESS, 
0, 0);
 
        /* Vertex Slide */
        WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, 
KM_SHIFT, 0);

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to