# HG changeset patch # User xerces # Date 1333430066 14400 # Node ID 314b6b0235098609bfef26eb3ee374c402fbcd5d # Parent bac7e2ddad62168f019c74e03d4d5fb8906854cd [mq]: bmesh_vertex_slide diff -r bac7e2ddad62 -r 314b6b023509 release/scripts/startup/bl_ui/space_view3d.py --- a/release/scripts/startup/bl_ui/space_view3d.py Mon Apr 02 23:24:25 2012 -0400 +++ b/release/scripts/startup/bl_ui/space_view3d.py Tue Apr 03 01:14:26 2012 -0400 @@ -1684,6 +1684,7 @@ layout.operator("mesh.split") layout.operator("mesh.separate") layout.operator("mesh.vert_connect") + layout.operator("mesh.vert_slide") layout.separator() diff -r bac7e2ddad62 -r 314b6b023509 source/blender/bmesh/CMakeLists.txt --- a/source/blender/bmesh/CMakeLists.txt Mon Apr 02 23:24:25 2012 -0400 +++ b/source/blender/bmesh/CMakeLists.txt Tue Apr 03 01:14:26 2012 -0400 @@ -36,6 +36,7 @@ set(SRC operators/bmo_bevel.c operators/bmo_connect.c + operators/bmo_slide.c operators/bmo_create.c operators/bmo_dissolve.c operators/bmo_dupe.c diff -r bac7e2ddad62 -r 314b6b023509 source/blender/bmesh/intern/bmesh_opdefines.c --- a/source/blender/bmesh/intern/bmesh_opdefines.c Mon Apr 02 23:24:25 2012 -0400 +++ b/source/blender/bmesh/intern/bmesh_opdefines.c Tue Apr 03 01:14:26 2012 -0400 @@ -1103,6 +1103,23 @@ 0 }; +/* + * Vertex Slide + * + * Translates vertes along an edge + */ +static BMOpDefine bmo_vert_slide_def = { +"vertslide", + {{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_OP_FLAG_UNTAN_MULTIRES +}; + + BMOpDefine *opdefines[] = { &bmo_split_def, &bmo_spin_def, @@ -1170,6 +1187,7 @@ &bmo_bridge_loops_def, &bmo_solidify_def, &bmo_inset_def, + &bmo_vert_slide_def, }; int bmesh_total_ops = (sizeof(opdefines) / sizeof(void *)); diff -r bac7e2ddad62 -r 314b6b023509 source/blender/bmesh/intern/bmesh_operators_private.h --- a/source/blender/bmesh/intern/bmesh_operators_private.h Mon Apr 02 23:24:25 2012 -0400 +++ b/source/blender/bmesh/intern/bmesh_operators_private.h Tue Apr 03 01:14:26 2012 -0400 @@ -43,6 +43,7 @@ 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_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); diff -r bac7e2ddad62 -r 314b6b023509 source/blender/bmesh/operators/bmo_slide.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/blender/bmesh/operators/bmo_slide.c Tue Apr 03 01:14:26 2012 -0400 @@ -0,0 +1,112 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Francisco De La Cruz + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include "MEM_guardedalloc.h" + +#include "BKE_global.h" + +#include "BLI_math.h" +#include "BLI_array.h" +#include "BLI_utildefines.h" + +#include "bmesh.h" + +#define EDGE_MARK 1 +#define VERT_MARK 2 + +/* + * Slides a vertex along a connected edge + * + */ +void bmo_vert_slide_exec(BMesh *bm, BMOperator *op) { + BMOIter oiter; + BMIter iter; + BMHeader *h; + BMVert *vertex; + BMEdge *edge; + int is_start_v1 = 0; + + /* Selection counts */ + int selected_verts = 0; + int selected_edges = 0; + + /* Get slide amount */ + const float distance_t = BMO_slot_float_get(op, "distance_t"); + + /* Get start vertex */ + vertex = BMO_iter_new(&oiter, bm, op, "vert", BM_VERT); + + + if (!vertex) { + if (G.debug & G_DEBUG) + fprintf(stderr, "vertslide: No vertex selected..."); + return; + } + + /* 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) */ + BMO_elem_flag_enable(bm, (BMElemF *) h, EDGE_MARK); + break; + } + } + + /* Only allow sliding between two verts */ + + if (selected_verts != 2 || selected_edges == 0) { + if (G.debug & G_DEBUG) + fprintf(stderr, "vertslide: select a single edge\n"); + return; + } + + /* 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; + break; + } + } + + /* Found edge */ + if (edge) { + + BMVert* other = BM_edge_other_vert(edge, vertex); + + /* mark */ + BMO_elem_flag_enable(bm, vertex, VERT_MARK); + + /* Interpolate */ + 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; +} diff -r bac7e2ddad62 -r 314b6b023509 source/blender/editors/mesh/CMakeLists.txt --- a/source/blender/editors/mesh/CMakeLists.txt Mon Apr 02 23:24:25 2012 -0400 +++ b/source/blender/editors/mesh/CMakeLists.txt Tue Apr 03 01:14:26 2012 -0400 @@ -46,6 +46,7 @@ editmesh_select.c editmesh_tools.c editmesh_utils.c + editmesh_slide.c mesh_data.c mesh_ops.c meshtools.c diff -r bac7e2ddad62 -r 314b6b023509 source/blender/editors/mesh/editmesh_slide.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/blender/editors/mesh/editmesh_slide.c Tue Apr 03 01:14:26 2012 -0400 @@ -0,0 +1,609 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Francisco De La Cruz + * + * ***** END GPL LICENSE BLOCK ***** + */ +/* Takes heavily from editmesh_loopcut.c */ + +#include +#include +#include +#include + +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" +#include "DNA_space_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_array.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_mesh.h" +#include "BKE_report.h" +#include "BKE_tessmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_mesh.h" +#include "ED_space_api.h" + +#include "UI_resources.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "mesh_intern.h" + +#define VTX_SLIDE_SLIDE_SENS_F 15.0 +#define VTX_SLIDE_SLOW_SENS_F 0.3 +#define VTX_SLIDE_SNAP_THRSH 0.3 + +static void vtx_slide_draw(const bContext *C, ARegion *ar, void *arg); +static int edbm_vert_slide_exec(bContext *C, wmOperator *op); +static void vtx_slide_exit(const bContext *C, wmOperator *op); + +/* Cusom VertexSlide Operator data */ +typedef struct VertexSlideOp { + /* Starting Vertex */ + BMVert *start_vtx; + BMEdge *sel_edge; + + ViewContext *view_context; + ARegion *active_region; + + /* Draw callback handle */ + void *draw_handle; + + /* Active Object */ + Object *obj; + + /* Are we in slide mode */ + int slide_mode; + int slow_mode; + int snap_to_end_vtx; + int snap_to_mid; + + float distance; + float interp[3]; + + /* Edge Frame + Count */ + int disk_edges; + + /* Edges */ + float (*edge_frame)[3]; + + /* Mouse Click 2d pos */ + int m_co[2]; + +} VertexSlideOp; + + +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; + + 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: Slow Move"; + + /* Allocate custom data */ + VertexSlideOp *vso; + EDBM_selectmode_flush(em); + ese = em->bm->selected.first; + + /* Is there a starting vertex ? */ + if (ese == NULL || ese->htype != BM_VERT) { + BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide Error: Select a (single) vertex"); + return FALSE; + } + + vso = MEM_callocN(sizeof(VertexSlideOp), "Vertex Slide Operator"); + vso->view_context = MEM_callocN(sizeof(ViewContext), "Vertex Slide View Context"); + + op->customdata = vso; + + /* Set the start vertex */ + vso->start_vtx = (BMVert *)ese->ele; + vso->sel_edge = NULL; + + /* Edges */ + vso->edge_frame = NULL; + + vso->disk_edges = 0; + + vso->slide_mode = FALSE; + + vso->slow_mode = FALSE; + + vso->snap_to_end_vtx = FALSE; + + vso->snap_to_mid = FALSE; + + vso->distance = 0.0f; + + /* Add handler for the vertex sliding */ + WM_event_add_modal_handler(C, op); + + /* Notify the viewport */ + view3d_operator_needs_opengl(C); + + /* Set the drawing region */ + vso->active_region = CTX_wm_region(C); + + /* Set the draw callback */ + vso->draw_handle = ED_region_draw_cb_activate(vso->active_region->type, vtx_slide_draw, vso, REGION_DRAW_POST_VIEW); + + ED_area_headerprint(CTX_wm_area(C), header_str); + + em_setup_viewcontext(C, vso->view_context); + + /* Tag for redraw */ + ED_region_tag_redraw(vso->active_region); + + /* Set the object */ + vso->obj = obedit; + + return TRUE; +} + +static void vtx_slide_confirm(bContext *C, wmOperator *op) { + /* Invoke operator */ + edbm_vert_slide_exec(C, op); +} + +static void vtx_slide_exit(const bContext *C, wmOperator *op) { + /* Fetch custom data */ + VertexSlideOp *vso = op->customdata; + BMEditMesh *em = BMEdit_FromObject(vso->obj); + + /* Clean-up the custom data */ + ED_region_draw_cb_exit(vso->active_region->type, vso->draw_handle); + ED_region_tag_redraw(vso->active_region); + + /* Store edit selection of the active vertex, allows other + * ops to run without reselecting */ + if (vso->start_vtx) + EDBM_editselection_store(em, &vso->start_vtx->head); + + /* Free Custom Data + * + */ + MEM_freeN(vso->view_context); + + vso->view_context = NULL; + + if (vso->edge_frame) { + MEM_freeN(vso->edge_frame); + } + + vso->edge_frame = NULL; + + vso->slide_mode = FALSE; + + + MEM_freeN(vso); + vso = NULL; + + /* Clear the header */ + ED_area_headerprint(CTX_wm_area(C), NULL); + +} + +static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) { + VertexSlideOp *vso = arg; + + /* Have an edge to draw */ + if (vso && vso->sel_edge) { + /* Get 3d view */ + View3D *view3d = CTX_wm_view3d(C); + int outline_w = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 1; + int i = 0; + if (view3d && view3d->zbuf) + glDisable(GL_DEPTH_TEST); + + glPushAttrib(GL_CURRENT_BIT|GL_LINE_BIT|GL_POINT_BIT); + + glPushMatrix(); + glMultMatrixf(vso->obj->obmat); + + 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->disk_edges > 0) { + /* Draw intermediate edge frame */ + UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 50, -50); + + for (i = 0; i < vso->disk_edges; i++) { + glBegin(GL_LINES); + glVertex3fv(vso->edge_frame[i]); + glVertex3fv(vso->interp); + glEnd(); + } + } + + + if (vso->slide_mode) { + /* Draw interpolated vertex */ + int pt_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 2; + UI_ThemeColorShadeAlpha(TH_FACE_DOT, -90, -50); + + glPointSize(pt_size); + + bglBegin(GL_POINTS); + bglVertex3fv(vso->interp); + bglEnd(); + } + + glDisable(GL_BLEND); + glPopMatrix(); + glPopAttrib(); + + if (view3d && view3d->zbuf) + glEnable(GL_DEPTH_TEST); + } +} + +static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event) { + /* Nearest edge */ + BMEdge *nst_edge = NULL; + + /* Temp Vtx */ + BMVert *start_vtx = vso->start_vtx; + + /* dist {input = max dist to search } + * { output = dist found } */ + int dist = 50; + + /* Set mouse coords */ + vso->view_context->mval[0] = event->mval[0]; + vso->view_context->mval[1] = event->mval[1]; + + /* Find nearest edge */ + nst_edge = EDBM_edge_find_nearest(vso->view_context, &dist); + + if (nst_edge) { + /* Find a connected edge */ + if (nst_edge->v1 == start_vtx || nst_edge->v2 == start_vtx) { + /* Save mouse coords */ + vso->m_co[0] = event->mval[0]; + vso->m_co[1] = event->mval[1]; + + /* Set edge */ + vso->sel_edge = nst_edge; + } + } +} + +/* Updates the status of the operator - Invoked on mouse movement */ +static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event) { + BMEdge* edge; + float edge_other_proj[3]; + float start_vtx_proj[3]; + BMVert* other; + /* Find nearest edge */ + edge = vso->sel_edge; + + if (edge) { + float interp[3]; + + /* Calculate interpolation value for preview */ + float t_val; + + float mval_float[] = { (float)event->mval[0], (float)event->mval[1]}; + float closest_2d[2]; + + other = BM_edge_other_vert(edge, vso->start_vtx); + + /* Project points onto screen and do interpolation in 2D */ + project_float_noclip(vso->active_region, vso->start_vtx->co, start_vtx_proj); + + project_float_noclip(vso->active_region, other->co, edge_other_proj); + + closest_to_line_v2(closest_2d, mval_float, start_vtx_proj, edge_other_proj); + + t_val = line_point_factor_v2(closest_2d, start_vtx_proj, edge_other_proj); + + if (vso->slow_mode) + t_val = t_val * VTX_SLIDE_SLOW_SENS_F; + + /* Snap to mid */ + if (vso->snap_to_mid) { + t_val = 0.5f; + } + + /* Interpolate preview vertex 3D */ + interp_v3_v3v3(interp, vso->start_vtx->co, other->co, t_val); + copy_v3_v3(vso->interp, interp); + + vso->distance = t_val; + + /* If snapping */ + if (vso->snap_to_end_vtx) { + int start_at_v1 = edge->v1 == vso->start_vtx; + 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) { + copy_v3_v3(vso->interp, edge->v2->co); + + if (start_at_v1) + vso->distance = 1.0f; + else + vso->distance = 0.0f; + } + if (v2_d > v1_d && v1_d < VTX_SLIDE_SNAP_THRSH) { + copy_v3_v3(vso->interp, edge->v1->co); + if (start_at_v1) + vso->distance = 0.0f; + else + vso->distance = 1.0f; + } + } + } +} + +/* Sets the outline frame */ +static void vtx_slide_set_frame(VertexSlideOp *vso) { + BMEdge* edge; + float (*edge_frame)[3] = NULL; + BLI_array_declare(edge_frame); + BMIter iter; + BMEditMesh *em = BMEdit_FromObject(vso->obj); + BMesh* bm = em->bm; + BMVert* sel_vtx = vso->start_vtx; + int idx = 0; + + vso->disk_edges = 0; + + if (vso->edge_frame) { + MEM_freeN(vso->edge_frame); + vso->edge_frame = NULL; + } + + /* Iterate over edges of vertex and copy them */ + BM_ITER_INDEX(edge, &iter, bm, BM_EDGES_OF_VERT, sel_vtx, idx) { + /* TODO: Deallocate this array */ + BLI_array_growone(edge_frame); + + if (sel_vtx == edge->v1) + copy_v3_v3(edge_frame[idx], edge->v2->co); + else + copy_v3_v3(edge_frame[idx], edge->v1->co); + + vso->disk_edges++; + } + + vso->edge_frame = edge_frame; + + /* Select new edge */ + BM_edge_select_set(bm, vso->sel_edge, TRUE); + + /* Set the interp at starting vtx */ + copy_v3_v3(vso->interp, sel_vtx->co); + +} + +static int edbm_vert_slide_modal(bContext *C, wmOperator *op, wmEvent *event) { + VertexSlideOp *vso = op->customdata; + + /* Notify the viewport */ + view3d_operator_needs_opengl(C); + + switch (event->type) { + case LEFTSHIFTKEY: { + switch (event->val) { + case KM_PRESS: + vso->snap_to_mid = TRUE; + break; + case KM_RELEASE: + vso->snap_to_mid = FALSE; + break; + } + + break; + } + case LEFTCTRLKEY: { + switch (event->val) { + case KM_PRESS: + vso->slow_mode = TRUE; + break; + case KM_RELEASE: + vso->slow_mode = FALSE; + break; + } + + break; + } + case LEFTALTKEY: { + switch (event->val) { + case KM_PRESS: + vso->snap_to_end_vtx = TRUE; + break; + case KM_RELEASE: + vso->snap_to_end_vtx = FALSE; + break; + } + + break; + } + case RIGHTMOUSE: { + /* Enforce redraw */ + ED_region_tag_redraw(vso->active_region); + + /* Clean-up */ + vtx_slide_exit(C, op); + + return OPERATOR_CANCELLED; + } + case LEFTMOUSE: { + if (event->val == KM_PRESS) { + /* Update mouse coords */ + copy_v2_v2_int(vso->m_co, event->mval); + + if (vso->slide_mode) { + vtx_slide_confirm(C, op); + /* Clean-up */ + vtx_slide_exit(C, op); + return OPERATOR_FINISHED; + } else if (vso->sel_edge) { + vso->slide_mode = TRUE; + + /* Sets the frame */ + vtx_slide_set_frame(vso); + } + } + + ED_region_tag_redraw(vso->active_region); + break; + + } + case MOUSEMOVE: { + if (!vso->slide_mode) { + vtx_slide_find_edge(vso, event); + } else { + vtx_slide_update(vso, event); + } + + ED_region_tag_redraw(vso->active_region); + break; + } + } + + return OPERATOR_RUNNING_MODAL; +} + +static int edbm_vert_slide_cancel(bContext *C, wmOperator *op) { + /* Exit the modal */ + vtx_slide_exit(C, op); + + return OPERATOR_CANCELLED; +} + +static int edbm_vert_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { + + /* Initialize the operator */ + if (vtx_slide_init(C, op)) + return OPERATOR_RUNNING_MODAL; + else + return OPERATOR_CANCELLED; +} + +/* Vertex Slide */ +static int edbm_vert_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.first; + + float distance_t = 0.0f; + + /* Invoked modally? */ + if (op->type->modal == edbm_vert_slide_modal && op->customdata) { + VertexSlideOp *vso = op->customdata; + distance_t = vso->distance; + } else { + /* Get Properties */ + distance_t = RNA_float_get(op->ptr, "distance_t"); + } + + /* Is there a starting vertex ? */ + if (ese == NULL || ese->htype != BM_VERT) { + BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide Error: Select a (single) vertex"); + return OPERATOR_CANCELLED; + } + + 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)) { + return OPERATOR_CANCELLED; + } + /* Execute operator */ + BMO_op_exec(bm, &bmop); + + /* Select the edge */ + BMO_slot_buffer_hflag_enable(bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + + /* Flush the select buffers */ + EDBM_selectmode_flush(em); + + if (!EDBM_op_finish(em, &bmop, op, TRUE)) { + return OPERATOR_CANCELLED; + } + + /* Update Geometry */ + EDBM_update_generic(C, em, TRUE); + + return OPERATOR_FINISHED; +} + +void MESH_OT_vert_slide(wmOperatorType *ot) { + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Vertex Slide"; + ot->idname = "MESH_OT_vert_slide"; + 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->poll = ED_operator_editmesh_region_view3d; + + /* ot->exec = edbm_vert_slide_exec; + * ot->poll = ED_operator_editmesh; */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties for vertex slide */ + prop = RNA_def_float(ot->srna, "distance_t", 0.0f, -FLT_MAX, FLT_MAX , "Distance", "Distance", -5.0f, 5.0f); + RNA_def_property_ui_range(prop, -5.0f, 5.0f, 0.1, 4); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} diff -r bac7e2ddad62 -r 314b6b023509 source/blender/editors/mesh/mesh_intern.h --- a/source/blender/editors/mesh/mesh_intern.h Mon Apr 02 23:24:25 2012 -0400 +++ b/source/blender/editors/mesh/mesh_intern.h Tue Apr 03 01:14:26 2012 -0400 @@ -214,6 +214,7 @@ void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot); void MESH_OT_inset(struct wmOperatorType *ot); +void MESH_OT_vert_slide(struct wmOperatorType *ot); /* ******************* mesh_navmesh.c */ void MESH_OT_navmesh_make(struct wmOperatorType *ot); diff -r bac7e2ddad62 -r 314b6b023509 source/blender/editors/mesh/mesh_ops.c --- a/source/blender/editors/mesh/mesh_ops.c Mon Apr 02 23:24:25 2012 -0400 +++ b/source/blender/editors/mesh/mesh_ops.c Tue Apr 03 01:14:26 2012 -0400 @@ -155,6 +155,7 @@ 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_slide); WM_operatortype_append(MESH_OT_knifetool); WM_operatortype_append(MESH_OT_bevel); @@ -335,6 +336,8 @@ 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); + /* Vertex Slide */ + WM_keymap_add_item(keymap, "MESH_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); /* use KM_CLICK because same key is used for tweaks */ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", TRUE);