Fix [#30855] Vertex Slide not using the active vertex

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.
This commit is contained in:
Francisco De La Cruz 2012-04-07 19:53:39 +00:00
parent fd37970b80
commit cbd95d8159
2 changed files with 50 additions and 31 deletions

View 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);

View 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 */