Fix [#30943] Crash when edge mode enabled and use the bmesh vertex slide(shift-V)
authorFrancisco De La Cruz <dlcs.frank@gmail.com>
Sun, 15 Apr 2012 18:34:13 +0000 (18:34 +0000)
committerFrancisco De La Cruz <dlcs.frank@gmail.com>
Sun, 15 Apr 2012 18:34:13 +0000 (18:34 +0000)
Also fixed snapping sensitivity. Gave BMOp a more consistent name "vertex_slide".

source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/intern/bmesh_operators_private.h
source/blender/bmesh/operators/bmo_slide.c
source/blender/editors/mesh/editmesh_slide.c

index 3352df71414d925fde66d0be46f5f167cd0a0f52..5896a18223a2e913d05eedec2c72e96e323f548a 100644 (file)
@@ -1110,14 +1110,14 @@ static BMOpDefine bmo_inset_def = {
  *
  * Translates vertes along an edge
  */
-static BMOpDefine bmo_vert_slide_def = {
-"vertslide",
+static BMOpDefine bmo_vertex_slide_def = {
+       "vertex_slide",
        {{BMO_OP_SLOT_ELEMENT_BUF, "vert"},
         {BMO_OP_SLOT_ELEMENT_BUF, "edge"},
         {BMO_OP_SLOT_ELEMENT_BUF, "vertout"},
         {BMO_OP_SLOT_FLT, "distance_t"},
         {0} /* null-terminating sentinel */},
-       bmo_vert_slide_exec,
+       bmo_vertex_slide_exec,
        BMO_OP_FLAG_UNTAN_MULTIRES
 };
 
@@ -1189,7 +1189,7 @@ BMOpDefine *opdefines[] = {
        &bmo_bridge_loops_def,
        &bmo_solidify_def,
        &bmo_inset_def,
-       &bmo_vert_slide_def,
+       &bmo_vertex_slide_def,
 };
 
 int bmesh_total_ops = (sizeof(opdefines) / sizeof(void *));
index c4b4f01b5b52e58f1e5022969c27bf6c86c01c68..62cabe88b055ff6e264648fe3d75efa3ebf0375f 100644 (file)
@@ -43,7 +43,7 @@ void bmo_dissolve_faces_exec(BMesh *bmesh, BMOperator *op);
 void bmo_dissolve_verts_exec(BMesh *bmesh, BMOperator *op);
 void bmo_dissolve_limit_exec(BMesh *bmesh, BMOperator *op);
 void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op);
-void bmo_vert_slide_exec(BMesh *bm, BMOperator *op);
+void bmo_vertex_slide_exec(BMesh *bm, BMOperator *op);
 void bmo_connectverts_exec(BMesh *bm, BMOperator *op);
 void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op);
 void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op);
index 9414c7308b64e24d666070416650941bb163032a..7b7b0638a3f35f04aeb2c0b05a153cfb9792602d 100644 (file)
@@ -40,7 +40,7 @@
  * Slides a vertex along a connected edge
  *
  */
-void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
+void bmo_vertex_slide_exec(BMesh *bm, BMOperator *op)
 {
        BMOIter oiter;
        BMIter iter;
@@ -60,8 +60,10 @@ void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
 
 
        if (!vertex) {
-               if (G.debug & G_DEBUG)
-                       fprintf(stderr, "vertslide: No vertex selected...");
+               if (G.debug & G_DEBUG) {
+                       fprintf(stderr, "vertex_slide: No vertex selected...");
+               }
+               BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide Error: Invalid selection.");
                return;
        }
 
@@ -78,8 +80,10 @@ void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
 
        /* 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");
+               if (G.debug & G_DEBUG) {
+                       fprintf(stderr, "vertex_slide: select a single edge\n");
+               }
+               BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide Error: Invalid selection.");
                return;
        }
 
@@ -102,9 +106,6 @@ void bmo_vert_slide_exec(BMesh *bm, BMOperator *op)
                interp_v3_v3v3(vertex->co, vertex->co, other->co, distance_t);
        }
 
-       /* Deselect the edges */
-       BMO_slot_buffer_hflag_disable(bm, op, "edge", BM_ALL, BM_ELEM_SELECT, TRUE);
-
        /* Return the new edge. The same previously marked with VERT_MARK */
        BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK);
        return;
