Fix [#30855] Vertex Slide not using the active vertex
authorFrancisco De La Cruz <dlcs.frank@gmail.com>
Sat, 7 Apr 2012 19:53:39 +0000 (19:53 +0000)
committerFrancisco De La Cruz <dlcs.frank@gmail.com>
Sat, 7 Apr 2012 19:53:39 +0000 (19:53 +0000)
Now uses the last selected vertex.
Also, snapping thresholds are now dynamic and the tool's operation should be more consistent with multiple edges selected on invocation.

source/blender/bmesh/operators/bmo_slide.c
source/blender/editors/mesh/editmesh_slide.c

index faeeafe97f6cec64ad61b097868cc8781ac6bc20..0e6a11613340ea1667de124044e6917f1aa902e6 100644 (file)
@@ -47,10 +47,10 @@ void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
        BMHeader *h;
        BMVert *vertex;
        BMEdge *edge;
+       BMEdge *slide_edge;
        int is_start_v1 = 0;
 
        /* Selection counts */
-       int selected_verts = 0;
        int selected_edges = 0;
 
        /* Get slide amount */
@@ -69,9 +69,6 @@ void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
        /* Count selected edges */
        BMO_ITER(h, &oiter, bm, op, "edge", BM_VERT | BM_EDGE) {
                switch (h->htype) {
-                       case BM_VERT:
-                               selected_verts++;
-                               break;
                        case BM_EDGE:
                                selected_edges++;
                                /* Mark all selected edges (cast BMHeader->BMEdge) */
@@ -80,9 +77,8 @@ void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
                }
        }
 
-       /* Only allow sliding between two verts */
-
-       if (selected_verts != 2 || selected_edges == 0) {
+       /* Only allow sliding if an edge is selected */
+       if (selected_edges == 0) {
                if (G.debug & G_DEBUG)
                        fprintf(stderr, "vertslide: select a single edge\n");
                return;
@@ -90,15 +86,15 @@ void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
 
        /* Make sure we get the correct edge. */
        BM_ITER(edge, &iter, bm, BM_EDGES_OF_VERT, vertex) {
-               if (BMO_elem_flag_test(bm, edge, EDGE_MARK)) {
-                       is_start_v1 = (edge->v1 == vertex);
+               if (BMO_elem_flag_test(bm, edge, EDGE_MARK) && BM_vert_in_edge(edge, vertex)) {
+                       slide_edge = edge;
                        break;
                }
        }
 
        /* Found edge */
-       if (edge) {
-               BMVert *other = BM_edge_other_vert(edge, vertex);
+       if (slide_edge) {
+               BMVert *other = BM_edge_other_vert(slide_edge, vertex);
 
                /* mark */
                BMO_elem_flag_enable(bm, vertex, VERT_MARK);
index 18c316d40fc141b1e3b6eee26e7dfd00823330d3..f4c96254a1a7b1a0751aa71328894656e2592094 100644 (file)
@@ -55,8 +55,7 @@
 
 #include "mesh_intern.h"
 
-#define VTX_SLIDE_SLIDE_SENS_F 15.0f
-#define VTX_SLIDE_SNAP_THRSH    0.3f
+#define VTX_SLIDE_SNAP_THRSH 0.15
 
 /* Cusom VertexSlide Operator data */
 typedef struct VertexSlideOp {
@@ -75,10 +74,13 @@ typedef struct VertexSlideOp {
 
        /* Are we in slide mode */
        int slide_mode;
-       int snap_n_weld;
+       int snap_n_merge;
        int snap_to_end_vtx;
        int snap_to_mid;
 
+       /* Snap threshold */
+       float snap_threshold;
+
        float distance;
        float interp[3];
 
@@ -105,13 +107,13 @@ static int vtx_slide_init(bContext *C, wmOperator *op)
 {
        Object *obedit = CTX_data_edit_object(C);
        BMEditMesh *em = BMEdit_FromObject(obedit);
-       BMEditSelection *ese = em->bm->selected.first;
+       BMEditSelection *ese;
 
        /* Custom data */
        VertexSlideOp *vso;
 
        const char *header_str = "Vertex Slide: Hover over an edge and left-click to select slide edge. "
-                                "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap&Weld";
+                                "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap&Merge";
 
        if (!obedit) {
                BKE_report(op->reports, RPT_ERROR, "Vertex Slide Error: Not object in context");
@@ -122,7 +124,7 @@ static int vtx_slide_init(bContext *C, wmOperator *op)
        ese = em->bm->selected.last;
 
        /* Is there a starting vertex  ? */
-       if (ese == NULL || ese->htype != BM_VERT) {
+       if (ese == NULL || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) {
                BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide Error: Select a (single) vertex");
                return FALSE;
        }
@@ -146,7 +148,7 @@ static int vtx_slide_init(bContext *C, wmOperator *op)
 
        vso->slide_mode = FALSE;
 
-       vso->snap_n_weld = FALSE;
+       vso->snap_n_merge = FALSE;
 
        vso->snap_to_end_vtx = FALSE;
 
@@ -154,6 +156,8 @@ static int vtx_slide_init(bContext *C, wmOperator *op)
 
        vso->distance = 0.0f;
 
+       vso->snap_threshold = 0.2f;
+
        /* Add handler for the vertex sliding */
        WM_event_add_modal_handler(C, op);
 
@@ -194,12 +198,21 @@ static void vtx_slide_confirm(bContext *C, wmOperator *op)
        /* Invoke operator */
        edbm_vert_slide_exec(C, op);
 
-       if(vso->snap_n_weld) {
+       if(vso->snap_n_merge) {
+               float other_d;
                BMVert* other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx);
-               BM_vert_select_set(bm, other, TRUE);
-       
-               EDBM_op_callf(em, op, "pointmerge verts=%hv mergeco=%v", BM_ELEM_SELECT, other->co);
-               EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+               other_d = len_v3v3(vso->interp, other->co);
+
+               /* Only snap if within threshold */
+               if (other_d < vso->snap_threshold) {
+                       BM_vert_select_set(bm, other, TRUE);
+                       BM_vert_select_set(bm, vso->start_vtx, TRUE);
+                       EDBM_op_callf(em, op, "pointmerge verts=%hv mergeco=%v", BM_ELEM_SELECT, other->co);
+                       EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+               } else {
+                       /* Store in historty if not merging */
+                       EDBM_editselection_store(em, &vso->start_vtx->head);            
+               }
        }
        else {
                /* Store edit selection of the active vertex, allows other
@@ -365,12 +378,18 @@ static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event)
 
        if (nst_edge) {
                /* Find a connected edge */
-               if (nst_edge->v1 == start_vtx || nst_edge->v2 == start_vtx) {
+               if (BM_vert_in_edge(nst_edge, vso->start_vtx)) {
+                       float edge_len;
+
                        /* Save mouse coords */
                        copy_v2_v2_int(vso->m_co, event->mval);
 
                        /* Set edge */
                        vso->sel_edge = nst_edge;
+                       
+                       /* Set snap threshold to be proportional to edge length */
+                       edge_len = len_v3v3(nst_edge->v1->co, nst_edge->v2->co);
+                       vso->snap_threshold = edge_len * VTX_SLIDE_SNAP_THRSH;
                }
        }
 }
@@ -426,7 +445,7 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
                        float v1_d = len_v3v3(vso->interp, edge->v1->co);
                        float v2_d = len_v3v3(vso->interp, edge->v2->co);
 
-                       if (v1_d > v2_d && v2_d < VTX_SLIDE_SNAP_THRSH) {
+                       if (v1_d > v2_d && v2_d < vso->snap_threshold) {
                                copy_v3_v3(vso->interp, edge->v2->co);
 
                                if (start_at_v1)
@@ -434,7 +453,7 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
                                else
                                        vso->distance = 0.0f;
                        }
-                       if (v2_d > v1_d && v1_d < VTX_SLIDE_SNAP_THRSH) {
+                       if (v2_d > v1_d && v1_d < vso->snap_threshold) {
                                copy_v3_v3(vso->interp, edge->v1->co);
                                if (start_at_v1)
                                        vso->distance = 0.0f;
@@ -514,11 +533,11 @@ static int edbm_vert_slide_modal(bContext *C, wmOperator *op, wmEvent *event)
                {
                        switch (event->val) {
                                case KM_PRESS:
-                                       vso->snap_n_weld = TRUE;
+                                       vso->snap_n_merge = TRUE;
                                        vso->snap_to_end_vtx = TRUE;
                                        break;
                                case KM_RELEASE:
-                                       vso->snap_n_weld = FALSE;
+                                       vso->snap_n_merge = FALSE;
                                        vso->snap_to_end_vtx = FALSE;
                                        break;
                        }
@@ -611,7 +630,7 @@ static int edbm_vert_slide_exec(bContext *C, wmOperator *op)
        BMesh *bm = em->bm;
        BMVert *start_vert;
        BMOperator bmop;
-       BMEditSelection *ese = em->bm->selected.first;
+       BMEditSelection *ese = em->bm->selected.last;
 
        float distance_t = 0.0f;
 
@@ -620,10 +639,14 @@ static int edbm_vert_slide_exec(bContext *C, wmOperator *op)
                VertexSlideOp *vso = op->customdata;
 
                if (bm->totedgesel > 1) {
+                       /* Reset selections */
                        EDBM_flag_disable_all(em, BM_ELEM_SELECT);
                        BM_edge_select_set(bm, vso->sel_edge, TRUE);
+                       BM_vert_select_set(bm, vso->start_vtx, TRUE);
+
                        EDBM_editselection_store(em, &vso->sel_edge->head);
-                       ese = em->bm->selected.first;
+                       EDBM_editselection_store(em, &vso->start_vtx->head);                    
+                       ese = em->bm->selected.last;
                }
                distance_t = vso->distance;
                RNA_float_set(op->ptr, "distance_t", distance_t);
@@ -642,7 +665,7 @@ static int edbm_vert_slide_exec(bContext *C, wmOperator *op)
        start_vert = (BMVert *)ese->ele;
 
        /* Prepare operator */
-       if (!EDBM_op_init(em, &bmop, op, "vertslide vert=%e edge=%hfev distance_t=%f", start_vert, BM_ELEM_SELECT, distance_t))  {
+       if (!EDBM_op_init(em, &bmop, op, "vertslide vert=%e edge=%hev distance_t=%f", start_vert, BM_ELEM_SELECT, distance_t))  {
                return OPERATOR_CANCELLED;
        }
        /* Execute operator */