static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; struct { Object *ob; BMElem *ele; float dist; int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; struct { int base_index; int vert_index; int edge_index; int face_index; } prev = { .base_index = gz_ele->base_index, .vert_index = gz_ele->vert_index, .edge_index = gz_ele->edge_index, .face_index = gz_ele->face_index, }; { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); if (((gz_ele->bases)) == NULL || (gz_ele->bases[0] != view_layer->basact)) { MEM_SAFE_FREE(gz_ele->bases); gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, v3d, &gz_ele->bases_len); } } ViewContext vc; em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); { /* TODO: support faces. */ int base_index = -1; BMVert *eve_test; BMEdge *eed_test; if (EDBM_unified_findnearest_from_raycast(&vc, gz_ele->bases, gz_ele->bases_len, true, &base_index, &eve_test, &eed_test, NULL)) { Base *base = gz_ele->bases[base_index]; best.ob = base->object; if (eve_test) { best.ele = (BMElem *)eve_test; } else if (eed_test) { best.ele = (BMElem *)eed_test; } else { BLI_assert(0); } best.base_index = base_index; /* Check above should never fail, if it does it's an internal error. */ BLI_assert(best.base_index != -1); } } BMesh *bm = NULL; gz_ele->base_index = -1; gz_ele->vert_index = -1; gz_ele->edge_index = -1; gz_ele->face_index = -1; if (best.ele) { gz_ele->base_index = best.base_index; bm = BKE_editmesh_from_object(gz_ele->bases[gz_ele->base_index]->object)->bm; BM_mesh_elem_index_ensure(bm, best.ele->head.htype); if (best.ele->head.htype == BM_VERT) { gz_ele->vert_index = BM_elem_index_get(best.ele); } else if (best.ele->head.htype == BM_EDGE) { gz_ele->edge_index = BM_elem_index_get(best.ele); } else if (best.ele->head.htype == BM_FACE) { gz_ele->face_index = BM_elem_index_get(best.ele); } } if ((prev.base_index == gz_ele->base_index) && (prev.vert_index == gz_ele->vert_index) && (prev.edge_index == gz_ele->edge_index) && (prev.face_index == gz_ele->face_index)) { /* pass (only recalculate on change) */ } else { if (best.ele) { const float(*coords)[3] = NULL; { Object *ob = gz_ele->bases[gz_ele->base_index]->object; Depsgraph *depsgraph = CTX_data_depsgraph(C); Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); if (me_eval->runtime.edit_data) { coords = me_eval->runtime.edit_data->vertexCos; } } EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); } else { EDBM_preselect_elem_clear(gz_ele->psel); } RNA_int_set(gz->ptr, "object_index", gz_ele->base_index); RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } // return best.eed ? 0 : -1; return -1; } static void gizmo_preselect_elem_setup(wmGizmo *gz) { MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; if (gz_ele->psel == NULL) { gz_ele->psel = EDBM_preselect_elem_create(); } gz_ele->base_index = -1; }
static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) { ViewContext vc; EditVert *eve; float min[3], max[3]; int done= 0; short use_proj; em_setup_viewcontext(C, &vc); use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) && (vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE); invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); INIT_MINMAX(min, max); for(eve= vc.em->verts.first; eve; eve= eve->next) { if(eve->f & SELECT) { DO_MINMAX(eve->co, min, max); done= 1; } } /* call extrude? */ if(done) { const short rot_src= RNA_boolean_get(op->ptr, "rotate_source"); EditEdge *eed; float vec[3], cent[3], mat[3][3]; float nor[3]= {0.0, 0.0, 0.0}; /* 2D normal calc */ float mval_f[2]; mval_f[0]= (float)event->mval[0]; mval_f[1]= (float)event->mval[1]; done= 0; /* calculate the normal for selected edges */ for(eed= vc.em->edges.first; eed; eed= eed->next) { if(eed->f & SELECT) { float co1[3], co2[3]; mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co); mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co); project_float_noclip(vc.ar, co1, co1); project_float_noclip(vc.ar, co2, co2); /* 2D rotate by 90d while adding. * (x, y) = (y, -x) * * accumulate the screenspace normal in 2D, * with screenspace edge length weighting the result. */ if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) { nor[0] += (co1[1] - co2[1]); nor[1] += -(co1[0] - co2[0]); } else { nor[0] += (co2[1] - co1[1]); nor[1] += -(co2[0] - co1[0]); } done= 1; } } if(done) { float view_vec[3], cross[3]; /* convert the 2D nomal into 3D */ mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */ mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */ /* correct the normal to be aligned on the view plane */ copy_v3_v3(view_vec, vc.rv3d->viewinv[2]); mul_mat3_m4_v3(vc.obedit->imat, view_vec); cross_v3_v3v3(cross, nor, view_vec); cross_v3_v3v3(nor, view_vec, cross); normalize_v3(nor); } /* center */ mid_v3_v3v3(cent, min, max); copy_v3_v3(min, cent); mul_m4_v3(vc.obedit->obmat, min); // view space view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE); mul_m4_v3(vc.obedit->imat, min); // back in object space sub_v3_v3(min, cent); /* calculate rotation */ unit_m3(mat); if(done) { float dot; copy_v3_v3(vec, min); normalize_v3(vec); dot= dot_v3v3(vec, nor); if( fabs(dot)<0.999) { float cross[3], si, q1[4]; cross_v3_v3v3(cross, nor, vec); normalize_v3(cross); dot= 0.5f*saacos(dot); /* halve the rotation if its applied twice */ if(rot_src) dot *= 0.5f; si= (float)sin(dot); q1[0]= (float)cos(dot); q1[1]= cross[0]*si; q1[2]= cross[1]*si; q1[3]= cross[2]*si; quat_to_mat3( mat,q1); } } if(rot_src) { rotateflag(vc.em, SELECT, cent, mat); /* also project the source, for retopo workflow */ if(use_proj) EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); } extrudeflag(vc.obedit, vc.em, SELECT, nor, 0); rotateflag(vc.em, SELECT, cent, mat); translateflag(vc.em, SELECT, min); recalc_editnormals(vc.em); } else if(vc.em->selectmode & SCE_SELECT_VERTEX) { float imat[4][4]; const float *curs= give_cursor(vc.scene, vc.v3d); copy_v3_v3(min, curs); view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE); eve= addvertlist(vc.em, 0, NULL); invert_m4_m4(imat, vc.obedit->obmat); mul_v3_m4v3(eve->co, imat, min); eve->f= SELECT; } if(use_proj) EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); DAG_id_tag_update(vc.obedit->data, 0); return OPERATOR_FINISHED; }
static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; struct { Object *ob; BMEdge *eed; float dist; int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; struct { int base_index; int edge_index; } prev = { .base_index = gz_ring->base_index, .edge_index = gz_ring->edge_index, }; { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); if (((gz_ring->bases)) == NULL || (gz_ring->bases[0] != view_layer->basact)) { MEM_SAFE_FREE(gz_ring->bases); gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, v3d, &gz_ring->bases_len); } } ViewContext vc; em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); uint base_index; BMEdge *eed_test = EDBM_edge_find_nearest_ex( &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index); if (eed_test) { best.ob = gz_ring->bases[base_index]->object; best.eed = eed_test; best.base_index = base_index; } BMesh *bm = NULL; if (best.eed) { gz_ring->base_index = best.base_index; bm = BKE_editmesh_from_object(gz_ring->bases[gz_ring->base_index]->object)->bm; BM_mesh_elem_index_ensure(bm, BM_EDGE); gz_ring->edge_index = BM_elem_index_get(best.eed); } else { gz_ring->base_index = -1; gz_ring->edge_index = -1; } if ((prev.base_index == gz_ring->base_index) && (prev.edge_index == gz_ring->edge_index)) { /* pass (only recalculate on change) */ } else { if (best.eed) { const float(*coords)[3] = NULL; { Object *ob = gz_ring->bases[gz_ring->base_index]->object; Depsgraph *depsgraph = CTX_data_depsgraph(C); Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); if (me_eval->runtime.edit_data) { coords = me_eval->runtime.edit_data->vertexCos; } } EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords); } else { EDBM_preselect_edgering_clear(gz_ring->psel); } RNA_int_set(gz->ptr, "object_index", gz_ring->base_index); RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index); ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } // return best.eed ? 0 : -1; return -1; } static void gizmo_preselect_edgering_setup(wmGizmo *gz) { MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; if (gz_ring->psel == NULL) { gz_ring->psel = EDBM_preselect_edgering_create(); } gz_ring->base_index = -1; }