index 94c546f0f1b42867afd18ff755f89d891d563dad..266117ec9a530edc3928d843b50efff5183bb977 100644 (file)
@@ -55,7 +55,7 @@
 
 #include "mesh_intern.h"
 
-#define VTX_SLIDE_SNAP_THRSH 0.15
+#define VTX_SLIDE_SNAP_THRSH 15
 
 /* Cusom VertexSlide Operator data */
 typedef struct VertexSlideOp {
@@ -99,9 +99,9 @@ typedef struct VertexSlideOp {
 } VertexSlideOp;
 
 static void vtx_slide_draw(const bContext *C, ARegion *ar, void *arg);
-static int edbm_vert_slide_exec(bContext *C, wmOperator *op);
+static int edbm_vertex_slide_exec(bContext *C, wmOperator *op);
 static void vtx_slide_exit(const bContext *C, wmOperator *op);
-static void vtx_slide_set_frame(VertexSlideOp *vso);
+static int vtx_slide_set_frame(VertexSlideOp *vso);
 
 static int vtx_slide_init(bContext *C, wmOperator *op)
 {
@@ -158,9 +158,6 @@ static int vtx_slide_init(bContext *C, wmOperator *op)
 
        vso->snap_threshold = 0.2f;
 
-       /* Add handler for the vertex sliding */
-       WM_event_add_modal_handler(C, op);
-
        /* Notify the viewport */
        view3d_operator_needs_opengl(C);
 
@@ -178,7 +175,14 @@ static int vtx_slide_init(bContext *C, wmOperator *op)
        vso->obj = obedit;
 
        /* Init frame */
-       vtx_slide_set_frame(vso);
+       if (!vtx_slide_set_frame(vso)) {
+               BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide: Can't find starting vertex!");
+               vtx_slide_exit(C, op);
+               return FALSE;
+       }
+
+       /* Add handler for the vertex sliding */
+       WM_event_add_modal_handler(C, op);
 
        /* Tag for redraw */
        ED_region_tag_redraw(vso->active_region);
@@ -196,7 +200,7 @@ static void vtx_slide_confirm(bContext *C, wmOperator *op)
        BM_edge_select_set(bm, vso->sel_edge, TRUE);
 
        /* Invoke operator */
-       edbm_vert_slide_exec(C, op);
+       edbm_vertex_slide_exec(C, op);
 
        if (vso->snap_n_merge) {
                float other_d;
@@ -260,6 +264,7 @@ static void vtx_slide_exit(const bContext *C, wmOperator *op)
 
        MEM_freeN(vso);
        vso = NULL;
+       op->customdata = NULL;
 
        /* Clear the header */
        ED_area_headerprint(CTX_wm_area(C), NULL);
@@ -273,7 +278,9 @@ static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
        if (vso && vso->sel_edge) {
                /* Get 3d view */
                View3D *view3d = CTX_wm_view3d(C);
-               const int outline_w = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 1;
+               const float outline_w = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.8f;
+               const float pt_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5;
+
                int i = 0;
 
                if (view3d && view3d->zbuf)
@@ -286,17 +293,7 @@ static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
 
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-               /* Draw selected edge
-                * Add color offset and reduce alpha */
-               UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 50, -50);
-
-               glLineWidth(outline_w);
-
-               glBegin(GL_LINES);
-               bglVertex3fv(vso->sel_edge->v1->co);
-               bglVertex3fv(vso->sel_edge->v2->co);
-               glEnd();
+                       
 
                if (vso->slide_mode && vso->disk_edges > 0) {
                        /* Draw intermediate edge frame */
@@ -310,10 +307,21 @@ static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
                        }
                }
 
+                       /* Draw selected edge
+                * Add color offset and reduce alpha */
+               UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 40, -50);
+
+               glLineWidth(outline_w);
+
+               glBegin(GL_LINES);
+               bglVertex3fv(vso->sel_edge->v1->co);
+               bglVertex3fv(vso->sel_edge->v2->co);
+               glEnd();
+
                if (vso->slide_mode) {
                        /* Draw interpolated vertex */
-                       int pt_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 2;
-                       UI_ThemeColorShadeAlpha(TH_FACE_DOT, -90, -50);
+                       
+                       UI_ThemeColorShadeAlpha(TH_FACE_DOT, -80, -50);
 
                        glPointSize(pt_size);
 
@@ -377,17 +385,12 @@ static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event)
        if (nst_edge) {
                /* Find a connected edge */
                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;
                }
        }
 }
