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-23 09:11:54 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-04-23 09:11:54 +0300
commit8010672bbc1a89e2b7c30bc22e936052325e4b75 (patch)
treed28861695eb506f2170a65dfd67e7a5e19c6e66a /source/blender
parent87b3e62b3d2110d4701e49389492f1b3528c9cdf (diff)
BMesh: mesh-data picking, edge+vert improvement
When zoomed out vert bias over edges meant it wasn't possible to select edges. Now pick the edge if the cursor is closer to its center.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/include/ED_mesh.h14
-rw-r--r--source/blender/editors/mesh/editmesh_select.c120
2 files changed, 110 insertions, 24 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index b982ff2a83b..55a254c7941 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -137,17 +137,23 @@ 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,
+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, const bool use_cycle);
+struct BMEdge *EDBM_edge_find_nearest_ex(
+ struct ViewContext *vc,float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ struct BMEdge **r_eed_zbuf);
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,
+ float *r_dist_center,
const bool use_select_bias, const bool use_cycle,
struct BMFace **r_efa_zbuf);
struct BMFace *EDBM_face_find_nearest(
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 90b683c5abd..3760ebcc2a4 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -489,11 +489,42 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
}
+/* find the distance to the edge we already have */
+struct NearestEdgeUserData_ZBuf {
+ float mval_fl[2];
+ float dist;
+ const BMEdge *edge_test;
+};
+
+static void find_nearest_edge_center__doZBuf(
+ void *userData, BMEdge *eed,
+ const float screen_co_a[2], const float screen_co_b[2],
+ int UNUSED(index))
+{
+ struct NearestEdgeUserData_ZBuf *data = userData;
+
+ if (eed == data->edge_test) {
+ float dist_test;
+ float screen_co_mid[2];
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ }
+ }
+}
+
struct NearestEdgeUserData_Hit {
float dist;
float dist_bias;
int index;
BMEdge *edge;
+
+ /* edges only, un-biased manhatten distance to which ever edge we pick
+ * (not used for choosing) */
+ float dist_center;
};
struct NearestEdgeUserData {
@@ -508,7 +539,10 @@ struct NearestEdgeUserData {
};
/* 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 index)
+static void find_nearest_edge__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;
@@ -544,10 +578,15 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float
}
if (dist_test_bias < data->hit.dist_bias) {
+ float screen_co_mid[2];
+
data->hit.dist_bias = dist_test_bias;
data->hit.dist = dist_test;
data->hit.index = index;
data->hit.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
}
if (data->use_cycle) {
@@ -555,23 +594,30 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float
(index > data->cycle_index_prev) &&
(dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
{
+ float screen_co_mid[2];
+
data->hit_cycle.dist_bias = dist_test_bias;
data->hit_cycle.dist = dist_test;
data->hit_cycle.index = index;
data->hit_cycle.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
}
}
}
BMEdge *EDBM_edge_find_nearest_ex(
ViewContext *vc, float *r_dist,
- const bool use_select_bias, const bool use_cycle)
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ BMEdge **r_eed_zbuf)
{
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 dist_test;
+ float dist_test = 0.0f;
unsigned int index;
BMEdge *eed;
@@ -579,7 +625,28 @@ BMEdge *EDBM_edge_find_nearest_ex(
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 (r_eed_zbuf) {
+ *r_eed_zbuf = eed;
+ }
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && eed) {
+ struct NearestEdgeUserData_ZBuf data;
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.dist = FLT_MAX;
+ data.edge_test = eed;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
if (eed) {
if (dist_test < *r_dist) {
*r_dist = dist_test;
@@ -614,10 +681,11 @@ BMEdge *EDBM_edge_find_nearest_ex(
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, find_nearest_edge__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
*r_dist = hit->dist;
+ *r_dist_center = hit->dist_center;
prev_select_elem = hit->edge;
prev_select_index = hit->index;
@@ -629,7 +697,7 @@ BMEdge *EDBM_edge_find_nearest_ex(
BMEdge *EDBM_edge_find_nearest(
ViewContext *vc, float *r_dist)
{
- return EDBM_edge_find_nearest_ex(vc, r_dist, false, false);
+ return EDBM_edge_find_nearest_ex(vc, r_dist, false, false, false, NULL);
}
/* find the distance to the face we already have */
@@ -639,7 +707,7 @@ struct NearestFaceUserData_ZBuf {
const BMFace *face_test;
};
-static void findnearestface__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
{
struct NearestFaceUserData_ZBuf *data = userData;
@@ -704,13 +772,14 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float
BMFace *EDBM_face_find_nearest_ex(
ViewContext *vc, float *r_dist,
+ float *r_dist_center,
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;
+ float dist_test = 0.0f;
unsigned int index;
BMFace *efa;
@@ -723,8 +792,8 @@ BMFace *EDBM_face_find_nearest_ex(
*r_efa_zbuf = efa;
}
- /* exception for faces (verts/edges don't need this) */
- if (efa) {
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && efa) {
struct NearestFaceUserData_ZBuf data;
data.mval_fl[0] = vc->mval[0];
@@ -734,9 +803,9 @@ BMFace *EDBM_face_find_nearest_ex(
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- dist_test = data.dist;
+ *r_dist_center = data.dist;
}
/* end exception */
@@ -775,7 +844,7 @@ BMFace *EDBM_face_find_nearest_ex(
mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
+ *r_dist = *r_dist_center = hit->dist;
prev_select_elem = hit->face;
prev_select_index = hit->index;
@@ -786,7 +855,7 @@ BMFace *EDBM_face_find_nearest_ex(
BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_face_find_nearest_ex(vc, r_dist, false, false, NULL);
+ return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
}
#undef FIND_NEAR_SELECT_BIAS
@@ -806,9 +875,10 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed,
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_bias = (dist_init / 4);
+ const float dist_margin = (dist_init / 2);
float dist = dist_init;
BMFace *efa_zbuf = NULL;
+ BMEdge *eed_zbuf = NULL;
BMVert *eve = NULL;
BMEdge *eed = NULL;
@@ -819,13 +889,20 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed,
ED_view3d_backbuf_validate(vc);
if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
- efa = EDBM_face_find_nearest_ex(vc, &dist, true, use_cycle, &efa_zbuf);
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
+ efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
+ if (efa && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
}
if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
- eed = EDBM_edge_find_nearest_ex(vc, &dist, true, use_cycle);
- if (eed) {
- dist = min_ff(dist + dist_bias, dist_init);
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
+ eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
+ if (eed && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
}
}
@@ -844,7 +921,10 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed,
/* 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) {
+ if (eed_zbuf) {
+ eed = eed_zbuf;
+ }
+ else if (efa_zbuf) {
efa = efa_zbuf;
}
}