Cleanup: move selection utilities into ED_select_buffer_utils
This commit is contained in:
parent
164b6c5b04
commit
d496236f4a
|
@ -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__ */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
Loading…
Reference in New Issue