Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/mesh/editmesh_select.c
| Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| #include "bmesh_tools.h" | #include "bmesh_tools.h" | ||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "DRW_engine.h" | |||||
| #include "mesh_intern.h" /* own include */ | #include "mesh_intern.h" /* own include */ | ||||
| /* use bmesh operator flags for a few operators */ | /* use bmesh operator flags for a few operators */ | ||||
| #define BMO_ELE_TAG 1 | #define BMO_ELE_TAG 1 | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Select Mirror | /** \name Select Mirror | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Back-Buffer OpenGL Selection | /** \name Back-Buffer OpenGL Selection | ||||
| * \{ */ | * \{ */ | ||||
| /* set in drawobject.c ... for colorindices */ | typedef struct EDBMBaseOffset { | ||||
| uint solidoffs; | |||||
| uint wireoffs; | |||||
| uint vertoffs; | |||||
| } EDBMBaseOffset; | |||||
| static EDBMBaseOffset *base_indexes_offsets = NULL; | |||||
| static void edbm_select_pick_cache_alloc(uint bases_len) | |||||
| { | |||||
| BLI_assert(base_indexes_offsets == NULL); | |||||
| base_indexes_offsets = MEM_mallocN(sizeof(EDBMBaseOffset) * bases_len, __func__); | |||||
| } | |||||
| static void edbm_select_pick_cache_free(void) | |||||
| { | |||||
| MEM_SAFE_FREE(base_indexes_offsets); | |||||
| } | |||||
| static bool check_ob_drawface_dot(short select_mode, View3D *vd, char dt) | |||||
| { | |||||
| if ((select_mode & SCE_SELECT_FACE) == 0) { | |||||
| return false; | |||||
| } | |||||
| /* if its drawing textures with zbuf sel, then don't draw dots */ | |||||
| if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| static void edbm_select_pick_draw_bases(ViewContext *vc, | |||||
| Base **bases, | |||||
| uint bases_len, | |||||
| short select_mode) | |||||
| { | |||||
| Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); | |||||
| DRW_framebuffer_select_id_setup(vc->ar, true); | |||||
| uint offset = 0; | |||||
| for (uint base_index = 0; base_index < bases_len; base_index++) { | |||||
| Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, bases[base_index]->object); | |||||
| EDBMBaseOffset *base_offsets = &base_indexes_offsets[base_index]; | |||||
| bool draw_facedot = check_ob_drawface_dot(select_mode, vc->v3d, ob_eval->dt); | |||||
| DRW_draw_select_id_object(vc->depsgraph, | |||||
| scene_eval, | |||||
| vc->v3d, | |||||
| vc->rv3d, | |||||
| ob_eval, | |||||
| select_mode, | |||||
| draw_facedot, | |||||
| offset, | |||||
| &base_offsets->solidoffs, | |||||
| &base_offsets->wireoffs, | |||||
| &base_offsets->vertoffs); | |||||
| offset = base_offsets->vertoffs; | |||||
| } | |||||
| DRW_framebuffer_select_id_release(vc->ar); | |||||
| } | |||||
| static uint edbm_select_pick_base_index_find(uint bases_len, uint elem_index, uint *r_offset) | |||||
| { | |||||
| *r_offset = 0; | |||||
| uint base_index = 0; | |||||
| for (; base_index < bases_len; base_index++) { | |||||
| EDBMBaseOffset *base_offsets = &base_indexes_offsets[base_index]; | |||||
| if (base_offsets->vertoffs > elem_index) { | |||||
| break; | |||||
| } | |||||
| *r_offset = base_offsets->vertoffs; | |||||
| } | |||||
| *r_offset += 1; | |||||
| return base_index; | |||||
| } | |||||
| /* set in view3d_draw_legacy.c ... for colorindices */ | |||||
| unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; | unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; | ||||
| /* facilities for box select and circle select */ | /* facilities for box select and circle select */ | ||||
| static BLI_bitmap *selbuf = NULL; | static BLI_bitmap *selbuf = NULL; | ||||
| static BLI_bitmap *edbm_backbuf_alloc(const int size) | static BLI_bitmap *edbm_backbuf_alloc(const int size) | ||||
| { | { | ||||
| return BLI_BITMAP_NEW(size, "selbuf"); | return BLI_BITMAP_NEW(size, "selbuf"); | ||||
| } | } | ||||
| /* reads rect, and builds selection array for quick lookup */ | /* reads rect, and builds selection array for quick lookup */ | ||||
| /* returns if all is OK */ | /* returns if all is OK */ | ||||
| bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) | bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) | ||||
| { | { | ||||
| uint *buf, *dr, buf_len; | uint *buf, *dr, buf_len; | ||||
| if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) { | if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| ED_view3d_select_id_validate(vc); | |||||
| buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); | buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); | ||||
| if ((buf == NULL) || (bm_vertoffs == 0)) { | if ((buf == NULL) || (bm_vertoffs == 0)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| dr = buf; | dr = buf; | ||||
| /* build selection lookup */ | /* build selection lookup */ | ||||
| ▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | if (vc->obedit == NULL) { | ||||
| if (!BKE_paint_select_elem_test(vc->obact)) { | if (!BKE_paint_select_elem_test(vc->obact)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| else if (XRAY_FLAG_ENABLED(vc->v3d)) { | else if (XRAY_FLAG_ENABLED(vc->v3d)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| ED_view3d_select_id_validate(vc); | |||||
| buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); | buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); | ||||
| if ((buf == NULL) || (bm_vertoffs == 0)) { | if ((buf == NULL) || (bm_vertoffs == 0)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| dr = buf; | dr = buf; | ||||
| dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__); | dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__); | ||||
| Show All 35 Lines | bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) | ||||
| else if (XRAY_FLAG_ENABLED(vc->v3d)) { | else if (XRAY_FLAG_ENABLED(vc->v3d)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| xmin = xs - rads; | xmin = xs - rads; | ||||
| xmax = xs + rads; | xmax = xs + rads; | ||||
| ymin = ys - rads; | ymin = ys - rads; | ||||
| ymax = ys + rads; | ymax = ys + rads; | ||||
| ED_view3d_select_id_validate(vc); | |||||
| buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL); | buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL); | ||||
| if ((buf == NULL) || (bm_vertoffs == 0)) { | if ((buf == NULL) || (bm_vertoffs == 0)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| dr = buf; | dr = buf; | ||||
| /* build selection lookup */ | /* build selection lookup */ | ||||
| ▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | |||||
| * - When true, selected vertices are given a 5 pixel bias | * - When true, selected vertices are given a 5 pixel bias | ||||
| * to make them further than unselect verts. | * to make them further than unselect verts. | ||||
| * - When false, unselected vertices are given the bias. | * - When false, unselected vertices are given the bias. | ||||
| * \param use_cycle: Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index. | * \param use_cycle: Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index. | ||||
| */ | */ | ||||
| BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, | BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, | ||||
| float *r_dist, | float *r_dist, | ||||
| const bool use_select_bias, | const bool use_select_bias, | ||||
| bool use_cycle) | bool use_cycle, | ||||
| Base **bases, | |||||
| uint bases_len, | |||||
| uint *r_base_index) | |||||
| { | { | ||||
| BMesh *bm = vc->em->bm; | uint base_index = 0; | ||||
| if (!XRAY_FLAG_ENABLED(vc->v3d)) { | if (!XRAY_FLAG_ENABLED(vc->v3d)) { | ||||
| uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); | uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); | ||||
| unsigned int index; | uint index, offset; | ||||
| BMVert *eve; | BMVert *eve; | ||||
| /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ | /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ | ||||
| { | { | ||||
| FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX) | FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX); | ||||
| ; | |||||
| ED_view3d_select_id_validate_with_select_mode(vc, select_mode); | edbm_select_pick_cache_alloc(bases_len); | ||||
| edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); | |||||
| index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px); | index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); | ||||
| eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; | |||||
| if (index) { | |||||
| base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); | |||||
| ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); | |||||
| eve = BM_vert_at_index_find_or_table(vc->em->bm, index - offset); | |||||
| } | |||||
| else { | |||||
| eve = NULL; | |||||
| } | |||||
| edbm_select_pick_cache_free(); | |||||
| FAKE_SELECT_MODE_END(vc, fake_select_mode); | FAKE_SELECT_MODE_END(vc, fake_select_mode); | ||||
| } | } | ||||
| if (eve) { | if (eve) { | ||||
| if (dist_px < *r_dist) { | if (dist_px < *r_dist) { | ||||
| if (r_base_index) { | |||||
| *r_base_index = base_index; | |||||
| } | |||||
| *r_dist = dist_px; | *r_dist = dist_px; | ||||
| return eve; | return eve; | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| else { | else { | ||||
| struct NearestVertUserData data = {{0}}; | struct NearestVertUserData data = {{0}}; | ||||
| const struct NearestVertUserData_Hit *hit; | const struct NearestVertUserData_Hit *hit; | ||||
| const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; | const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; | ||||
| static int prev_select_index = 0; | static int prev_select_index = 0; | ||||
| static const BMVert *prev_select_elem = NULL; | static const BMVert *prev_select_elem = NULL; | ||||
| if ((use_cycle == false) || | if ((use_cycle == false) || | ||||
| (prev_select_elem && | (prev_select_elem && | ||||
| (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) { | (prev_select_elem != BM_vert_at_index_find_or_table(vc->em->bm, prev_select_index)))) { | ||||
| prev_select_index = 0; | prev_select_index = 0; | ||||
| prev_select_elem = NULL; | prev_select_elem = NULL; | ||||
| } | } | ||||
| data.mval_fl[0] = vc->mval[0]; | data.mval_fl[0] = vc->mval[0]; | ||||
| data.mval_fl[1] = vc->mval[1]; | data.mval_fl[1] = vc->mval[1]; | ||||
| data.use_select_bias = use_select_bias; | data.use_select_bias = use_select_bias; | ||||
| data.use_cycle = use_cycle; | data.use_cycle = use_cycle; | ||||
| data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; | |||||
| data.cycle_index_prev = prev_select_index; | data.cycle_index_prev = prev_select_index; | ||||
| for (; base_index < bases_len; base_index++) { | |||||
| Base *base_iter = bases[base_index]; | |||||
| ED_view3d_viewcontext_init_object(vc, base_iter->object); | |||||
| data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; | |||||
| ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); | ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); | ||||
| mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); | mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); | ||||
| hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; | hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; | ||||
| if (hit->dist < *r_dist) { | |||||
| if (r_base_index) { | |||||
| *r_base_index = base_index; | |||||
| } | |||||
| *r_dist = hit->dist; | *r_dist = hit->dist; | ||||
| } | |||||
| } | |||||
| prev_select_elem = hit->vert; | prev_select_elem = hit->vert; | ||||
| prev_select_index = hit->index; | prev_select_index = hit->index; | ||||
| return hit->vert; | return hit->vert; | ||||
| } | } | ||||
| } | } | ||||
| BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) | BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) | ||||
| { | { | ||||
| return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); | Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); | ||||
| return EDBM_vert_find_nearest_ex(vc, r_dist, false, false, &base, 1, NULL); | |||||
| } | } | ||||
| /* find the distance to the edge we already have */ | /* find the distance to the edge we already have */ | ||||
| struct NearestEdgeUserData_ZBuf { | struct NearestEdgeUserData_ZBuf { | ||||
| float mval_fl[2]; | float mval_fl[2]; | ||||
| float dist; | float dist; | ||||
| const BMEdge *edge_test; | const BMEdge *edge_test; | ||||
| }; | }; | ||||
| ▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | static void find_nearest_edge__doClosest( | ||||
| } | } | ||||
| } | } | ||||
| BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, | BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, | ||||
| float *r_dist, | float *r_dist, | ||||
| float *r_dist_center, | float *r_dist_center, | ||||
| const bool use_select_bias, | const bool use_select_bias, | ||||
| const bool use_cycle, | const bool use_cycle, | ||||
| BMEdge **r_eed_zbuf) | BMEdge **r_eed_zbuf, | ||||
| Base **bases, | |||||
| uint bases_len, | |||||
| uint *r_base_index) | |||||
| { | { | ||||
| BMesh *bm = vc->em->bm; | uint base_index = 0; | ||||
| if (!XRAY_FLAG_ENABLED(vc->v3d)) { | if (!XRAY_FLAG_ENABLED(vc->v3d)) { | ||||
| uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); | uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); | ||||
| unsigned int index; | uint index, offset; | ||||
| BMEdge *eed; | BMEdge *eed; | ||||
| /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ | /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ | ||||
| { | { | ||||
| FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_EDGE) | FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE); | ||||
| ; | |||||
| ED_view3d_select_id_validate_with_select_mode(vc, select_mode); | edbm_select_pick_cache_alloc(bases_len); | ||||
| edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); | |||||
| index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); | |||||
| if (index) { | |||||
| base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); | |||||
| ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); | |||||
| eed = BM_edge_at_index_find_or_table(vc->em->bm, index - offset); | |||||
| } | |||||
| else { | |||||
| eed = NULL; | |||||
| } | |||||
| index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px); | edbm_select_pick_cache_free(); | ||||
| eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; | |||||
| FAKE_SELECT_MODE_END(vc, fake_select_mode); | FAKE_SELECT_MODE_END(vc, fake_select_mode); | ||||
| } | } | ||||
| if (r_eed_zbuf) { | if (r_eed_zbuf) { | ||||
| *r_eed_zbuf = eed; | *r_eed_zbuf = eed; | ||||
| } | } | ||||
| Show All 12 Lines | if (r_dist_center && eed) { | ||||
| vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | ||||
| *r_dist_center = data.dist; | *r_dist_center = data.dist; | ||||
| } | } | ||||
| /* end exception */ | /* end exception */ | ||||
| if (eed) { | if (eed) { | ||||
| if (dist_px < *r_dist) { | if (dist_px < *r_dist) { | ||||
| if (r_base_index) { | |||||
| *r_base_index = base_index; | |||||
| } | |||||
| *r_dist = dist_px; | *r_dist = dist_px; | ||||
| return eed; | return eed; | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| else { | else { | ||||
| struct NearestEdgeUserData data = {{0}}; | struct NearestEdgeUserData data = {{0}}; | ||||
| const struct NearestEdgeUserData_Hit *hit; | const struct NearestEdgeUserData_Hit *hit; | ||||
| /* interpolate along the edge before doing a clipping plane test */ | /* interpolate along the edge before doing a clipping plane test */ | ||||
| const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB; | const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB; | ||||
| static int prev_select_index = 0; | static int prev_select_index = 0; | ||||
| static const BMEdge *prev_select_elem = NULL; | static const BMEdge *prev_select_elem = NULL; | ||||
| if ((use_cycle == false) || | if ((use_cycle == false) || | ||||
| (prev_select_elem && | (prev_select_elem && | ||||
| (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) { | (prev_select_elem != BM_edge_at_index_find_or_table(vc->em->bm, prev_select_index)))) { | ||||
| prev_select_index = 0; | prev_select_index = 0; | ||||
| prev_select_elem = NULL; | prev_select_elem = NULL; | ||||
| } | } | ||||
| data.vc = *vc; | data.vc = *vc; | ||||
| data.mval_fl[0] = vc->mval[0]; | data.mval_fl[0] = vc->mval[0]; | ||||
| data.mval_fl[1] = vc->mval[1]; | data.mval_fl[1] = vc->mval[1]; | ||||
| data.use_select_bias = use_select_bias; | data.use_select_bias = use_select_bias; | ||||
| data.use_cycle = use_cycle; | data.use_cycle = use_cycle; | ||||
| data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; | |||||
| data.cycle_index_prev = prev_select_index; | data.cycle_index_prev = prev_select_index; | ||||
| for (; base_index < bases_len; base_index++) { | |||||
| Base *base_iter = bases[base_index]; | |||||
| ED_view3d_viewcontext_init_object(vc, base_iter->object); | |||||
| data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = | |||||
| *r_dist; | |||||
| ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); | ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); | ||||
| mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); | mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); | ||||
| hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; | hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; | ||||
| if (hit->dist < *r_dist) { | |||||
| if (r_base_index) { | |||||
| *r_base_index = base_index; | |||||
| } | |||||
| *r_dist = hit->dist; | *r_dist = hit->dist; | ||||
| } | |||||
| } | |||||
| if (r_dist_center) { | if (r_dist_center) { | ||||
| *r_dist_center = hit->dist_center; | *r_dist_center = hit->dist_center; | ||||
| } | } | ||||
| prev_select_elem = hit->edge; | prev_select_elem = hit->edge; | ||||
| prev_select_index = hit->index; | prev_select_index = hit->index; | ||||
| return hit->edge; | return hit->edge; | ||||
| } | } | ||||
| } | } | ||||
| BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) | BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) | ||||
| { | { | ||||
| return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); | Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); | ||||
| return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL); | |||||
| } | } | ||||
| /* find the distance to the face we already have */ | /* find the distance to the face we already have */ | ||||
| struct NearestFaceUserData_ZBuf { | struct NearestFaceUserData_ZBuf { | ||||
| float mval_fl[2]; | float mval_fl[2]; | ||||
| float dist; | float dist; | ||||
| const BMFace *face_test; | const BMFace *face_test; | ||||
| }; | }; | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | static void findnearestface__doClosest(void *userData, | ||||
| } | } | ||||
| } | } | ||||
| BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, | BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, | ||||
| float *r_dist, | float *r_dist, | ||||
| float *r_dist_center, | float *r_dist_center, | ||||
| const bool use_select_bias, | const bool use_select_bias, | ||||
| const bool use_cycle, | const bool use_cycle, | ||||
| BMFace **r_efa_zbuf) | BMFace **r_efa_zbuf, | ||||
| Base **bases, | |||||
| uint bases_len, | |||||
| uint *r_base_index) | |||||
| { | { | ||||
| BMesh *bm = vc->em->bm; | uint base_index = 0; | ||||
| if (!XRAY_FLAG_ENABLED(vc->v3d)) { | if (!XRAY_FLAG_ENABLED(vc->v3d)) { | ||||
| float dist_test = 0.0f; | float dist_test = 0.0f; | ||||
| unsigned int index; | uint index, offset; | ||||
| BMFace *efa; | BMFace *efa; | ||||
| { | FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE); | ||||
| FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_FACE) | |||||
| ; | edbm_select_pick_cache_alloc(bases_len); | ||||
| ED_view3d_select_id_validate_with_select_mode(vc, select_mode); | edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); | ||||
| index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); | index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); | ||||
| efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; | |||||
| FAKE_SELECT_MODE_END(vc, fake_select_mode); | if (index) { | ||||
| base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); | |||||
| ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); | |||||
| efa = BM_face_at_index_find_or_table(vc->em->bm, index - offset); | |||||
| } | } | ||||
| else { | |||||
| efa = NULL; | |||||
| } | |||||
| edbm_select_pick_cache_free(); | |||||
| FAKE_SELECT_MODE_END(vc, fake_select_mode); | |||||
| if (r_efa_zbuf) { | if (r_efa_zbuf) { | ||||
| *r_efa_zbuf = efa; | *r_efa_zbuf = efa; | ||||
| } | } | ||||
| /* exception for faces (verts don't need this) */ | /* exception for faces (verts don't need this) */ | ||||
| if (r_dist_center && efa) { | if (r_dist_center && efa) { | ||||
| struct NearestFaceUserData_ZBuf data; | struct NearestFaceUserData_ZBuf data; | ||||
| Show All 9 Lines | if (r_dist_center && efa) { | ||||
| vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); | ||||
| *r_dist_center = data.dist; | *r_dist_center = data.dist; | ||||
| } | } | ||||
| /* end exception */ | /* end exception */ | ||||
| if (efa) { | if (efa) { | ||||
| if (dist_test < *r_dist) { | if (dist_test < *r_dist) { | ||||
| if (r_base_index) { | |||||
| *r_base_index = base_index; | |||||
| } | |||||
| *r_dist = dist_test; | *r_dist = dist_test; | ||||
| return efa; | return efa; | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| else { | else { | ||||
| struct NearestFaceUserData data = {{0}}; | struct NearestFaceUserData data = {{0}}; | ||||
| const struct NearestFaceUserData_Hit *hit; | const struct NearestFaceUserData_Hit *hit; | ||||
| const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; | const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; | ||||
| static int prev_select_index = 0; | static int prev_select_index = 0; | ||||
| static const BMFace *prev_select_elem = NULL; | static const BMFace *prev_select_elem = NULL; | ||||
| if ((use_cycle == false) || | if ((use_cycle == false) || | ||||
| (prev_select_elem && | (prev_select_elem && | ||||
| (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) { | (prev_select_elem != BM_face_at_index_find_or_table(vc->em->bm, prev_select_index)))) { | ||||
| prev_select_index = 0; | prev_select_index = 0; | ||||
| prev_select_elem = NULL; | prev_select_elem = NULL; | ||||
| } | } | ||||
| data.mval_fl[0] = vc->mval[0]; | data.mval_fl[0] = vc->mval[0]; | ||||
| data.mval_fl[1] = vc->mval[1]; | data.mval_fl[1] = vc->mval[1]; | ||||
| data.use_select_bias = use_select_bias; | data.use_select_bias = use_select_bias; | ||||
| data.use_cycle = use_cycle; | data.use_cycle = use_cycle; | ||||
| data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; | |||||
| data.cycle_index_prev = prev_select_index; | data.cycle_index_prev = prev_select_index; | ||||
| for (; base_index < bases_len; base_index++) { | |||||
| Base *base_iter = bases[base_index]; | |||||
| ED_view3d_viewcontext_init_object(vc, base_iter->object); | |||||
| data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = | |||||
| *r_dist; | |||||
| ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); | ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); | ||||
| mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); | mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); | ||||
| hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; | hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; | ||||
| if (hit->dist < *r_dist) { | |||||
| if (r_base_index) { | |||||
| *r_base_index = base_index; | |||||
| } | |||||
| *r_dist = hit->dist; | *r_dist = hit->dist; | ||||
| } | |||||
| } | |||||
| if (r_dist_center) { | if (r_dist_center) { | ||||
| *r_dist_center = hit->dist; | *r_dist_center = hit->dist; | ||||
| } | } | ||||
| prev_select_elem = hit->face; | prev_select_elem = hit->face; | ||||
| prev_select_index = hit->index; | prev_select_index = hit->index; | ||||
| return hit->face; | return hit->face; | ||||
| } | } | ||||
| } | } | ||||
| BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) | BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) | ||||
| { | { | ||||
| return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); | Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); | ||||
| return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL); | |||||
| } | } | ||||
| #undef FIND_NEAR_SELECT_BIAS | #undef FIND_NEAR_SELECT_BIAS | ||||
| #undef FIND_NEAR_CYCLE_THRESHOLD_MIN | #undef FIND_NEAR_CYCLE_THRESHOLD_MIN | ||||
| /* best distance based on screen coords. | /* best distance based on screen coords. | ||||
| * use em->selectmode to define how to use | * use em->selectmode to define how to use | ||||
| * selected vertices and edges get disadvantage | * selected vertices and edges get disadvantage | ||||
| Show All 26 Lines | struct { | ||||
| int base_index; | int base_index; | ||||
| } e, e_zbuf; | } e, e_zbuf; | ||||
| struct { | struct { | ||||
| BMFace *ele; | BMFace *ele; | ||||
| int base_index; | int base_index; | ||||
| } f, f_zbuf; | } f, f_zbuf; | ||||
| } hit = {{NULL}}; | } hit = {{NULL}}; | ||||
| /* TODO(campbell): perform selection as one pass | |||||
| * instead of many smaller passes (which doesn't work for zbuf occlusion). */ | |||||
| /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ | /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ | ||||
| short selectmode = vc->scene->toolsettings->selectmode; | |||||
| if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { | if ((dist > 0.0f) && (selectmode & SCE_SELECT_FACE)) { | ||||
| float dist_center = 0.0f; | float dist_center = 0.0f; | ||||
| float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? | float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? | ||||
| &dist_center : | &dist_center : | ||||
| NULL; | NULL; | ||||
| for (uint base_index = 0; base_index < bases_len; base_index++) { | uint base_index = 0; | ||||
| Base *base_iter = bases[base_index]; | |||||
| Object *obedit = base_iter->object; | |||||
| ED_view3d_viewcontext_init_object(vc, obedit); | |||||
| BLI_assert(vc->em->selectmode == em->selectmode); | |||||
| BMFace *efa_zbuf = NULL; | BMFace *efa_zbuf = NULL; | ||||
| BMFace *efa_test = EDBM_face_find_nearest_ex( | BMFace *efa_test = EDBM_face_find_nearest_ex( | ||||
| vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); | vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index); | ||||
| if (efa_test && dist_center_p) { | if (efa_test && dist_center_p) { | ||||
| dist = min_ff(dist_margin, dist_center); | dist = min_ff(dist_margin, dist_center); | ||||
| } | } | ||||
| if (efa_test) { | if (efa_test) { | ||||
| hit.f.base_index = base_index; | hit.f.base_index = base_index; | ||||
| hit.f.ele = efa_test; | hit.f.ele = efa_test; | ||||
| } | } | ||||
| if (efa_zbuf) { | if (efa_zbuf) { | ||||
| hit.f_zbuf.base_index = base_index; | hit.f_zbuf.base_index = base_index; | ||||
| hit.f_zbuf.ele = efa_zbuf; | hit.f_zbuf.ele = efa_zbuf; | ||||
| } | } | ||||
| } /* bases */ | |||||
| } | } | ||||
| if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { | if ((dist > 0.0f) && (selectmode & SCE_SELECT_EDGE)) { | ||||
| float dist_center = 0.0f; | float dist_center = 0.0f; | ||||
| float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; | float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; | ||||
| for (uint base_index = 0; base_index < bases_len; base_index++) { | uint base_index = 0; | ||||
| Base *base_iter = bases[base_index]; | |||||
| Object *obedit = base_iter->object; | |||||
| ED_view3d_viewcontext_init_object(vc, obedit); | |||||
| BMEdge *eed_zbuf = NULL; | BMEdge *eed_zbuf = NULL; | ||||
| BMEdge *eed_test = EDBM_edge_find_nearest_ex( | BMEdge *eed_test = EDBM_edge_find_nearest_ex( | ||||
| vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); | vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf, bases, bases_len, &base_index); | ||||
| if (eed_test && dist_center_p) { | if (eed_test && dist_center_p) { | ||||
| dist = min_ff(dist_margin, dist_center); | dist = min_ff(dist_margin, dist_center); | ||||
| } | } | ||||
| if (eed_test) { | if (eed_test) { | ||||
| hit.e.base_index = base_index; | hit.e.base_index = base_index; | ||||
| hit.e.ele = eed_test; | hit.e.ele = eed_test; | ||||
| } | } | ||||
| if (eed_zbuf) { | if (eed_zbuf) { | ||||
| hit.e_zbuf.base_index = base_index; | hit.e_zbuf.base_index = base_index; | ||||
| hit.e_zbuf.ele = eed_zbuf; | hit.e_zbuf.ele = eed_zbuf; | ||||
| } | } | ||||
| } /* bases */ | |||||
| } | } | ||||
| if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { | if ((dist > 0.0f) && (selectmode & SCE_SELECT_VERTEX)) { | ||||
| for (uint base_index = 0; base_index < bases_len; base_index++) { | uint base_index = 0; | ||||
| Base *base_iter = bases[base_index]; | BMVert *eve_test = EDBM_vert_find_nearest_ex( | ||||
| Object *obedit = base_iter->object; | vc, &dist, true, use_cycle, bases, bases_len, &base_index); | ||||
| ED_view3d_viewcontext_init_object(vc, obedit); | |||||
| BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); | |||||
| if (eve_test) { | if (eve_test) { | ||||
| hit.v.base_index = base_index; | hit.v.base_index = base_index; | ||||
| hit.v.ele = eve_test; | hit.v.ele = eve_test; | ||||
| } | } | ||||
| } /* bases */ | |||||
| } | } | ||||
| /* return only one of 3 pointers, for frontbuffer redraws */ | /* return only one of 3 pointers, for frontbuffer redraws */ | ||||
| if (hit.v.ele) { | if (hit.v.ele) { | ||||
| hit.f.ele = NULL; | hit.f.ele = NULL; | ||||
| hit.e.ele = NULL; | hit.e.ele = NULL; | ||||
| } | } | ||||
| else if (hit.e.ele) { | else if (hit.e.ele) { | ||||
| ▲ Show 20 Lines • Show All 3,842 Lines • Show Last 20 Lines | |||||