diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-05-20 06:16:29 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-05-20 06:19:24 +0300 |
commit | d496236f4aefad9dfb8ae456e1799eb8e6f175d0 (patch) | |
tree | 4270fc5419ae1f9b6a0f3c74d796e5efaff8e6a9 /source | |
parent | 164b6c5b047e82c84793ecb43cbbee9f3b6e245e (diff) |
Cleanup: move selection utilities into ED_select_buffer_utils
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/include/ED_select_buffer_utils.h | 8 | ||||
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 3 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 7 | ||||
-rw-r--r-- | source/blender/editors/mesh/meshtools.c | 9 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_utils.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw_legacy.c | 95 | ||||
-rw-r--r-- | source/blender/editors/util/select_buffer_utils.c | 124 |
7 files changed, 143 insertions, 106 deletions
diff --git a/source/blender/editors/include/ED_select_buffer_utils.h b/source/blender/editors/include/ED_select_buffer_utils.h index 54e4cdb6e4f..af745cee676 100644 --- a/source/blender/editors/include/ED_select_buffer_utils.h +++ b/source/blender/editors/include/ED_select_buffer_utils.h @@ -23,6 +23,7 @@ struct rcti; +/* Boolean array from selection ID's. */ uint *ED_select_buffer_bitmap_from_rect(const uint bitmap_len, const struct rcti *rect); uint *ED_select_buffer_bitmap_from_circle(const uint bitmap_len, const int center[2], @@ -32,4 +33,11 @@ uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len, const int poly_len, const rcti *rect); +/* Single result from selection ID's. */ +uint ED_select_buffer_sample_point(const int center[2]); +uint ED_select_buffer_find_nearest_to_point(const int center[2], + const uint id_min, + const uint id_max, + uint *dist); + #endif /* __ED_SELECT_BUFFER_UTILS_H__ */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 6110d35ab0d..1c5fc3340eb 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -451,11 +451,8 @@ int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); void ED_view3d_select_id_validate(struct ViewContext *vc); -uint ED_view3d_select_id_sample(struct ViewContext *vc, int x, int y); uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len); uint *ED_view3d_select_id_read_rect(const struct rcti *rect, uint *r_buf_len); -uint ED_view3d_select_id_read_nearest( - struct ViewContext *vc, const int mval[2], const uint min, const uint max, uint *r_dist); bool ED_view3d_autodist(struct Depsgraph *depsgraph, struct ARegion *ar, diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index b1cd21e9e32..dc94219cb9a 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -53,6 +53,7 @@ #include "ED_mesh.h" #include "ED_screen.h" #include "ED_transform.h" +#include "ED_select_buffer_utils.h" #include "ED_select_utils.h" #include "ED_view3d.h" @@ -476,7 +477,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { eve = (BMVert *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -701,7 +702,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { eed = (BMEdge *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -910,7 +911,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); + index = ED_select_buffer_sample_point(vc->mval); if (index) { efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index e29cfa6b6e0..41736fb9a14 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -61,6 +61,7 @@ #include "DEG_depsgraph_query.h" #include "ED_mesh.h" +#include "ED_select_buffer_utils.h" #include "ED_object.h" #include "ED_view3d.h" @@ -1114,11 +1115,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, if (dist_px) { /* sample rect to increase chances of selecting, so that when clicking * on an edge in the backbuf, we can still select a face */ - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px); + *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totpoly + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); } if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) { @@ -1295,11 +1296,11 @@ bool ED_mesh_pick_vert( if (dist_px > 0) { /* sample rect to increase chances of selecting, so that when clicking * on an face in the backbuf, we can still select a vert */ - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px); + *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totvert + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); } if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) { diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 84b4a130183..c8ad1b5781d 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -71,6 +71,7 @@ #include "BLI_sys_types.h" #include "ED_mesh.h" /* for face mask functions */ +#include "ED_select_buffer_utils.h" #include "WM_api.h" #include "WM_types.h" @@ -390,7 +391,7 @@ static int imapaint_pick_face(ViewContext *vc, /* sample only on the exact position */ ED_view3d_select_id_validate(vc); - *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 1d785c67e8b..755852a2e18 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -277,22 +277,6 @@ int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); } -/* samples a single pixel (copied from vpaint) */ -uint ED_view3d_select_id_sample(ViewContext *vc, int x, int y) -{ - if (x >= vc->ar->winx || y >= vc->ar->winy) { - return 0; - } - - uint buf_len; - uint *buf = ED_view3d_select_id_read(x, y, x, y, &buf_len); - BLI_assert(0 != buf_len); - uint ret = buf[0]; - MEM_freeN(buf); - - return ret; -} - /* reads full rect, converts indices */ uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) { @@ -317,85 +301,6 @@ uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_b return buf; } -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -uint ED_view3d_select_id_read_nearest(struct ViewContext *UNUSED(vc), - const int mval[2], - const uint id_min, - const uint id_max, - uint *r_dist) -{ - /* Create region around mouse cursor. This must be square and have an odd - * width, the spiraling algorithm does not work with arbitrary rectangles. */ - rcti rect; - BLI_rcti_init_pt_radius(&rect, mval, *r_dist); - rect.xmax += 1; - rect.ymax += 1; - - int width = BLI_rcti_size_x(&rect); - int height = width; - BLI_assert(width == height); - - /* Read from selection framebuffer. */ - uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__); - DRW_framebuffer_select_id_read(&rect, buf); - - /* Spiral, starting from center of buffer. */ - int spiral_offset = height * (int)(width / 2) + (height / 2); - int spiral_direction = 0; - - uint index = 0; - - for (int nr = 1; nr <= height; nr++) { - for (int a = 0; a < 2; a++) { - for (int b = 0; b < nr; b++) { - /* Find hit within the specified range. */ - uint hit_id = buf[spiral_offset]; - - if (hit_id && hit_id >= id_min && hit_id < id_max) { - /* Get x/y from spiral offset. */ - int hit_x = spiral_offset % width; - int hit_y = spiral_offset / width; - - int center_x = width / 2; - int center_y = height / 2; - - /* Manhatten distance in keeping with other screen-based selection. */ - *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); - - /* Indices start at 1 here. */ - index = (hit_id - id_min) + 1; - goto exit; - } - - /* Next spiral step. */ - if (spiral_direction == 0) { - spiral_offset += 1; /* right */ - } - else if (spiral_direction == 1) { - spiral_offset -= width; /* down */ - } - else if (spiral_direction == 2) { - spiral_offset -= 1; /* left */ - } - else { - spiral_offset += width; /* up */ - } - - /* Stop if we are outside the buffer. */ - if (spiral_offset < 0 || spiral_offset >= width * height) { - goto exit; - } - } - - spiral_direction = (spiral_direction + 1) % 4; - } - } - -exit: - MEM_freeN(buf); - return index; -} - /* ************************************************************* */ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) diff --git a/source/blender/editors/util/select_buffer_utils.c b/source/blender/editors/util/select_buffer_utils.c index 8818757653e..130f6819e34 100644 --- a/source/blender/editors/util/select_buffer_utils.c +++ b/source/blender/editors/util/select_buffer_utils.c @@ -19,6 +19,11 @@ /** \file * \ingroup edutil + * + * Generic utilities for handling buffer selection where selection ID's are drawn onto + * an off screen buffer. + * + * All coordinates are relative to the current region. */ #include "MEM_guardedalloc.h" @@ -35,6 +40,14 @@ * way to read from selection buffers that doesn't depend on the view3d API. */ #include "ED_view3d.h" +/* -------------------------------------------------------------------- */ +/** \name Select Bitmap from ID's + * + * Given a buffer of select ID's, fill in a booleans (true/false) per index. + * #BLI_bitmap is used for memory effeciency. + * + * \{ */ + /** * \param bitmap_len: Number of indices in the selection id buffer. * \param rect: The rectangle to sample indices from (min/max inclusive). @@ -177,3 +190,114 @@ uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len, return bitmap_buf; } + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Find Single Select ID's + * + * Given a buffer of select ID's, find the a single select id. + * + * \{ */ + +/** + * Samples a single pixel. + */ +uint ED_select_buffer_sample_point(const int center[2]) +{ + uint buf_len; + uint *buf = ED_view3d_select_id_read(center[0], center[1], center[0], center[1], &buf_len); + BLI_assert(0 != buf_len); + uint ret = buf[0]; + MEM_freeN(buf); + return ret; +} + +/** + * Find the selection id closest to \a center. + * \param dist[in,out]: Use to initalize the distance, + * when found, this value is set to the distance of the selection thats returned. + */ +uint ED_select_buffer_find_nearest_to_point(const int center[2], + const uint id_min, + const uint id_max, + uint *dist) +{ + /* Smart function to sample a rect spiralling outside, nice for selection ID. */ + + /* Create region around center (typically the mouse cursor). + * This must be square and have an odd width, + * the spiraling algorithm does not work with arbitrary rectangles. */ + rcti rect; + BLI_rcti_init_pt_radius(&rect, center, *dist); + rect.xmax += 1; + rect.ymax += 1; + + int width = BLI_rcti_size_x(&rect); + int height = width; + BLI_assert(width == height); + + /* Read from selection framebuffer. */ + + uint buf_len; + const uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len); + BLI_assert(width * height == buf_len); + + /* Spiral, starting from center of buffer. */ + int spiral_offset = height * (int)(width / 2) + (height / 2); + int spiral_direction = 0; + + uint index = 0; + + for (int nr = 1; nr <= height; nr++) { + for (int a = 0; a < 2; a++) { + for (int b = 0; b < nr; b++) { + /* Find hit within the specified range. */ + uint hit_id = buf[spiral_offset]; + + if (hit_id && hit_id >= id_min && hit_id < id_max) { + /* Get x/y from spiral offset. */ + int hit_x = spiral_offset % width; + int hit_y = spiral_offset / width; + + int center_x = width / 2; + int center_y = height / 2; + + /* Manhatten distance in keeping with other screen-based selection. */ + *dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); + + /* Indices start at 1 here. */ + index = (hit_id - id_min) + 1; + goto exit; + } + + /* Next spiral step. */ + if (spiral_direction == 0) { + spiral_offset += 1; /* right */ + } + else if (spiral_direction == 1) { + spiral_offset -= width; /* down */ + } + else if (spiral_direction == 2) { + spiral_offset -= 1; /* left */ + } + else { + spiral_offset += width; /* up */ + } + + /* Stop if we are outside the buffer. */ + if (spiral_offset < 0 || spiral_offset >= buf_len) { + goto exit; + } + } + + spiral_direction = (spiral_direction + 1) % 4; + } + } + +exit: + MEM_freeN((void *)buf); + return index; +} + +/** \} */ |