diff options
Diffstat (limited to 'source/blender/editors/mesh/editmesh_rip_edge.c')
-rw-r--r-- | source/blender/editors/mesh/editmesh_rip_edge.c | 348 |
1 files changed, 173 insertions, 175 deletions
diff --git a/source/blender/editors/mesh/editmesh_rip_edge.c b/source/blender/editors/mesh/editmesh_rip_edge.c index e449f96bc05..e2b77d8c83b 100644 --- a/source/blender/editors/mesh/editmesh_rip_edge.c +++ b/source/blender/editors/mesh/editmesh_rip_edge.c @@ -40,213 +40,211 @@ #include "bmesh.h" -#include "mesh_intern.h" /* own include */ +#include "mesh_intern.h" /* own include */ /* uses total number of selected edges around a vertex to choose how to extend */ #define USE_TRICKY_EXTEND static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMesh *bm = em->bm; - - BMIter viter; - BMVert *v; - const float mval_fl[2] = { UNPACK2(event->mval) }; - float cent_sco[2]; - int cent_tot; - bool changed = false; - - /* mouse direction to view center */ - float mval_dir[2]; - - float projectMat[4][4]; - - if (bm->totvertsel == 0) - continue; - - ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); - - zero_v2(cent_sco); - cent_tot = 0; - - /* clear tags and calc screen center */ - BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(v, BM_ELEM_TAG); - - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - float v_sco[2]; - ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat); - - add_v2_v2(cent_sco, v_sco); - cent_tot += 1; - } - } - mul_v2_fl(cent_sco, 1.0f / (float)cent_tot); - - /* not essential, but gives more expected results with edge selection */ - if (bm->totedgesel) { - /* angle against center can give odd result, - * try re-position the center to the closest edge */ - BMIter eiter; - BMEdge *e; - float dist_sq_best = len_squared_v2v2(cent_sco, mval_fl); - - BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - float e_sco[2][2]; - float cent_sco_test[2]; - float dist_sq_test; - - ED_view3d_project_float_v2_m4(ar, e->v1->co, e_sco[0], projectMat); - ED_view3d_project_float_v2_m4(ar, e->v2->co, e_sco[1], projectMat); - - closest_to_line_segment_v2(cent_sco_test, mval_fl, e_sco[0], e_sco[1]); - dist_sq_test = len_squared_v2v2(cent_sco_test, mval_fl); - if (dist_sq_test < dist_sq_best) { - dist_sq_best = dist_sq_test; - - /* we have a new screen center */ - copy_v2_v2(cent_sco, cent_sco_test); - } - } - } - } - - sub_v2_v2v2(mval_dir, mval_fl, cent_sco); - normalize_v2(mval_dir); - - /* operate on selected verts */ - BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) { - BMIter eiter; - BMEdge *e; - float v_sco[2]; - - if (BM_elem_flag_test(v, BM_ELEM_SELECT) && - BM_elem_flag_test(v, BM_ELEM_TAG) == false) - { - /* Rules for */ - float angle_best = FLT_MAX; - BMEdge *e_best = NULL; + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + + BMIter viter; + BMVert *v; + const float mval_fl[2] = {UNPACK2(event->mval)}; + float cent_sco[2]; + int cent_tot; + bool changed = false; + + /* mouse direction to view center */ + float mval_dir[2]; + + float projectMat[4][4]; + + if (bm->totvertsel == 0) + continue; + + ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); + + zero_v2(cent_sco); + cent_tot = 0; + + /* clear tags and calc screen center */ + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_disable(v, BM_ELEM_TAG); + + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + float v_sco[2]; + ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat); + + add_v2_v2(cent_sco, v_sco); + cent_tot += 1; + } + } + mul_v2_fl(cent_sco, 1.0f / (float)cent_tot); + + /* not essential, but gives more expected results with edge selection */ + if (bm->totedgesel) { + /* angle against center can give odd result, + * try re-position the center to the closest edge */ + BMIter eiter; + BMEdge *e; + float dist_sq_best = len_squared_v2v2(cent_sco, mval_fl); + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + float e_sco[2][2]; + float cent_sco_test[2]; + float dist_sq_test; + + ED_view3d_project_float_v2_m4(ar, e->v1->co, e_sco[0], projectMat); + ED_view3d_project_float_v2_m4(ar, e->v2->co, e_sco[1], projectMat); + + closest_to_line_segment_v2(cent_sco_test, mval_fl, e_sco[0], e_sco[1]); + dist_sq_test = len_squared_v2v2(cent_sco_test, mval_fl); + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + + /* we have a new screen center */ + copy_v2_v2(cent_sco, cent_sco_test); + } + } + } + } + + sub_v2_v2v2(mval_dir, mval_fl, cent_sco); + normalize_v2(mval_dir); + + /* operate on selected verts */ + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BMIter eiter; + BMEdge *e; + float v_sco[2]; + + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && BM_elem_flag_test(v, BM_ELEM_TAG) == false) { + /* Rules for */ + float angle_best = FLT_MAX; + BMEdge *e_best = NULL; #ifdef USE_TRICKY_EXTEND - /* first check if we can select the edge to split based on selection-only */ - int tot_sel = 0, tot = 0; - - BM_ITER_ELEM(e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - e_best = e; - tot_sel += 1; - } - tot += 1; - } - } - if (tot_sel != 1) { - e_best = NULL; - } - - /* only one edge selected, operate on that */ - if (e_best) { - goto found_edge; - } - /* none selected, fall through and find one */ - else if (tot_sel == 0) { - /* pass */ - } - /* selection not 0 or 1, do nothing */ - else { - goto found_edge; - } + /* first check if we can select the edge to split based on selection-only */ + int tot_sel = 0, tot = 0; + + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + e_best = e; + tot_sel += 1; + } + tot += 1; + } + } + if (tot_sel != 1) { + e_best = NULL; + } + + /* only one edge selected, operate on that */ + if (e_best) { + goto found_edge; + } + /* none selected, fall through and find one */ + else if (tot_sel == 0) { + /* pass */ + } + /* selection not 0 or 1, do nothing */ + else { + goto found_edge; + } #endif - ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat); + ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat); - BM_ITER_ELEM(e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - BMVert *v_other = BM_edge_other_vert(e, v); - float v_other_sco[2]; - float angle_test; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + BMVert *v_other = BM_edge_other_vert(e, v); + float v_other_sco[2]; + float angle_test; - ED_view3d_project_float_v2_m4(ar, v_other->co, v_other_sco, projectMat); + ED_view3d_project_float_v2_m4(ar, v_other->co, v_other_sco, projectMat); - /* avoid comparing with view-axis aligned edges (less than a pixel) */ - if (len_squared_v2v2(v_sco, v_other_sco) > 1.0f) { - float v_dir[2]; + /* avoid comparing with view-axis aligned edges (less than a pixel) */ + if (len_squared_v2v2(v_sco, v_other_sco) > 1.0f) { + float v_dir[2]; - sub_v2_v2v2(v_dir, v_other_sco, v_sco); - normalize_v2(v_dir); + sub_v2_v2v2(v_dir, v_other_sco, v_sco); + normalize_v2(v_dir); - angle_test = angle_normalized_v2v2(mval_dir, v_dir); + angle_test = angle_normalized_v2v2(mval_dir, v_dir); - if (angle_test < angle_best) { - angle_best = angle_test; - e_best = e; - } - } - } - } + if (angle_test < angle_best) { + angle_best = angle_test; + e_best = e; + } + } + } + } #ifdef USE_TRICKY_EXTEND -found_edge : + found_edge: #endif - if (e_best) { - const bool e_select = BM_elem_flag_test_bool(e_best, BM_ELEM_SELECT); - BMVert *v_new; - BMEdge *e_new; + if (e_best) { + const bool e_select = BM_elem_flag_test_bool(e_best, BM_ELEM_SELECT); + BMVert *v_new; + BMEdge *e_new; - v_new = BM_edge_split(bm, e_best, v, &e_new, 0.0f); + v_new = BM_edge_split(bm, e_best, v, &e_new, 0.0f); - BM_vert_select_set(bm, v, false); - BM_edge_select_set(bm, e_new, false); + BM_vert_select_set(bm, v, false); + BM_edge_select_set(bm, e_new, false); - BM_vert_select_set(bm, v_new, true); - if (e_select) { - BM_edge_select_set(bm, e_best, true); - } - BM_elem_flag_enable(v_new, BM_ELEM_TAG); /* prevent further splitting */ + BM_vert_select_set(bm, v_new, true); + if (e_select) { + BM_edge_select_set(bm, e_best, true); + } + BM_elem_flag_enable(v_new, BM_ELEM_TAG); /* prevent further splitting */ - changed = true; - } - } - } + changed = true; + } + } + } - if (changed) { - BM_select_history_clear(bm); + if (changed) { + BM_select_history_clear(bm); - BM_mesh_select_mode_flush(bm); + BM_mesh_select_mode_flush(bm); - EDBM_update_generic(em, true, true); - } - } + EDBM_update_generic(em, true, true); + } + } - MEM_freeN(objects); + MEM_freeN(objects); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } - void MESH_OT_rip_edge(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Extend Vertices"; - ot->idname = "MESH_OT_rip_edge"; - ot->description = "Extend vertices along the edge closest to the cursor"; + /* identifiers */ + ot->name = "Extend Vertices"; + ot->idname = "MESH_OT_rip_edge"; + ot->description = "Extend vertices along the edge closest to the cursor"; - /* api callbacks */ - ot->invoke = edbm_rip_edge_invoke; - ot->poll = EDBM_view3d_poll; + /* api callbacks */ + ot->invoke = edbm_rip_edge_invoke; + ot->poll = EDBM_view3d_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* to give to transform */ - Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); + /* to give to transform */ + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); } |