@@ -403,6 +406,7 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
        if (edge) {
                float edge_other_proj[3];
                float start_vtx_proj[3];
+               float edge_len;
                BMVert *other;
 
                float interp[3];
@@ -426,6 +430,16 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
 
                t_val = line_point_factor_v2(closest_2d, start_vtx_proj, edge_other_proj);
 
+               /* Set snap threshold to be proportional to edge length */
+               edge_len = len_v3v3(start_vtx_proj, edge_other_proj);
+               
+               if (edge_len <= 0.0f)
+                       edge_len = VTX_SLIDE_SNAP_THRSH;
+
+               edge_len =  (len_v3v3(edge->v1->co, edge->v2->co) * VTX_SLIDE_SNAP_THRSH) / edge_len;
+
+               vso->snap_threshold =  edge_len;
+
                /* Snap to mid */
                if (vso->snap_to_mid) {
                        t_val = 0.5f;
@@ -463,11 +477,12 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
 }
 
 /* Sets the outline frame */
-static void vtx_slide_set_frame(VertexSlideOp *vso)
+static int vtx_slide_set_frame(VertexSlideOp *vso)
 {
        BMEdge *edge;
        float (*vtx_frame)[3] = NULL;
        BMEdge** edge_frame = NULL;
+       BMVert *curr_vert = NULL;
        BLI_array_declare(vtx_frame);
        BLI_array_declare(edge_frame);
        BMIter iter;
@@ -491,12 +506,15 @@ static void vtx_slide_set_frame(VertexSlideOp *vso)
        /* Iterate over edges of vertex and copy them */
        BM_ITER_INDEX(edge, &iter, bm, BM_EDGES_OF_VERT, sel_vtx, idx)
        {
-               BLI_array_growone(vtx_frame);
+               curr_vert = BM_edge_other_vert(edge, sel_vtx);
+               if (curr_vert) {
+                       BLI_array_growone(vtx_frame);
 
-               copy_v3_v3(vtx_frame[idx], BM_edge_other_vert(edge, sel_vtx)->co);
+                       copy_v3_v3(vtx_frame[idx], curr_vert->co);
 
-               BLI_array_append(edge_frame, edge);
-               vso->disk_edges++;
+                       BLI_array_append(edge_frame, edge);
+                       vso->disk_edges++;
+               }
        }
 
        vso->edge_frame = edge_frame;
@@ -504,11 +522,17 @@ static void vtx_slide_set_frame(VertexSlideOp *vso)
 
        /* Set the interp at starting vtx */
        copy_v3_v3(vso->interp, sel_vtx->co);
+
+       return vso->disk_edges > 0;
 }
 
-static int edbm_vert_slide_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_vertex_slide_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
        VertexSlideOp *vso = op->customdata;
+       char buff[128];
+
+       if (!vso)
+               return OPERATOR_CANCELLED;
 
        /* Notify the viewport */
        view3d_operator_needs_opengl(C);
@@ -588,13 +612,14 @@ static int edbm_vert_slide_modal(bContext *C, wmOperator *op, wmEvent *event)
                }
                case MOUSEMOVE:
                {
+                       sprintf(buff, "Vertex Slide: %f", vso->distance);
                        if (!vso->slide_mode) {
                                vtx_slide_find_edge(vso, event);
                        }
                        else {
                                vtx_slide_update(vso, event);
                        }
-
+                       ED_area_headerprint(CTX_wm_area(C), buff);
                        ED_region_tag_redraw(vso->active_region);
                        break;
                }
