[Bf-blender-cvs] [e3a6440] master: BMesh: mesh-data picking, general improvements
Campbell Barton
noreply at git.blender.org
Tue Apr 21 13:26:01 CEST 2015
Commit: e3a6440e7af7f90432319aec9f6ad43b557def31
Author: Campbell Barton
Date: Tue Apr 21 21:16:19 2015 +1000
Branches: master
https://developer.blender.org/rBe3a6440e7af7f90432319aec9f6ad43b557def31
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).
===================================================================
M source/blender/editors/include/ED_mesh.h
M source/blender/editors/include/ED_view3d.h
M source/blender/editors/mesh/editmesh_select.c
M source/blender/editors/space_view3d/view3d_draw.c
===================================================================
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 3c67236..b982ff2 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 6be7f70..ab270f6 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 84ca945..92c7dde 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;
+ }
+
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list