diff options
author | mano-wii <germano.costa@ig.com.br> | 2019-08-12 18:10:44 +0300 |
---|---|---|
committer | mano-wii <germano.costa@ig.com.br> | 2019-08-12 18:10:44 +0300 |
commit | 44d95cbf9561a3b8840fb2145c22e0411d22f26d (patch) | |
tree | e0ed28bf7fc2e92a21afb0d14c9ab76b304676fd /source/blender/draw/engines/select | |
parent | 37b4384b59c09684ac4ece5e39bf20187968f737 (diff) |
Cleanup: DRW manager: Move `select_buffer.c` utilities out of the selection engine internals
Diffstat (limited to 'source/blender/draw/engines/select')
4 files changed, 4 insertions, 534 deletions
diff --git a/source/blender/draw/engines/select/select_buffer.c b/source/blender/draw/engines/select/select_buffer.c deleted file mode 100644 index b184992cb56..00000000000 --- a/source/blender/draw/engines/select/select_buffer.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Copyright 2019, Blender Foundation. - */ - -/** \file - * \ingroup draw_engine - * - * Utilities to read id buffer created in select_engine. - */ - -#include "MEM_guardedalloc.h" - -#include "BLI_bitmap.h" -#include "BLI_bitmap_draw_2d.h" -#include "BLI_rect.h" - -#include "DNA_screen_types.h" - -#include "GPU_select.h" - -#include "DRW_engine.h" -#include "DRW_select_buffer.h" - -#include "select_private.h" -#include "select_engine.h" - -/* -------------------------------------------------------------------- */ -/** \name Buffer of select ID's - * \{ */ - -/* Read a block of pixels from the select frame buffer. */ -uint *DRW_select_buffer_read(const rcti *rect, uint *r_buf_len) -{ - struct SELECTID_Context *select_ctx = select_context_get(); - - /* clamp rect by texture */ - rcti r = { - .xmin = 0, - .xmax = GPU_texture_width(select_ctx->texture_u32), - .ymin = 0, - .ymax = GPU_texture_height(select_ctx->texture_u32), - }; - - rcti rect_clamp = *rect; - if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) { - uint buf_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); - uint *r_buf = MEM_mallocN(buf_len * sizeof(*r_buf), __func__); - - DRW_opengl_context_enable(); - GPU_framebuffer_bind(select_ctx->framebuffer_select_id); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(rect_clamp.xmin, - rect_clamp.ymin, - BLI_rcti_size_x(&rect_clamp), - BLI_rcti_size_y(&rect_clamp), - GL_RED_INTEGER, - GL_UNSIGNED_INT, - r_buf); - - GPU_framebuffer_restore(); - DRW_opengl_context_disable(); - - if (!BLI_rcti_compare(rect, &rect_clamp)) { - GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); - } - - if (r_buf_len) { - *r_buf_len = buf_len; - } - - return r_buf; - } - return NULL; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \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 efficiency. - * - * \{ */ - -/** - * \param rect: The rectangle to sample indices from (min/max inclusive). - * \param mask: Specifies the rect pixels (optional). - * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. - */ -uint *DRW_select_buffer_bitmap_from_rect(const rcti *rect, uint *r_bitmap_len) -{ - struct SELECTID_Context *select_ctx = select_context_get(); - - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - - rcti rect_px = *rect; - rect_px.xmax += 1; - rect_px.ymax += 1; - - uint buf_len; - uint *buf = DRW_select_buffer_read(&rect_px, &buf_len); - if (buf == NULL) { - return NULL; - } - - BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); - const uint *buf_iter = buf; - while (buf_len--) { - const uint index = *buf_iter - 1; - if (index < bitmap_len) { - BLI_BITMAP_ENABLE(bitmap_buf, index); - } - buf_iter++; - } - MEM_freeN((void *)buf); - - if (r_bitmap_len) { - *r_bitmap_len = bitmap_len; - } - - return bitmap_buf; -} - -/** - * \param bitmap_len: Number of indices in the selection id buffer. - * \param center: Circle center. - * \param radius: Circle radius. - * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. - */ -uint *DRW_select_buffer_bitmap_from_circle(const int center[2], - const int radius, - uint *r_bitmap_len) -{ - struct SELECTID_Context *select_ctx = select_context_get(); - - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - - const rcti rect = { - .xmin = center[0] - radius, - .xmax = center[0] + radius + 1, - .ymin = center[1] - radius, - .ymax = center[1] + radius + 1, - }; - - const uint *buf = DRW_select_buffer_read(&rect, NULL); - - if (buf == NULL) { - return NULL; - } - - const uint *buf_iter = buf; - - BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); - const int radius_sq = radius * radius; - for (int yc = -radius; yc <= radius; yc++) { - for (int xc = -radius; xc <= radius; xc++, buf_iter++) { - if (xc * xc + yc * yc < radius_sq) { - /* Intentionally wrap to max value if this is zero. */ - const uint index = *buf_iter - 1; - if (index < bitmap_len) { - BLI_BITMAP_ENABLE(bitmap_buf, index); - } - } - } - } - MEM_freeN((void *)buf); - - if (r_bitmap_len) { - *r_bitmap_len = bitmap_len; - } - - return bitmap_buf; -} - -struct PolyMaskData { - BLI_bitmap *px; - int width; -}; - -static void drw_select_mask_px_cb(int x, int x_end, int y, void *user_data) -{ - struct PolyMaskData *data = user_data; - BLI_bitmap *px = data->px; - int i = (y * data->width) + x; - do { - BLI_BITMAP_ENABLE(px, i); - i++; - } while (++x != x_end); -} - -/** - * \param poly: The polygon coordinates. - * \param poly_len: Length of the polygon. - * \param rect: Polygon boundaries. - * \returns a #BLI_bitmap. - */ -uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len, const rcti *rect) -{ - struct SELECTID_Context *select_ctx = select_context_get(); - - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - - rcti rect_px = *rect; - rect_px.xmax += 1; - rect_px.ymax += 1; - - uint buf_len; - uint *buf = DRW_select_buffer_read(&rect_px, &buf_len); - if (buf == NULL) { - return NULL; - } - - BLI_bitmap *buf_mask = BLI_BITMAP_NEW(buf_len, __func__); - - struct PolyMaskData poly_mask_data; - poly_mask_data.px = buf_mask; - poly_mask_data.width = (rect->xmax - rect->xmin) + 1; - - BLI_bitmap_draw_2d_poly_v2i_n(rect_px.xmin, - rect_px.ymin, - rect_px.xmax, - rect_px.ymax, - poly, - poly_len, - drw_select_mask_px_cb, - &poly_mask_data); - - BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); - const uint *buf_iter = buf; - int i = 0; - while (buf_len--) { - const uint index = *buf_iter - 1; - if (index < bitmap_len && BLI_BITMAP_TEST(buf_mask, i)) { - BLI_BITMAP_ENABLE(bitmap_buf, index); - } - buf_iter++; - i++; - } - MEM_freeN((void *)buf); - MEM_freeN(buf_mask); - - 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 DRW_select_buffer_sample_point(const int center[2]) -{ - const rcti rect = { - .xmin = center[0], - .xmax = center[0] + 1, - .ymin = center[1], - .ymax = center[1] + 1, - }; - - uint buf_len; - uint *buf = DRW_select_buffer_read(&rect, &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 initialize the distance, - * when found, this value is set to the distance of the selection that's returned. - */ -uint DRW_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 spiraling 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. */ - - uint index = 0; - - 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 = DRW_select_buffer_read(&rect, &buf_len); - - if (buf == NULL) { - return index; - } - - 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; - - 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; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Object Utils - * \{ */ - -bool DRW_select_buffer_elem_get(const uint sel_id, - uint *r_elem, - uint *r_base_index, - char *r_elem_type) -{ - struct SELECTID_Context *select_ctx = select_context_get(); - - char elem_type = 0; - uint elem_id; - uint base_index = 0; - - for (; base_index < select_ctx->objects_len; base_index++) { - struct BaseOffset *base_ofs = &select_ctx->index_offsets[base_index]; - - if (base_ofs->face > sel_id) { - elem_id = sel_id - base_ofs->face_start; - elem_type = SCE_SELECT_FACE; - break; - } - if (base_ofs->edge > sel_id) { - elem_id = sel_id - base_ofs->edge_start; - elem_type = SCE_SELECT_EDGE; - break; - } - if (base_ofs->vert > sel_id) { - elem_id = sel_id - base_ofs->vert_start; - elem_type = SCE_SELECT_VERTEX; - break; - } - } - - if (base_index == select_ctx->objects_len) { - return false; - } - - *r_elem = elem_id; - - if (r_base_index) { - *r_base_index = base_index; - } - - if (r_elem_type) { - *r_elem_type = elem_type; - } - - return true; -} - -uint DRW_select_buffer_context_offset_for_object_elem(const uint base_index, char elem_type) -{ - struct SELECTID_Context *select_ctx = select_context_get(); - struct BaseOffset *base_ofs = &select_ctx->index_offsets[base_index]; - - if (elem_type == SCE_SELECT_VERTEX) { - return base_ofs->vert_start - 1; - } - if (elem_type == SCE_SELECT_EDGE) { - return base_ofs->edge_start - 1; - } - if (elem_type == SCE_SELECT_FACE) { - return base_ofs->face_start - 1; - } - BLI_assert(0); - return 0; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Context - * \{ */ - -void DRW_select_buffer_context_create(Base **UNUSED(bases), - const uint bases_len, - short select_mode) -{ - struct SELECTID_Context *select_ctx = select_context_get(); - - select_ctx->select_mode = select_mode; - select_ctx->objects_len = bases_len; - - MEM_SAFE_FREE(select_ctx->index_offsets); - select_ctx->index_offsets = MEM_mallocN(sizeof(*select_ctx->index_offsets) * bases_len, - __func__); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Legacy - * \{ */ - -void DRW_draw_select_id_object(Depsgraph *depsgraph, - ViewLayer *view_layer, - ARegion *ar, - View3D *v3d, - Object *ob, - short select_mode) -{ - Base *base = BKE_view_layer_base_find(view_layer, ob); - DRW_draw_select_id(depsgraph, ar, v3d, &base, 1, select_mode); -} - -/** \} */ diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c index c3ee7f962a1..b65a158cdcf 100644 --- a/source/blender/draw/engines/select/select_draw_utils.c +++ b/source/blender/draw/engines/select/select_draw_utils.c @@ -32,6 +32,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "DRW_select_buffer.h" + #include "draw_cache_impl.h" #include "select_private.h" diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index 3e4e4861f50..83f6563ab53 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -29,6 +29,7 @@ #include "UI_resources.h" #include "DRW_engine.h" +#include "DRW_select_buffer.h" #include "select_private.h" #include "select_engine.h" @@ -272,7 +273,7 @@ RenderEngineType DRW_engine_viewport_select_type = { /** \name Exposed `select_private.h` functions * \{ */ -struct SELECTID_Context *select_context_get(void) +struct SELECTID_Context *DRW_select_engine_context_get(void) { return &e_data.context; } diff --git a/source/blender/draw/engines/select/select_private.h b/source/blender/draw/engines/select/select_private.h index 2104f1485e7..d95b14ff2b6 100644 --- a/source/blender/draw/engines/select/select_private.h +++ b/source/blender/draw/engines/select/select_private.h @@ -62,39 +62,6 @@ typedef struct SELECTID_PrivateData { DRWView *view_verts; } SELECTID_PrivateData; /* Transient data */ -struct BaseOffset { - /* For convenience only. */ - union { - uint offset; - uint face_start; - }; - union { - uint face; - uint edge_start; - }; - union { - uint edge; - uint vert_start; - }; - uint vert; -}; - -struct SELECTID_Context { - struct GPUFrameBuffer *framebuffer_select_id; - struct GPUTexture *texture_u32; - - struct BaseOffset *index_offsets; - uint objects_len; - uint last_object_drawn; - /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ - uint last_index_drawn; - - short select_mode; -}; - -/* select_engine.c */ -struct SELECTID_Context *select_context_get(void); - /* select_draw_utils.c */ void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *r_select_ctx); short select_id_get_object_select_mode(Scene *scene, Object *ob); |