Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_view3d/view3d_select.cc
| Context not available. | |||||
| /** \name Internal Edit-Mesh Utilities | /** \name Internal Edit-Mesh Utilities | ||||
| * \{ */ | * \{ */ | ||||
| struct BoxSelectUserData { | |||||
| ViewContext *vc; | |||||
| const rcti *rect; | |||||
| const rctf *rect_fl; | |||||
| rctf _rect_fl; | |||||
| eSelectOp sel_op; | |||||
| eBezTriple_Flag select_flag; | |||||
| int edge_style; | |||||
| int face_style; | |||||
| /* runtime */ | |||||
| bool is_done; | |||||
| bool is_changed; | |||||
| }; | |||||
| struct LassoSelectUserData { | |||||
| ViewContext *vc; | |||||
| const rcti *rect; | |||||
| const rctf *rect_fl; | |||||
| rctf _rect_fl; | |||||
| const int (*mcoords)[2]; | |||||
| int mcoords_len; | |||||
| eSelectOp sel_op; | |||||
| eBezTriple_Flag select_flag; | |||||
| int edge_style; | |||||
| int face_style; | |||||
| /* runtime */ | |||||
| int pass; | |||||
| bool is_done; | |||||
| bool is_changed; | |||||
| }; | |||||
| struct CircleSelectUserData { | |||||
| ViewContext *vc; | |||||
| bool select; | |||||
| int mval[2]; | |||||
| float mval_fl[2]; | |||||
| float radius; | |||||
| float radius_squared; | |||||
| eBezTriple_Flag select_flag; | |||||
| int edge_style; | |||||
| int face_style; | |||||
| /* runtime */ | |||||
| bool is_changed; | |||||
| }; | |||||
| static bool edbm_backbuf_check_and_select_verts(EditSelectBuf_Cache *esel, | static bool edbm_backbuf_check_and_select_verts(EditSelectBuf_Cache *esel, | ||||
| Depsgraph *depsgraph, | Depsgraph *depsgraph, | ||||
| Object *ob, | Object *ob, | ||||
| Context not available. | |||||
| return changed; | return changed; | ||||
| } | } | ||||
| static bool edbm_backbuf_check_and_select_edges(EditSelectBuf_Cache *esel, | static bool edbm_backbuf_check_and_select_edges(void *userData, | ||||
| EditSelectBuf_Cache *esel, | |||||
| Depsgraph *depsgraph, | Depsgraph *depsgraph, | ||||
| Object *ob, | Object *ob, | ||||
| BMEditMesh *em, | BMEditMesh *em, | ||||
| const eSelectOp sel_op) | const eSelectOp sel_op) | ||||
| { | { | ||||
| CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); | |||||
| BMEdge *eed; | BMEdge *eed; | ||||
| BMIter iter; | BMVert *eve; | ||||
| BMIter iter, viter; | |||||
| bool changed = false; | bool changed = false; | ||||
| int style = data->edge_style; | |||||
| const BLI_bitmap *select_bitmap = esel->select_bitmap; | const BLI_bitmap *select_bitmap = esel->select_bitmap; | ||||
| uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); | uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); | ||||
| Context not available. | |||||
| if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { | if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { | ||||
| const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); | const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); | ||||
| const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); | const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); | ||||
| const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); | bool enclose_edge = true; | ||||
| /* enclose edge */ | |||||
| if (style == 4 && is_inside) { | |||||
| BM_ITER_ELEM (eve, &viter, eed, BM_VERTS_OF_EDGE) { | |||||
| float vertv3[3] = {eve->co[0], eve->co[1], eve->co[2]}; | |||||
| float vertv2[2] = {0.0f, 0.0f}; | |||||
| ED_view3d_project_float_object( | |||||
| data->vc->region, vertv3, vertv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| enclose_edge = len_squared_v2v2(data->mval_fl, vertv2) <= data->radius_squared; | |||||
| if (!enclose_edge) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| const int sel_op_result = ED_select_op_action_deselected( | |||||
| sel_op, is_select, is_inside && enclose_edge); | |||||
| if (sel_op_result != -1) { | if (sel_op_result != -1) { | ||||
| BM_edge_select_set(em->bm, eed, sel_op_result); | BM_edge_select_set(em->bm, eed, sel_op_result); | ||||
| changed = true; | changed = true; | ||||
| Context not available. | |||||
| return changed; | return changed; | ||||
| } | } | ||||
| static bool edbm_backbuf_check_and_select_faces(EditSelectBuf_Cache *esel, | static bool edbm_backbuf_check_and_select_faces(ViewContext *vc, | ||||
| EditSelectBuf_Cache *esel, | |||||
| Depsgraph *depsgraph, | Depsgraph *depsgraph, | ||||
| Object *ob, | Object *ob, | ||||
| BMEditMesh *em, | BMEditMesh *em, | ||||
| const eSelectOp sel_op) | const eSelectOp sel_op, | ||||
| const rcti *rect, | |||||
| const int face_style, | |||||
| void *lassoData, | |||||
| void *circleData) | |||||
| { | { | ||||
| BMIter iter, viter; | |||||
| BMFace *efa; | BMFace *efa; | ||||
| BMIter iter; | BMVert *eve; | ||||
| bool changed = false; | bool changed = false; | ||||
| const BLI_bitmap *select_bitmap = esel->select_bitmap; | const BLI_bitmap *select_bitmap = esel->select_bitmap; | ||||
| rctf rectf; | |||||
| LassoSelectUserData *ldata = static_cast<LassoSelectUserData *>(lassoData); | |||||
| CircleSelectUserData *cdata = static_cast<CircleSelectUserData *>(circleData); | |||||
| uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_FACE); | uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_FACE); | ||||
| if (index == 0) { | uint vindex = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_VERTEX); | ||||
| int style = face_style; | |||||
| if (rect != NULL) { | |||||
| BLI_rctf_rcti_copy(&rectf, rect); | |||||
| } | |||||
| if (index == 0 || vindex == 0) { | |||||
| return false; | return false; | ||||
| } | } | ||||
| index -= 1; | index -= 1; | ||||
| vindex -= 1; | |||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { | if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { | ||||
| const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); | const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); | ||||
| const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); | const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); | ||||
| const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); | bool enclose_face = true; | ||||
| bool center_face = true; | |||||
| if (style > 2 && is_inside) { | |||||
| /* enclose face */ | |||||
| if (style == 4) { | |||||
| BM_ITER_ELEM (eve, &viter, efa, BM_VERTS_OF_FACE) { | |||||
| /* circle enclose */ | |||||
| if (cdata != NULL) { | |||||
| float vertv3[3] = {eve->co[0], eve->co[1], eve->co[2]}; | |||||
| float vertv2[2] = {0.0f, 0.0f}; | |||||
| ED_view3d_project_float_object( | |||||
| vc->region, vertv3, vertv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| enclose_face = len_squared_v2v2(cdata->mval_fl, vertv2) <= cdata->radius_squared; | |||||
| if (!enclose_face) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* box and lasso enclose */ | |||||
| else { | |||||
| if (!BLI_BITMAP_TEST_BOOL(select_bitmap, vindex + BM_elem_index_get(eve))) { | |||||
| enclose_face = false; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* center face */ | |||||
| else { | |||||
| float centerv3[3] = {0.0f, 0.0f, 0.0f}; | |||||
| float centerv2[2] = {0.0f, 0.0f}; | |||||
| /* tri */ | |||||
| if (efa->len == 3) { | |||||
| float tri_vco[3][3] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; | |||||
| int tri_index = 0; | |||||
| BM_ITER_ELEM (eve, &viter, efa, BM_VERTS_OF_FACE) { | |||||
| tri_vco[tri_index][0] = eve->co[0]; | |||||
| tri_vco[tri_index][1] = eve->co[1]; | |||||
| tri_vco[tri_index][2] = eve->co[2]; | |||||
| tri_index++; | |||||
| } | |||||
| float triv1[3] = {tri_vco[0][0], tri_vco[0][1], tri_vco[0][2]}; | |||||
| float triv2[3] = {tri_vco[1][0], tri_vco[1][1], tri_vco[1][2]}; | |||||
| float triv3[3] = {tri_vco[2][0], tri_vco[2][1], tri_vco[2][2]}; | |||||
| mid_v3_v3v3v3(centerv3, triv1, triv2, triv3); | |||||
| } | |||||
| /* quad */ | |||||
| else if (efa->len == 4) { | |||||
| float quad_vco[4][3] = { | |||||
| 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; | |||||
| int quad_index = 0; | |||||
| BM_ITER_ELEM (eve, &viter, efa, BM_VERTS_OF_FACE) { | |||||
| quad_vco[quad_index][0] = eve->co[0]; | |||||
| quad_vco[quad_index][1] = eve->co[1]; | |||||
| quad_vco[quad_index][2] = eve->co[2]; | |||||
| quad_index++; | |||||
| } | |||||
| float quadv1[3] = {quad_vco[0][0], quad_vco[0][1], quad_vco[0][2]}; | |||||
| float quadv2[3] = {quad_vco[1][0], quad_vco[1][1], quad_vco[1][2]}; | |||||
| float quadv3[3] = {quad_vco[2][0], quad_vco[2][1], quad_vco[2][2]}; | |||||
| float quadv4[3] = {quad_vco[3][0], quad_vco[3][1], quad_vco[3][2]}; | |||||
| mid_v3_v3v3v3v3(centerv3, quadv1, quadv2, quadv3, quadv4); | |||||
| } | |||||
| /* ngon */ | |||||
| else { | |||||
| const float w = 1.0f / (float)efa->len; | |||||
| BM_ITER_ELEM (eve, &viter, efa, BM_VERTS_OF_FACE) { | |||||
| madd_v3_v3fl(centerv3, eve->co, w); | |||||
| } | |||||
| } | |||||
| ED_view3d_project_float_object( | |||||
| vc->region, centerv3, centerv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| /* lasso center */ | |||||
| if (lassoData != NULL) { | |||||
| center_face = BLI_rctf_isect_pt_v(&rectf, centerv2) && | |||||
| BLI_lasso_is_point_inside(ldata->mcoords, | |||||
| ldata->mcoords_len, | |||||
| centerv2[0], | |||||
| centerv2[1], | |||||
| IS_CLIPPED); | |||||
| } | |||||
| /* circle center */ | |||||
| else if (circleData != NULL) { | |||||
| center_face = (len_squared_v2v2(cdata->mval_fl, centerv2) <= cdata->radius_squared); | |||||
| } | |||||
| /* box center */ | |||||
| else { | |||||
| center_face = BLI_rctf_isect_pt_v(&rectf, centerv2); | |||||
| } | |||||
| } | |||||
| } | |||||
| const int sel_op_result = ED_select_op_action_deselected( | |||||
| sel_op, is_select, is_inside && enclose_face && center_face); | |||||
| if (sel_op_result != -1) { | if (sel_op_result != -1) { | ||||
| BM_face_select_set(em->bm, efa, sel_op_result); | BM_face_select_set(em->bm, efa, sel_op_result); | ||||
| changed = true; | changed = true; | ||||
| Context not available. | |||||
| /** \name Lasso Select | /** \name Lasso Select | ||||
| * \{ */ | * \{ */ | ||||
| struct LassoSelectUserData { | |||||
| ViewContext *vc; | |||||
| const rcti *rect; | |||||
| const rctf *rect_fl; | |||||
| rctf _rect_fl; | |||||
| const int (*mcoords)[2]; | |||||
| int mcoords_len; | |||||
| eSelectOp sel_op; | |||||
| eBezTriple_Flag select_flag; | |||||
| /* runtime */ | |||||
| int pass; | |||||
| bool is_done; | |||||
| bool is_changed; | |||||
| }; | |||||
| static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, | static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, | ||||
| ViewContext *vc, | ViewContext *vc, | ||||
| const rcti *rect, | const rcti *rect, | ||||
| const int (*mcoords)[2], | const int (*mcoords)[2], | ||||
| const int mcoords_len, | const int mcoords_len, | ||||
| const eSelectOp sel_op) | const eSelectOp sel_op, | ||||
| const int edge_style, | |||||
| const int face_style) | |||||
| { | { | ||||
| r_data->vc = vc; | r_data->vc = vc; | ||||
| Context not available. | |||||
| r_data->sel_op = sel_op; | r_data->sel_op = sel_op; | ||||
| /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ | /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ | ||||
| r_data->select_flag = (eBezTriple_Flag)SELECT; | r_data->select_flag = (eBezTriple_Flag)SELECT; | ||||
| r_data->edge_style = edge_style; | |||||
| r_data->face_style = face_style; | |||||
| /* runtime */ | /* runtime */ | ||||
| r_data->pass = 0; | r_data->pass = 0; | ||||
| Context not available. | |||||
| } | } | ||||
| if (BLI_rctf_isect_segment(data->rect_fl, screen_co_a, screen_co_b) && | if (BLI_rctf_isect_segment(data->rect_fl, screen_co_a, screen_co_b) && | ||||
| BLI_lasso_is_edge_inside( | BLI_lasso_is_edge_inside(data->mcoords, | ||||
| data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) { | data->mcoords_len, | ||||
| UNPACK2(screen_co_a), | |||||
| UNPACK2(screen_co_b), | |||||
| INT_MAX, | |||||
| false)) { | |||||
| pchan->bone->flag |= BONE_DONE; | pchan->bone->flag |= BONE_DONE; | ||||
| data->is_changed = true; | data->is_changed = true; | ||||
| } | } | ||||
| Context not available. | |||||
| BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | ||||
| view3d_userdata_lassoselect_init( | view3d_userdata_lassoselect_init( | ||||
| &data, vc, &rect, mcoords, mcoords_len, static_cast<eSelectOp>(0)); | &data, vc, &rect, mcoords, mcoords_len, static_cast<eSelectOp>(0), 0, 0); | ||||
| ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); | ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); | ||||
| Context not available. | |||||
| data->mcoords_len, | data->mcoords_len, | ||||
| UNPACK2(screen_co_a), | UNPACK2(screen_co_a), | ||||
| UNPACK2(screen_co_b), | UNPACK2(screen_co_b), | ||||
| IS_CLIPPED)); | IS_CLIPPED, | ||||
| false)); | |||||
| const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); | const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); | ||||
| if (sel_op_result != -1) { | if (sel_op_result != -1) { | ||||
| BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); | BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| static void do_lasso_select_mesh__doSelectFace(void *userData, | static void do_lasso_select_mesh__doSelectFaceCenter(void *userData, | ||||
| BMFace *efa, | BMFace *efa, | ||||
| const float screen_co[2], | const float screen_co[2], | ||||
| int /*index*/) | int /*index*/) | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| static void do_lasso_select_mesh__doSelectFace(void *user_data, | |||||
| BMFace *efa, | |||||
| const float screen_co[][2], | |||||
| int total_count, | |||||
| rctf *screen_rect, | |||||
| bool *face_hit) | |||||
| { | |||||
| LassoSelectUserData *data = static_cast<LassoSelectUserData *>(user_data); | |||||
| int style = data->face_style; | |||||
| if (!BLI_rctf_isect(data->rect_fl, screen_rect, NULL)) | |||||
| return; | |||||
| bool inside = false; | |||||
| for (int i = 0; i < total_count; i++) { | |||||
| int a = i; | |||||
| int b = (i + 1) % total_count; | |||||
| /* enclose */ | |||||
| if (style == 4) { | |||||
| inside = BLI_lasso_is_edge_inside(data->mcoords, | |||||
| data->mcoords_len, | |||||
| UNPACK2(screen_co[a]), | |||||
| UNPACK2(screen_co[b]), | |||||
| IS_CLIPPED, | |||||
| true); | |||||
| if (!inside) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* touch */ | |||||
| else { | |||||
| inside = BLI_lasso_is_edge_inside(data->mcoords, | |||||
| data->mcoords_len, | |||||
| UNPACK2(screen_co[a]), | |||||
| UNPACK2(screen_co[b]), | |||||
| IS_CLIPPED, | |||||
| false); | |||||
| if (inside) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* touch interior of face */ | |||||
| if (style == 2) { | |||||
| if (!inside) { | |||||
| float point[2] = {static_cast<float>(data->mcoords[0][0]), static_cast<float>(data->mcoords[0][1])}; | |||||
| inside = isect_point_poly_v2(point, screen_co, total_count, true); | |||||
| } | |||||
| } | |||||
| *face_hit = inside; | |||||
| const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); | |||||
| const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, inside); | |||||
| if (sel_op_result != -1) { | |||||
| BM_face_select_set(data->vc->em->bm, efa, sel_op_result); | |||||
| data->is_changed = true; | |||||
| } | |||||
| } | |||||
| static bool do_lasso_select_mesh(ViewContext *vc, | static bool do_lasso_select_mesh(ViewContext *vc, | ||||
| wmGenericUserData *wm_userdata, | wmGenericUserData *wm_userdata, | ||||
| const int mcoords[][2], | const int mcoords[][2], | ||||
| const int mcoords_len, | const int mcoords_len, | ||||
| const eSelectOp sel_op) | const eSelectOp sel_op, | ||||
| wmOperator *op) | |||||
| { | { | ||||
| LassoSelectUserData data; | LassoSelectUserData data; | ||||
| ToolSettings *ts = vc->scene->toolsettings; | ToolSettings *ts = vc->scene->toolsettings; | ||||
| Context not available. | |||||
| BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | ||||
| view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); | view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, RNA_enum_get(op->ptr, "edge_type"), RNA_enum_get(op->ptr, "face_type")); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| if (vc->em->bm->totvertsel) { | if (vc->em->bm->totvertsel) { | ||||
| Context not available. | |||||
| EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | ||||
| if (use_zbuf) { | if (use_zbuf) { | ||||
| if (wm_userdata->data == nullptr) { | if (wm_userdata->data == nullptr) { | ||||
| editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); | /* for near enclose face */ | ||||
| if (data.face_style == 4 && ts->selectmode & SCE_SELECT_FACE && | |||||
| !(ts->selectmode & SCE_SELECT_VERTEX)) { | |||||
| editselect_buf_cache_init_with_generic_userdata( | |||||
| wm_userdata, vc, ts->selectmode | SCE_SELECT_VERTEX); | |||||
| } | |||||
| else { | |||||
| editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); | |||||
| } | |||||
| esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | ||||
| esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( | esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( | ||||
| vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, nullptr); | vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, nullptr); | ||||
| Context not available. | |||||
| const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | | const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | | ||||
| (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); | (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); | ||||
| /* Fully inside. */ | /* Fully inside, default and enclose edge */ | ||||
| mesh_foreachScreenEdge_clip_bb_segment( | if (data.edge_style != 2) { | ||||
| vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, clip_flag); | mesh_foreachScreenEdge_clip_bb_segment( | ||||
| if (data.is_done == false) { | vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, clip_flag); | ||||
| /* Fall back to partially inside. | } | ||||
| * Clip content to account for edges partially behind the view. */ | /* Partially inside, default and touch edge */ | ||||
| if (data.edge_style == 2 || data.edge_style == 1 && data.is_done == false) { | |||||
| mesh_foreachScreenEdge_clip_bb_segment(vc, | mesh_foreachScreenEdge_clip_bb_segment(vc, | ||||
| do_lasso_select_mesh__doSelectEdge_pass1, | do_lasso_select_mesh__doSelectEdge_pass1, | ||||
| &data_for_edge, | &data_for_edge, | ||||
| Context not available. | |||||
| } | } | ||||
| if (ts->selectmode & SCE_SELECT_FACE) { | if (ts->selectmode & SCE_SELECT_FACE) { | ||||
| if (use_zbuf) { | /* xray default and center face with fallback for touch and enclose intersect */ | ||||
| data.is_changed |= edbm_backbuf_check_and_select_faces( | if (!use_zbuf && | ||||
| esel, vc->depsgraph, vc->obedit, vc->em, sel_op); | (data.face_style == 1 || data.face_style == 8 || SEL_OP_USE_OUTSIDE(sel_op))) { | ||||
| } | mesh_foreachScreenFaceCenter( | ||||
| vc, do_lasso_select_mesh__doSelectFaceCenter, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | |||||
| } | |||||
| /* xray touch and enclose face */ | |||||
| else if (!use_zbuf) { | |||||
| /* works for everything except intersect for some reason */ | |||||
| mesh_foreachScreenFaceVerts(vc, | |||||
| do_lasso_select_mesh__doSelectFace, | |||||
| &data, | |||||
| V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| } | |||||
| /* near face */ | |||||
| else { | else { | ||||
| mesh_foreachScreenFace( | data.is_changed |= edbm_backbuf_check_and_select_faces(vc, | ||||
| vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | esel, | ||||
| vc->depsgraph, | |||||
| vc->obedit, | |||||
| vc->em, | |||||
| sel_op, | |||||
| &rect, | |||||
| data.face_style, | |||||
| &data, | |||||
| NULL); | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | ||||
| view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); | view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); | ||||
| Curve *curve = (Curve *)vc->obedit->data; | Curve *curve = (Curve *)vc->obedit->data; | ||||
| ListBase *nurbs = BKE_curve_editNurbs_get(curve); | ListBase *nurbs = BKE_curve_editNurbs_get(curve); | ||||
| Context not available. | |||||
| BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | ||||
| view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); | view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); | data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); | ||||
| Context not available. | |||||
| if (screen_co_a[0] != IS_CLIPPED) { | if (screen_co_a[0] != IS_CLIPPED) { | ||||
| if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && | if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && | ||||
| BLI_lasso_is_point_inside( | BLI_lasso_is_point_inside( | ||||
| data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { | data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX), | ||||
| false) { | |||||
| is_inside_flag |= BONESEL_ROOT; | is_inside_flag |= BONESEL_ROOT; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| if (screen_co_b[0] != IS_CLIPPED) { | if (screen_co_b[0] != IS_CLIPPED) { | ||||
| if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && | if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && | ||||
| BLI_lasso_is_point_inside( | BLI_lasso_is_point_inside( | ||||
| data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { | data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX), | ||||
| false) { | |||||
| is_inside_flag |= BONESEL_TIP; | is_inside_flag |= BONESEL_TIP; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| data->mcoords_len, | data->mcoords_len, | ||||
| UNPACK2(screen_co_a), | UNPACK2(screen_co_a), | ||||
| UNPACK2(screen_co_b), | UNPACK2(screen_co_b), | ||||
| INT_MAX)) { | INT_MAX, | ||||
| false)) { | |||||
| is_inside_flag |= BONESEL_BONE; | is_inside_flag |= BONESEL_BONE; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| } | } | ||||
| if (BLI_lasso_is_edge_inside( | if (BLI_lasso_is_edge_inside( | ||||
| data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) { | data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX, false)) { | ||||
| is_inside_flag |= BONESEL_BONE; | is_inside_flag |= BONESEL_BONE; | ||||
| } | } | ||||
| Context not available. | |||||
| BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | ||||
| view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); | view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); | data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); | ||||
| Context not available. | |||||
| BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | BLI_lasso_boundbox(&rect, mcoords, mcoords_len); | ||||
| view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); | view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= BKE_mball_deselect_all(mb); | data.is_changed |= BKE_mball_deselect_all(mb); | ||||
| Context not available. | |||||
| LassoSelectUserData_ForMeshVert data; | LassoSelectUserData_ForMeshVert data; | ||||
| data.select_vert = select_vert.span; | data.select_vert = select_vert.span; | ||||
| view3d_userdata_lassoselect_init(&data.lasso_data, vc, &rect, mcoords, mcoords_len, sel_op); | view3d_userdata_lassoselect_init( | ||||
| &data.lasso_data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); | |||||
| ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); | ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); | ||||
| Context not available. | |||||
| ViewContext *vc, | ViewContext *vc, | ||||
| const int mcoords[][2], | const int mcoords[][2], | ||||
| const int mcoords_len, | const int mcoords_len, | ||||
| const eSelectOp sel_op) | const eSelectOp sel_op, | ||||
| wmOperator *op) | |||||
| { | { | ||||
| Object *ob = CTX_data_active_object(C); | Object *ob = CTX_data_active_object(C); | ||||
| bool changed_multi = false; | bool changed_multi = false; | ||||
| Context not available. | |||||
| switch (vc->obedit->type) { | switch (vc->obedit->type) { | ||||
| case OB_MESH: | case OB_MESH: | ||||
| changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op); | changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op, op); | ||||
| break; | break; | ||||
| case OB_CURVES_LEGACY: | case OB_CURVES_LEGACY: | ||||
| case OB_SURF: | case OB_SURF: | ||||
| Context not available. | |||||
| ED_view3d_viewcontext_init(C, &vc, depsgraph); | ED_view3d_viewcontext_init(C, &vc, depsgraph); | ||||
| eSelectOp sel_op = static_cast<eSelectOp>(RNA_enum_get(op->ptr, "mode")); | eSelectOp sel_op = static_cast<eSelectOp>(RNA_enum_get(op->ptr, "mode")); | ||||
| bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op); | bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op, op); | ||||
| MEM_freeN((void *)mcoords); | MEM_freeN((void *)mcoords); | ||||
| Context not available. | |||||
| /** \name Box Select | /** \name Box Select | ||||
| * \{ */ | * \{ */ | ||||
| struct BoxSelectUserData { | |||||
| ViewContext *vc; | |||||
| const rcti *rect; | |||||
| const rctf *rect_fl; | |||||
| rctf _rect_fl; | |||||
| eSelectOp sel_op; | |||||
| eBezTriple_Flag select_flag; | |||||
| /* runtime */ | |||||
| bool is_done; | |||||
| bool is_changed; | |||||
| }; | |||||
| static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, | static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, | ||||
| ViewContext *vc, | ViewContext *vc, | ||||
| const rcti *rect, | const rcti *rect, | ||||
| const eSelectOp sel_op) | const eSelectOp sel_op, | ||||
| const int edge_style, | |||||
| const int face_style) | |||||
| { | { | ||||
| r_data->vc = vc; | r_data->vc = vc; | ||||
| Context not available. | |||||
| r_data->sel_op = sel_op; | r_data->sel_op = sel_op; | ||||
| /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ | /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ | ||||
| r_data->select_flag = (eBezTriple_Flag)SELECT; | r_data->select_flag = (eBezTriple_Flag)SELECT; | ||||
| r_data->edge_style = edge_style; | |||||
| r_data->face_style = face_style; | |||||
| /* runtime */ | /* runtime */ | ||||
| r_data->is_done = false; | r_data->is_done = false; | ||||
| Context not available. | |||||
| BoxSelectUserData_ForMeshVert data; | BoxSelectUserData_ForMeshVert data; | ||||
| data.select_vert = select_vert.span; | data.select_vert = select_vert.span; | ||||
| view3d_userdata_boxselect_init(&data.box_data, vc, rect, sel_op); | view3d_userdata_boxselect_init(&data.box_data, vc, rect, sel_op, 0, 0); | ||||
| ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); | ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); | ||||
| Context not available. | |||||
| const bool deselect_all = (sel_op == SEL_OP_SET); | const bool deselect_all = (sel_op == SEL_OP_SET); | ||||
| BoxSelectUserData data; | BoxSelectUserData data; | ||||
| view3d_userdata_boxselect_init(&data, vc, rect, sel_op); | view3d_userdata_boxselect_init(&data, vc, rect, sel_op, 0, 0); | ||||
| Curve *curve = (Curve *)vc->obedit->data; | Curve *curve = (Curve *)vc->obedit->data; | ||||
| ListBase *nurbs = BKE_curve_editNurbs_get(curve); | ListBase *nurbs = BKE_curve_editNurbs_get(curve); | ||||
| Context not available. | |||||
| { | { | ||||
| BoxSelectUserData data; | BoxSelectUserData data; | ||||
| view3d_userdata_boxselect_init(&data, vc, rect, sel_op); | view3d_userdata_boxselect_init(&data, vc, rect, sel_op, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); | data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); | ||||
| Context not available. | |||||
| data->is_changed = true; | data->is_changed = true; | ||||
| } | } | ||||
| } | } | ||||
| static void do_mesh_box_select__doSelectFace(void *userData, | static void do_mesh_box_select__doSelectFace(void *userData, | ||||
| BMFace *efa, | |||||
| const float screen_co[][2], | |||||
| int total_count, | |||||
| rctf *screen_rect, | |||||
| bool *face_hit) | |||||
| { | |||||
| BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); | |||||
| int style = data->face_style; | |||||
| if (!BLI_rctf_isect(data->rect_fl, screen_rect, NULL)) | |||||
| return; | |||||
| bool inside = false; | |||||
| for (int i = 0; i < total_count; i++) { | |||||
| int a = i; | |||||
| int b = (i + 1) % total_count; | |||||
| /* enclose */ | |||||
| if (style == 4) { | |||||
| inside = edge_fully_inside_rect(data->rect_fl, screen_co[a], screen_co[b]); | |||||
| if (!inside) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* touch */ | |||||
| else { | |||||
| inside = edge_inside_rect(data->rect_fl, screen_co[a], screen_co[b]); | |||||
| if (inside) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* touch interior of face */ | |||||
| if (style == 2 && !inside) { | |||||
| float point[2] = {data->rect_fl->xmax, data->rect_fl->ymax}; | |||||
| inside = isect_point_poly_v2(point, screen_co, total_count, true); | |||||
| } | |||||
| *face_hit = inside; | |||||
| const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); | |||||
| const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, inside); | |||||
| if (sel_op_result != -1) { | |||||
| BM_face_select_set(data->vc->em->bm, efa, sel_op_result); | |||||
| data->is_changed = true; | |||||
| } | |||||
| } | |||||
| static void do_mesh_box_select__doSelectFaceCenter(void *userData, | |||||
| BMFace *efa, | BMFace *efa, | ||||
| const float screen_co[2], | const float screen_co[2], | ||||
| int /*index*/) | int /*index*/) | ||||
| Context not available. | |||||
| static bool do_mesh_box_select(ViewContext *vc, | static bool do_mesh_box_select(ViewContext *vc, | ||||
| wmGenericUserData *wm_userdata, | wmGenericUserData *wm_userdata, | ||||
| const rcti *rect, | const rcti *rect, | ||||
| const eSelectOp sel_op) | const eSelectOp sel_op, | ||||
| wmOperator *op) | |||||
| { | { | ||||
| BoxSelectUserData data; | BoxSelectUserData data; | ||||
| ToolSettings *ts = vc->scene->toolsettings; | ToolSettings *ts = vc->scene->toolsettings; | ||||
| view3d_userdata_boxselect_init(&data, vc, rect, sel_op); | view3d_userdata_boxselect_init(&data, | ||||
| vc, | |||||
| rect, | |||||
| sel_op, | |||||
| RNA_enum_get(op->ptr, "edge_type"), | |||||
| RNA_enum_get(op->ptr, "face_type")); | |||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| if (vc->em->bm->totvertsel) { | if (vc->em->bm->totvertsel) { | ||||
| Context not available. | |||||
| EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | ||||
| if (use_zbuf) { | if (use_zbuf) { | ||||
| if (wm_userdata->data == nullptr) { | if (wm_userdata->data == nullptr) { | ||||
| editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); | /* for near enclose face */ | ||||
| if (data.face_style == 4 && ts->selectmode & SCE_SELECT_FACE && | |||||
| !(ts->selectmode & SCE_SELECT_VERTEX)) { | |||||
| editselect_buf_cache_init_with_generic_userdata( | |||||
| wm_userdata, vc, ts->selectmode | SCE_SELECT_VERTEX); | |||||
| } | |||||
| else { | |||||
| editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); | |||||
| } | |||||
| esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); | ||||
| esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( | esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( | ||||
| vc->depsgraph, vc->region, vc->v3d, rect, nullptr); | vc->depsgraph, vc->region, vc->v3d, rect, nullptr); | ||||
| Context not available. | |||||
| const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | | const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | | ||||
| (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); | (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); | ||||
| /* Fully inside. */ | /* Fully inside, default and enclose edge */ | ||||
| mesh_foreachScreenEdge_clip_bb_segment( | if (data.edge_style != 2) { | ||||
| vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, clip_flag); | mesh_foreachScreenEdge_clip_bb_segment( | ||||
| if (data.is_done == false) { | vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, clip_flag); | ||||
| /* Fall back to partially inside. | } | ||||
| * Clip content to account for edges partially behind the view. */ | /* Partially inside, default and touch edge */ | ||||
| if (data.edge_style == 2 || data.edge_style == 1 && data.is_done == false) { | |||||
| mesh_foreachScreenEdge_clip_bb_segment(vc, | mesh_foreachScreenEdge_clip_bb_segment(vc, | ||||
| do_mesh_box_select__doSelectEdge_pass1, | do_mesh_box_select__doSelectEdge_pass1, | ||||
| &cb_data, | &cb_data, | ||||
| Context not available. | |||||
| } | } | ||||
| if (ts->selectmode & SCE_SELECT_FACE) { | if (ts->selectmode & SCE_SELECT_FACE) { | ||||
| if (use_zbuf) { | /* xray default and center face with fallback for touch and enclose intersect */ | ||||
| data.is_changed |= edbm_backbuf_check_and_select_faces( | if (!use_zbuf && | ||||
| esel, vc->depsgraph, vc->obedit, vc->em, sel_op); | (data.face_style == 1 || data.face_style == 8 || SEL_OP_USE_OUTSIDE(sel_op))) { | ||||
| } | mesh_foreachScreenFaceCenter( | ||||
| vc, do_mesh_box_select__doSelectFaceCenter, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | |||||
| } | |||||
| /* xray touch and enclose face */ | |||||
| else if (!use_zbuf) { | |||||
| /* works for everything except intersect for some reason */ | |||||
| mesh_foreachScreenFaceVerts(vc, | |||||
| do_mesh_box_select__doSelectFace, | |||||
| &data, | |||||
| V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| } | |||||
| /* near face */ | |||||
| else { | else { | ||||
| mesh_foreachScreenFace( | data.is_changed |= edbm_backbuf_check_and_select_faces( | ||||
| vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | vc, esel, vc->depsgraph, vc->obedit, vc->em, sel_op, rect, data.face_style, NULL, NULL); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| switch (vc.obedit->type) { | switch (vc.obedit->type) { | ||||
| case OB_MESH: | case OB_MESH: | ||||
| vc.em = BKE_editmesh_from_object(vc.obedit); | vc.em = BKE_editmesh_from_object(vc.obedit); | ||||
| changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op); | changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op, op); | ||||
| if (changed) { | if (changed) { | ||||
| DEG_id_tag_update(static_cast<ID *>(vc.obedit->data), ID_RECALC_SELECT); | DEG_id_tag_update(static_cast<ID *>(vc.obedit->data), ID_RECALC_SELECT); | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); | ||||
| Context not available. | |||||
| /** \name Circle Select | /** \name Circle Select | ||||
| * \{ */ | * \{ */ | ||||
| struct CircleSelectUserData { | |||||
| ViewContext *vc; | |||||
| bool select; | |||||
| int mval[2]; | |||||
| float mval_fl[2]; | |||||
| float radius; | |||||
| float radius_squared; | |||||
| eBezTriple_Flag select_flag; | |||||
| /* runtime */ | |||||
| bool is_changed; | |||||
| }; | |||||
| static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, | static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, | ||||
| ViewContext *vc, | ViewContext *vc, | ||||
| const bool select, | const bool select, | ||||
| const int mval[2], | const int mval[2], | ||||
| const float rad) | const float rad, | ||||
| const int edge_style, | |||||
| const int face_style) | |||||
| { | { | ||||
| r_data->vc = vc; | r_data->vc = vc; | ||||
| r_data->select = select; | r_data->select = select; | ||||
| Context not available. | |||||
| /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ | /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ | ||||
| r_data->select_flag = (eBezTriple_Flag)SELECT; | r_data->select_flag = (eBezTriple_Flag)SELECT; | ||||
| r_data->edge_style = edge_style; | |||||
| r_data->face_style = face_style; | |||||
| /* runtime */ | /* runtime */ | ||||
| r_data->is_changed = false; | r_data->is_changed = false; | ||||
| Context not available. | |||||
| int /*index*/) | int /*index*/) | ||||
| { | { | ||||
| CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); | CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); | ||||
| const int style = data->edge_style; | |||||
| BMVert *eve; | |||||
| BMIter iter; | |||||
| if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { | if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { | ||||
| BM_edge_select_set(data->vc->em->bm, eed, data->select); | bool enclose_edge = true; | ||||
| data->is_changed = true; | /* enclose edge */ | ||||
| if (style == 4) { | |||||
| BM_ITER_ELEM (eve, &iter, eed, BM_VERTS_OF_EDGE) { | |||||
| float vertv3[3] = {eve->co[0], eve->co[1], eve->co[2]}; | |||||
| float vertv2[2] = {0.0f, 0.0f}; | |||||
| ED_view3d_project_float_object( | |||||
| data->vc->region, vertv3, vertv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| enclose_edge = len_squared_v2v2(data->mval_fl, vertv2) <= data->radius_squared; | |||||
| if (!enclose_edge) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (enclose_edge) { | |||||
| BM_edge_select_set(data->vc->em->bm, eed, data->select); | |||||
| data->is_changed = true; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| static void mesh_circle_doSelectFace(void *userData, | static void mesh_circle_doSelectFace(void *userData, | ||||
| BMFace *efa, | |||||
| const float screen_co[][2], | |||||
| int total_count, | |||||
| rctf *screen_rect, | |||||
| bool *face_hit) | |||||
| { | |||||
| CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); | |||||
| BMIter iter; | |||||
| BMVert *eve; | |||||
| int style = data->face_style; | |||||
| if (!BLI_rctf_isect_circle(screen_rect, data->mval_fl, data->radius)) { | |||||
| return; | |||||
| } | |||||
| bool inside = false; | |||||
| for (int i = 0; i < total_count; i++) { | |||||
| int a = i; | |||||
| int b = (i + 1) % total_count; | |||||
| inside = edge_inside_circle(data->mval_fl, data->radius, screen_co[a], screen_co[b]); | |||||
| if (inside) | |||||
| break; | |||||
| } | |||||
| if (!inside) { | |||||
| inside = isect_point_poly_v2(data->mval_fl, screen_co, total_count, true); | |||||
| } | |||||
| *face_hit = inside; | |||||
| bool enclose_face = true; | |||||
| /* enclose face */ | |||||
| if (style == 4 && inside) { | |||||
| BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { | |||||
| float vertv3[3] = {eve->co[0], eve->co[1], eve->co[2]}; | |||||
| float vertv2[2] = {0.0f, 0.0f}; | |||||
| ED_view3d_project_float_object( | |||||
| data->vc->region, vertv3, vertv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| enclose_face = len_squared_v2v2(data->mval_fl, vertv2) <= data->radius_squared; | |||||
| if (!enclose_face) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (inside && enclose_face) { | |||||
| BM_face_select_set(data->vc->em->bm, efa, data->select); | |||||
| data->is_changed = true; | |||||
| } | |||||
| } | |||||
| static void mesh_circle_doSelectFaceCenter(void *userData, | |||||
| BMFace *efa, | BMFace *efa, | ||||
| const float screen_co[2], | const float screen_co[2], | ||||
| int /*index*/) | int /*index*/) | ||||
| Context not available. | |||||
| wmGenericUserData *wm_userdata, | wmGenericUserData *wm_userdata, | ||||
| eSelectOp sel_op, | eSelectOp sel_op, | ||||
| const int mval[2], | const int mval[2], | ||||
| float rad) | float rad, | ||||
| wmOperator *op) | |||||
| { | { | ||||
| ToolSettings *ts = vc->scene->toolsettings; | ToolSettings *ts = vc->scene->toolsettings; | ||||
| CircleSelectUserData data; | CircleSelectUserData data; | ||||
| Context not available. | |||||
| ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ | ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ | ||||
| view3d_userdata_circleselect_init(&data, vc, select, mval, rad); | view3d_userdata_circleselect_init(&data, | ||||
| vc, | |||||
| select, | |||||
| mval, | |||||
| rad, | |||||
| RNA_enum_get(op->ptr, "edge_type"), | |||||
| RNA_enum_get(op->ptr, "face_type")); | |||||
| const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); | const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); | ||||
| Context not available. | |||||
| if (use_zbuf) { | if (use_zbuf) { | ||||
| if (esel->select_bitmap != nullptr) { | if (esel->select_bitmap != nullptr) { | ||||
| changed |= edbm_backbuf_check_and_select_edges( | changed |= edbm_backbuf_check_and_select_edges( | ||||
| esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); | &data, esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| Context not available. | |||||
| } | } | ||||
| if (ts->selectmode & SCE_SELECT_FACE) { | if (ts->selectmode & SCE_SELECT_FACE) { | ||||
| if (use_zbuf) { | /* xray default and center face */ | ||||
| if (esel->select_bitmap != nullptr) { | if (!use_zbuf && (data.face_style == 1 || data.face_style == 8)) { | ||||
| changed |= edbm_backbuf_check_and_select_faces( | mesh_foreachScreenFaceCenter( | ||||
| esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); | vc, mesh_circle_doSelectFaceCenter, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | ||||
| } | |||||
| } | } | ||||
| /* xray touch and enclose face */ | |||||
| else if (!use_zbuf) { | |||||
| mesh_foreachScreenFaceVerts( | |||||
| vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); | |||||
| } | |||||
| /* near face */ | |||||
| else { | else { | ||||
| mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | if (esel->select_bitmap != NULL) { | ||||
| changed |= edbm_backbuf_check_and_select_faces(vc, | |||||
| esel, | |||||
| vc->depsgraph, | |||||
| vc->obedit, | |||||
| vc->em, | |||||
| select ? SEL_OP_ADD : SEL_OP_SUB, | |||||
| NULL, | |||||
| data.face_style, | |||||
| NULL, | |||||
| &data); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ | ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ | ||||
| view3d_userdata_circleselect_init(&data.circle_data, vc, select, mval, rad); | view3d_userdata_circleselect_init(&data.circle_data, vc, select, mval, rad, 0, 0); | ||||
| meshobject_foreachScreenVert( | meshobject_foreachScreenVert( | ||||
| vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | ||||
| changed |= data.circle_data.is_changed; | changed |= data.circle_data.is_changed; | ||||
| Context not available. | |||||
| const bool deselect_all = (sel_op == SEL_OP_SET); | const bool deselect_all = (sel_op == SEL_OP_SET); | ||||
| CircleSelectUserData data; | CircleSelectUserData data; | ||||
| view3d_userdata_circleselect_init(&data, vc, select, mval, rad); | view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); | ||||
| Curve *curve = (Curve *)vc->obedit->data; | Curve *curve = (Curve *)vc->obedit->data; | ||||
| ListBase *nurbs = BKE_curve_editNurbs_get(curve); | ListBase *nurbs = BKE_curve_editNurbs_get(curve); | ||||
| Context not available. | |||||
| CircleSelectUserData data; | CircleSelectUserData data; | ||||
| const bool select = (sel_op != SEL_OP_SUB); | const bool select = (sel_op != SEL_OP_SUB); | ||||
| view3d_userdata_circleselect_init(&data, vc, select, mval, rad); | view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); | data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); | ||||
| Context not available. | |||||
| CircleSelectUserData data; | CircleSelectUserData data; | ||||
| const bool select = (sel_op != SEL_OP_SUB); | const bool select = (sel_op != SEL_OP_SUB); | ||||
| view3d_userdata_circleselect_init(&data, vc, select, mval, rad); | view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false); | data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false); | ||||
| Context not available. | |||||
| const bool select = (sel_op != SEL_OP_SUB); | const bool select = (sel_op != SEL_OP_SUB); | ||||
| view3d_userdata_circleselect_init(&data, vc, select, mval, rad); | view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); | data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); | ||||
| Context not available. | |||||
| const bool select = (sel_op != SEL_OP_SUB); | const bool select = (sel_op != SEL_OP_SUB); | ||||
| view3d_userdata_circleselect_init(&data, vc, select, mval, rad); | view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | ||||
| data.is_changed |= BKE_mball_deselect_all(static_cast<MetaBall *>(vc->obedit->data)); | data.is_changed |= BKE_mball_deselect_all(static_cast<MetaBall *>(vc->obedit->data)); | ||||
| Context not available. | |||||
| wmGenericUserData *wm_userdata, | wmGenericUserData *wm_userdata, | ||||
| const eSelectOp sel_op, | const eSelectOp sel_op, | ||||
| const int mval[2], | const int mval[2], | ||||
| float rad) | float rad, | ||||
| wmOperator *op) | |||||
| { | { | ||||
| bool changed = false; | bool changed = false; | ||||
| BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); | BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); | ||||
| switch (vc->obedit->type) { | switch (vc->obedit->type) { | ||||
| case OB_MESH: | case OB_MESH: | ||||
| changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad); | changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad, op); | ||||
| break; | break; | ||||
| case OB_CURVES_LEGACY: | case OB_CURVES_LEGACY: | ||||
| case OB_SURF: | case OB_SURF: | ||||
| Context not available. | |||||
| obedit = vc.obedit; | obedit = vc.obedit; | ||||
| if (obedit) { | if (obedit) { | ||||
| obedit_circle_select(C, &vc, wm_userdata, sel_op, mval, float(radius)); | obedit_circle_select(C, &vc, wm_userdata, sel_op, mval, float(radius), op); | ||||
| } | } | ||||
| else if (BKE_paint_select_face_test(obact)) { | else if (BKE_paint_select_face_test(obact)) { | ||||
| paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, float(radius)); | paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, float(radius)); | ||||
| Context not available. | |||||