@@ -603,7 +628,7 @@ static int edbm_vert_slide_modal(bContext *C, wmOperator *op, wmEvent *event)
        return OPERATOR_RUNNING_MODAL;
 }
 
-static int edbm_vert_slide_cancel(bContext *C, wmOperator *op)
+static int edbm_vertex_slide_cancel(bContext *C, wmOperator *op)
 {
        /* Exit the modal */
        vtx_slide_exit(C, op);
@@ -611,7 +636,7 @@ static int edbm_vert_slide_cancel(bContext *C, wmOperator *op)
        return OPERATOR_CANCELLED;
 }
 
-static int edbm_vert_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int edbm_vertex_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 {
        /* Initialize the operator */
        if (vtx_slide_init(C, op))
@@ -621,20 +646,20 @@ static int edbm_vert_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(e
 }
 
 /* Vertex Slide */
-static int edbm_vert_slide_exec(bContext *C, wmOperator *op)
+static int edbm_vertex_slide_exec(bContext *C, wmOperator *op)
 {
        Object *obedit = CTX_data_edit_object(C);
        BMEditMesh *em = BMEdit_FromObject(obedit);
        BMesh *bm = em->bm;
        BMVert *start_vert;
        BMOperator bmop;
-       BMEditSelection *ese = em->bm->selected.last;
+       BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last;
 
        float distance_t = 0.0f;
 
        /* Invoked modally? */
-       if (op->type->modal == edbm_vert_slide_modal && op->customdata) {
-               VertexSlideOp *vso = op->customdata;
+       if (op->type->modal == edbm_vertex_slide_modal && op->customdata) {
+               VertexSlideOp *vso = (VertexSlideOp *)op->customdata;
 
                if (bm->totedgesel > 1) {
                        /* Reset selections */
@@ -644,7 +669,7 @@ static int edbm_vert_slide_exec(bContext *C, wmOperator *op)
 
                        EDBM_editselection_store(em, &vso->sel_edge->head);
                        EDBM_editselection_store(em, &vso->start_vtx->head);                    
-                       ese = em->bm->selected.last;
+                       ese = (BMEditSelection *)em->bm->selected.last;
                }
                distance_t = vso->distance;
                RNA_float_set(op->ptr, "distance_t", distance_t);
@@ -663,13 +688,16 @@ 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=%hev distance_t=%f", start_vert, BM_ELEM_SELECT, distance_t))  {
+       if (!EDBM_op_init(em, &bmop, op, "vertex_slide vert=%e edge=%hev distance_t=%f", start_vert, BM_ELEM_SELECT, distance_t))  {
                return OPERATOR_CANCELLED;
        }
        /* Execute operator */
        BMO_op_exec(bm, &bmop);
 
-       /* Select the edge */
+       /* Deselect the input edges */
+       BMO_slot_buffer_hflag_disable(bm, &bmop, "edge", BM_ALL, BM_ELEM_SELECT, TRUE);
+
+       /* Select the output vert */
        BMO_slot_buffer_hflag_enable(bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE);
 
        /* Flush the select buffers */
@@ -695,12 +723,12 @@ void MESH_OT_vert_slide(wmOperatorType *ot)
        ot->description = "Vertex slide";
 
        /* api callback */
-       ot->invoke = edbm_vert_slide_invoke;
-       ot->modal = edbm_vert_slide_modal;
-       ot->cancel = edbm_vert_slide_cancel;
+       ot->invoke = edbm_vertex_slide_invoke;
+       ot->modal = edbm_vertex_slide_modal;
+       ot->cancel = edbm_vertex_slide_cancel;
        ot->poll = ED_operator_editmesh_region_view3d;
 
-       /* ot->exec = edbm_vert_slide_exec;
+       /* ot->exec = edbm_vertex_slide_exec;
         * ot->poll = ED_operator_editmesh; */
 
        /* flags */