Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2015-04-21 14:16:19 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-04-21 14:25:43 +0300
commite3a6440e7af7f90432319aec9f6ad43b557def31 (patch)
tree6fa80f9fc9547d6c20b9cd92e0b673865f588257
parent907d4d310f697a2a9b5c83bb2fc428175a7daaf2 (diff)
BMesh: mesh-data picking, general improvements
Generalize logic for vert/edge/face selection: - index cycling. - selection bias with mixed modes. Details: - Edges now support index cycling (as verts/faces did already) - Cycling over near elements is now only enabled when the mouse position remains the same. - No longer do 2 selection passes to perform index cycling. Fixes: - Edges behind the view could be selected (surprising nobody reported!) - Selection bias now only changes the element that gets picked without interning the return distance (was buggy with mixed modes).
-rw-r--r--source/blender/editors/include/ED_mesh.h14
-rw-r--r--source/blender/editors/include/ED_view3d.h2
-rw-r--r--source/blender/editors/mesh/editmesh_select.c381
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c12
4 files changed, 244 insertions, 165 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 3c672362a54..b982ff2a83b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -137,20 +137,18 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2]
short xmin, short ymin, short xmax, short ymax);
bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
-struct BMVert *EDBM_vert_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
- const bool use_select_bias);
+struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist,
+ const bool use_select_bias, bool use_cycle);
struct BMVert *EDBM_vert_find_nearest(
struct ViewContext *vc, float *r_dist);
-struct BMEdge *EDBM_edge_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
- const bool use_select_bias);
+struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, float *r_dist,
+ const bool use_select_bias, const bool use_cycle);
struct BMEdge *EDBM_edge_find_nearest(
struct ViewContext *vc, float *r_dist);
-struct BMFace *EDBM_face_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
+struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, float *r_dist,
+ const bool use_select_bias, const bool use_cycle,
struct BMFace **r_efa_zbuf);
struct BMFace *EDBM_face_find_nearest(
struct ViewContext *vc, float *r_dist);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 6be7f706f28..ab270f657a4 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -271,7 +271,7 @@ void ED_view3d_backbuf_validate(struct ViewContext *vc);
struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
unsigned int ED_view3d_backbuf_sample_rect(
struct ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *dist);
+ unsigned int min, unsigned int max, float *r_dist);
int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 84ca945bf48..92c7dde1f6f 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -354,45 +354,62 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
/* -------------------------------------------------------------------- */
/** \name Find Nearest Vert/Edge/Face
+ *
+ * \note Screen-space manhatten distances are used here,
+ * since its faster and good enough for the purpose of selection.
+ *
+ * \note \a dist_bias is used so we can bias against selected items.
+ * when choosing between elements of a single type, but return the real distance
+ * to avoid the bias interfering with distance comparisons when mixing types.
* \{ */
-#define FIND_NEAR_THRESHOLD_MIN 3
-#define FIND_NEAR_BIAS 5
+#define FIND_NEAR_SELECT_BIAS 5
+#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3
+
+struct NearestVertUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMVert *vert;
+};
struct NearestVertUserData {
float mval_fl[2];
- int pass;
bool use_select_bias;
- float dist;
- int index_last;
- int index_nearest;
- BMVert *vert_nearest;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestVertUserData_Hit hit;
+ struct NearestVertUserData_Hit hit_cycle;
};
static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
{
struct NearestVertUserData *data = userData;
+ float dist_test, dist_test_bias;
- if (data->pass == 0) {
- if (index <= data->index_last)
- return;
- }
- else {
- if (index > data->index_last)
- return;
- }
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
- if (data->dist > FIND_NEAR_THRESHOLD_MIN) {
- float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+ if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
- if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- dist_test += FIND_NEAR_BIAS;
- }
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.vert = eve;
+ }
- if (dist_test < data->dist) {
- data->dist = dist_test;
- data->vert_nearest = eve;
- data->index_nearest = index;
+ if (data->use_cycle) {
+ if ((data->hit_cycle.vert == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.vert = eve;
}
}
}
@@ -408,89 +425,94 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float
*/
BMVert *EDBM_vert_find_nearest_ex(
ViewContext *vc, float *r_dist,
- const bool use_select_bias)
+ const bool use_select_bias, bool use_cycle)
{
BMesh *bm = vc->em->bm;
if (V3D_IS_ZBUF(vc->v3d)) {
const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- float distance;
+ float dist_test;
unsigned int index;
BMVert *eve;
index = ED_view3d_backbuf_sample_rect(
- vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance);
-
+ vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
- if (eve && distance < *r_dist) {
- *r_dist = distance;
- return eve;
- }
- else {
- return NULL;
+ if (eve) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return eve;
+ }
}
+ return NULL;
}
else {
- struct NearestVertUserData data;
+ struct NearestVertUserData data = {{0}};
+ const struct NearestVertUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
static int prev_select_index = 0;
static const BMVert *prev_select_elem = NULL;
- if (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))) {
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))))
+ {
prev_select_index = 0;
prev_select_elem = NULL;
}
- data.index_last = prev_select_index;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
- data.dist = *r_dist;
-
- data.vert_nearest = NULL;
- data.index_nearest = 0;
-
- data.pass = 0;
+ 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;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- if (data.dist > FIND_NEAR_THRESHOLD_MIN) {
- data.pass = 1;
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
+ hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
- *r_dist = data.dist;
- prev_select_elem = data.vert_nearest;
- prev_select_index = data.index_nearest;
+ prev_select_elem = hit->vert;
+ prev_select_index = hit->index;
- return data.vert_nearest;
+ return hit->vert;
}
}
BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_vert_find_nearest_ex(vc, r_dist, false);
+ return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
}
+struct NearestEdgeUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMEdge *edge;
+};
struct NearestEdgeUserData {
ViewContext vc;
float mval_fl[2];
bool use_select_bias;
- char hflag_select;
- float dist;
- BMEdge *edge_nearest;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestEdgeUserData_Hit hit;
+ struct NearestEdgeUserData_Hit hit_cycle;
};
/* note; uses v3d, so needs active 3d window */
-static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
+static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
struct NearestEdgeUserData *data = userData;
+ float dist_test, dist_test_bias;
+
float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
- float distance;
float screen_co[2];
if (fac <= 0.0f) {
@@ -505,93 +527,117 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float
interp_v3_v3v3(screen_co, screen_co_a, screen_co_b, fac);
}
- distance = len_manhattan_v2v2(data->mval_fl, screen_co);
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- distance += FIND_NEAR_BIAS;
+ dist_test += FIND_NEAR_SELECT_BIAS;
}
- if (distance < data->dist) {
- if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
- float vec[3];
+ if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
- interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
- if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) {
- data->dist = distance;
- data->edge_nearest = eed;
- }
+ interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
+ if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
+ return;
}
- else {
- data->dist = distance;
- data->edge_nearest = eed;
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.edge = eed;
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.edge == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.edge = eed;
}
}
}
BMEdge *EDBM_edge_find_nearest_ex(
ViewContext *vc, float *r_dist,
- const bool use_select_bias)
+ const bool use_select_bias, const bool use_cycle)
{
BMesh *bm = vc->em->bm;
if (V3D_IS_ZBUF(vc->v3d)) {
const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- float distance;
+ float dist_test;
unsigned int index;
BMEdge *eed;
ED_view3d_backbuf_validate(vc);
- index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &distance);
+ index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
- if (eed && distance < *r_dist) {
- *r_dist = distance;
- return eed;
- }
- else {
- return NULL;
+ if (eed) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return eed;
+ }
}
+ return NULL;
}
else {
- struct NearestEdgeUserData data;
+ struct NearestEdgeUserData data = {{0}};
+ const struct NearestEdgeUserData_Hit *hit;
+ /* interpolate along the edge before doing a boundbox check */
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
+
+ static int prev_select_index = 0;
+ static const BMEdge *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index))))
+ {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
data.vc = *vc;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
- data.dist = *r_dist;
- data.edge_nearest = NULL;
+ 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;
+
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, clip_flag);
- mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN);
+ hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
- *r_dist = data.dist;
- return data.edge_nearest;
+ prev_select_elem = hit->edge;
+ prev_select_index = hit->index;
+
+ return hit->edge;
}
}
BMEdge *EDBM_edge_find_nearest(
ViewContext *vc, float *r_dist)
{
- return EDBM_edge_find_nearest_ex(vc, r_dist, false);
+ return EDBM_edge_find_nearest_ex(vc, r_dist, false, false);
}
+/* find the distance to the face we already have */
struct NearestFaceUserData_ZBuf {
float mval_fl[2];
float dist;
const BMFace *face_test;
};
-struct NearestFaceUserData_Closest {
- float mval_fl[2];
- int pass;
- float dist;
- int index_last;
- int index_nearest;
- BMFace *face_nearest;
-};
-
static void findnearestface__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
{
struct NearestFaceUserData_ZBuf *data = userData;
@@ -606,26 +652,50 @@ static void findnearestface__doZBuf(void *userData, BMFace *efa, const float scr
}
+struct NearestFaceUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMFace *face;
+};
+
+struct NearestFaceUserData {
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestFaceUserData_Hit hit;
+ struct NearestFaceUserData_Hit hit_cycle;
+};
+
static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index)
{
- struct NearestFaceUserData_Closest *data = userData;
+ struct NearestFaceUserData *data = userData;
+ float dist_test, dist_test_bias;
- if (data->pass == 0) {
- if (index <= data->index_last)
- return;
- }
- else {
- if (index > data->index_last)
- return;
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
- if (data->dist > FIND_NEAR_THRESHOLD_MIN) {
- const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.face = efa;
+ }
- if (dist_test < data->dist) {
- data->dist = dist_test;
- data->face_nearest = efa;
- data->index_nearest = index;
+ if (data->use_cycle) {
+ if ((data->hit_cycle.face == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.face = efa;
}
}
}
@@ -633,11 +703,13 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float
BMFace *EDBM_face_find_nearest_ex(
ViewContext *vc, float *r_dist,
+ const bool use_select_bias, const bool use_cycle,
BMFace **r_efa_zbuf)
{
BMesh *bm = vc->em->bm;
if (V3D_IS_ZBUF(vc->v3d)) {
+ float dist_test;
unsigned int index;
BMFace *efa;
@@ -650,6 +722,7 @@ BMFace *EDBM_face_find_nearest_ex(
*r_efa_zbuf = efa;
}
+ /* exception for faces (verts/edges don't need this) */
if (efa) {
struct NearestFaceUserData_ZBuf data;
@@ -662,51 +735,57 @@ BMFace *EDBM_face_find_nearest_ex(
mesh_foreachScreenFace(vc, findnearestface__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if ((vc->em->selectmode == SCE_SELECT_FACE) || (data.dist < *r_dist)) { /* only faces, no dist check */
- *r_dist = data.dist;
+ dist_test = data.dist;
+ }
+ /* end exception */
+
+ if (efa) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
return efa;
}
}
-
return NULL;
}
else {
- struct NearestFaceUserData_Closest data;
+ struct NearestFaceUserData data = {{0}};
+ const struct NearestFaceUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
static int prev_select_index = 0;
static const BMFace *prev_select_elem = NULL;
- if (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))) {
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))))
+ {
prev_select_index = 0;
prev_select_elem = NULL;
}
- data.index_last = prev_select_index;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.dist = *r_dist;
- data.face_nearest = NULL;
- data.index_nearest = 0;
+ data.use_select_bias = use_select_bias;
+ 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.pass = 0;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
- if (data.dist > FIND_NEAR_THRESHOLD_MIN) {
- data.pass = 1;
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
+ hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
- *r_dist = data.dist;
- prev_select_elem = data.face_nearest;
- prev_select_index = data.index_nearest;
+ prev_select_elem = hit->face;
+ prev_select_index = hit->index;
- return data.face_nearest;
+ return hit->face;
}
}
BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_face_find_nearest_ex(vc, r_dist, NULL);
+ return EDBM_face_find_nearest_ex(vc, r_dist, false, false, NULL);
}
@@ -718,44 +797,45 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
{
BMEditMesh *em = vc->em;
+ static short mval_prev[2] = {-1, -1};
+ /* only cycle while the mouse remains still */
+ const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
const float dist_init = ED_view3d_select_dist_px();
- /* since edges select lines, we give dots advantage of 20 pix */
- const float dist_edge_bias = (dist_init / 3.75f);
+ /* since edges select lines, we give dots advantage of ~20 pix */
+ const float dist_bias = (dist_init / 4);
float dist = dist_init;
- float dist_vert = dist_init;
BMFace *efa_zbuf = NULL;
BMVert *eve = NULL;
BMEdge *eed = NULL;
BMFace *efa = NULL;
-
+
+
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
ED_view3d_backbuf_validate(vc);
- if (em->selectmode & SCE_SELECT_VERTEX) {
- eve = EDBM_vert_find_nearest_ex(vc, &dist, true);
- dist_vert = dist;
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
+ efa = EDBM_face_find_nearest_ex(vc, &dist, true, use_cycle, &efa_zbuf);
}
- if (em->selectmode & SCE_SELECT_FACE) {
- efa = EDBM_face_find_nearest_ex(vc, &dist, eve ? &efa_zbuf : NULL);
+ if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
+ eed = EDBM_edge_find_nearest_ex(vc, &dist, true, use_cycle);
+ dist = min_ff(dist + dist_bias, dist_init);
}
- /* distance bias from verts (not faces) */
- dist = min_ff(dist, dist_vert - dist_edge_bias);
- if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
- eed = EDBM_edge_find_nearest_ex(vc, &dist, true);
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
+ eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
}
/* return only one of 3 pointers, for frontbuffer redraws */
- if (eed) {
- efa = NULL; eve = NULL;
+ if (eve) {
+ efa = NULL; eed = NULL;
}
- else if (efa) {
- eve = NULL;
+ else if (eed) {
+ efa = NULL;
}
- /* there may be a face under the cursor, but who's center if too far away
+ /* there may be a face under the cursor, who's center if too far away
* use this if all else fails, it makes sense to select this */
if ((eve || eed || efa) == 0) {
if (efa_zbuf) {
@@ -763,6 +843,9 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed,
}
}
+ mval_prev[0] = vc->mval[0];
+ mval_prev[1] = vc->mval[1];
+
*r_eve = eve;
*r_eed = eed;
*r_efa = efa;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 9fcdb77ef7f..a69a6be298e 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1587,13 +1587,11 @@ unsigned int ED_view3d_backbuf_sample_rect(
if (*tbuf && *tbuf >= min && *tbuf < max) {
/* we got a hit */
- /* get x,y pixel coords from the offset */
- const float delta[2] = {
- ((tbuf - buf->rect) % size) - (size / 2),
- ((tbuf - buf->rect) / size) - (size / 2),
- };
-
- *r_dist = len_v2(delta);
+ /* get x,y pixel coords from the offset
+ * (manhatten distance in keeping with other screen-based selection) */
+ *r_dist = (float)(
+ abs(((tbuf - buf->rect) % size) - (size / 2)) +
+ abs(((tbuf - buf->rect) / size) - (size / 2)));
/* indices start at 1 here */
index = (*tbuf - min) + 1;