diff options
author | mano-wii <germano.costa@ig.com.br> | 2019-05-16 02:26:33 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-05-16 02:36:15 +0300 |
commit | 8a6414ed46f669ede106b3ffbe48f74b47718e11 (patch) | |
tree | 2aec66bbcc3d42acd2f09ea4ef215c3993300f7d /source | |
parent | 989d8543853c422fb555411bfd8fffc46d9a070b (diff) |
Fix T54686: objects don't occlude each other for edit-mesh select
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/DRW_engine.h | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 206 | ||||
-rw-r--r-- | source/blender/editors/include/ED_mesh.h | 16 | ||||
-rw-r--r-- | source/blender/editors/mesh/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/mesh/editface.c | 6 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_loopcut.c | 69 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 359 | ||||
-rw-r--r-- | source/blender/editors/mesh/meshtools.c | 8 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_utils.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 237 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw_legacy.c | 16 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c | 17 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_intern.h | 7 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.c | 9 |
14 files changed, 557 insertions, 405 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index cb75a965ef7..5919e100ddd 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -38,6 +38,7 @@ struct IDProperty; struct Main; struct Material; struct Object; +struct RegionView3D; struct RenderEngine; struct RenderEngineType; struct Scene; @@ -135,6 +136,15 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, void DRW_draw_depth_object(struct ARegion *ar, struct GPUViewport *viewport, struct Object *object); +void DRW_draw_select_id_object(struct Scene *scene, + struct RegionView3D *rv3d, + struct Object *ob, + short select_mode, + bool draw_facedot, + uint initial_offset, + uint *r_vert_offset, + uint *r_edge_offset, + uint *r_face_offset); void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear); void DRW_framebuffer_select_id_release(struct ARegion *ar); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 355046ae277..ca283e3a83a 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -34,6 +34,7 @@ #include "BKE_anim.h" #include "BKE_colortools.h" #include "BKE_curve.h" +#include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_lattice.h" @@ -2615,6 +2616,12 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, DRW_opengl_context_disable(); } +/** See #DRW_shgroup_world_clip_planes_from_rv3d. */ +static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) +{ + GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); +} + /** * Clears the Depth Buffer and draws only the specified object. */ @@ -2658,7 +2665,7 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) GPU_SHADER_CFG_DEFAULT; GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); if (world_clip_planes != NULL) { - GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); } GPU_batch_draw(batch); @@ -2678,6 +2685,203 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) DRW_opengl_context_disable(); } +static void draw_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +{ + GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); +} + +static void draw_mesh_edges(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +{ + GPU_line_width(1.0f); + glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); + + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + + glProvokingVertex(GL_LAST_VERTEX_CONVENTION); +} + +/* two options, facecolors or black */ +static void draw_mesh_face(GPUBatch *batch, + int offset, + const bool use_select, + const float world_clip_planes[6][4]) +{ + if (use_select) { + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + } + else { + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "id", 0); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + } +} + +static void draw_mesh_face_dot(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +{ + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); +} + +void DRW_draw_select_id_object(Scene *scene, + RegionView3D *rv3d, + Object *ob, + short select_mode, + bool draw_facedot, + uint initial_offset, + uint *r_vert_offset, + uint *r_edge_offset, + uint *r_face_offset) +{ + ToolSettings *ts = scene->toolsettings; + if (select_mode == -1) { + select_mode = ts->selectmode; + } + + GPU_matrix_mul(ob->obmat); + GPU_depth_test(true); + + const float(*world_clip_planes)[4] = NULL; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_local(rv3d, ob->obmat); + world_clip_planes = rv3d->clip_local; + } + + initial_offset += 1; + + switch (ob->type) { + case OB_MESH: + if (ob->mode & OB_MODE_EDIT) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; + + DRW_mesh_batch_cache_validate(me); + + BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); + + GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + if (select_mode & SCE_SELECT_EDGE) { + geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + } + if (select_mode & SCE_SELECT_VERTEX) { + geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + } + if (draw_facedot) { + geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); + } + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + + draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes); + + if (use_faceselect && draw_facedot) { + draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes); + } + + if (select_mode & SCE_SELECT_FACE) { + *r_face_offset = initial_offset + em->bm->totface; + } + else { + *r_face_offset = initial_offset; + } + + ED_view3d_polygon_offset(rv3d, 1.0); + + /* Unlike faces, only draw edges if edge select mode. */ + if (select_mode & SCE_SELECT_EDGE) { + draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes); + *r_edge_offset = *r_face_offset + em->bm->totedge; + } + else { + /* Note that `r_vert_offset` is calculated from `r_edge_offset`. + * Otherwise the first vertex is never selected, see: T53512. */ + *r_edge_offset = *r_face_offset; + } + + ED_view3d_polygon_offset(rv3d, 1.1); + + /* Unlike faces, only verts if vert select mode. */ + if (select_mode & SCE_SELECT_VERTEX) { + draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes); + *r_vert_offset = *r_edge_offset + em->bm->totvert; + } + else { + *r_vert_offset = *r_edge_offset; + } + + ED_view3d_polygon_offset(rv3d, 0.0); + } + else { + Mesh *me_orig = DEG_get_original_object(ob)->data; + Mesh *me_eval = ob->data; + + DRW_mesh_batch_cache_validate(me_eval); + GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval); + if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) && + /* Currently vertex select supports weight paint and vertex paint. */ + ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { + + GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval); + DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true); + + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + draw_mesh_face(geom_faces, 0, false, world_clip_planes); + draw_mesh_verts(geom_verts, 1, world_clip_planes); + + *r_vert_offset = me_eval->totvert + 1; + } + else { + const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); + DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide); + + draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes); + + *r_face_offset = initial_offset + me_eval->totface; + } + } + break; + case OB_CURVE: + case OB_SURF: + break; + } + + GPU_matrix_set(rv3d->viewmat); +} + /* Set an opengl context to be used with shaders that draw on U32 colors. */ void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear) { diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index ce8521a1f6a..c6d25e6f988 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -163,7 +163,10 @@ bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist, const bool use_select_bias, - bool use_cycle); + bool use_cycle, + struct Base **bases, + uint bases_len, + uint *r_base_index); struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist); struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, @@ -171,7 +174,10 @@ struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - struct BMEdge **r_eed_zbuf); + struct BMEdge **r_eed_zbuf, + struct Base **bases, + uint bases_len, + uint *r_base_index); struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist); struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, @@ -179,7 +185,10 @@ struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - struct BMFace **r_efa_zbuf); + struct BMFace **r_efa_zbuf, + struct Base **bases, + uint bases_len, + uint *r_base_index); struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist); bool EDBM_unified_findnearest(struct ViewContext *vc, @@ -230,6 +239,7 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len); bool EDBM_mesh_deselect_all_multi(struct bContext *C); +/* Only use for modes that don't support multi-edit-modes (painting). */ extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; /* editmesh_preselect_edgering.c */ diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 57bf67e825e..9a779db4812 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blentranslation ../../bmesh ../../depsgraph + ../../draw ../../gpu ../../imbuf ../../makesdna diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 990250792a1..fdbcc3449b2 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -461,13 +461,13 @@ bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) } else { MPoly *mpoly; - uint *rt; + uint *rt, *buf, buf_len; int a, index; char *selar = MEM_callocN(me->totpoly + 1, "selar"); - uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); + ED_view3d_select_id_validate(vc); + buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); rt = buf; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 528235e693a..59355890428 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -79,11 +79,11 @@ typedef struct RingSelOpData { Depsgraph *depsgraph; - Object **objects; - uint objects_len; + Base **bases; + uint bases_len; /* These values switch objects based on the object under the cursor. */ - uint ob_index; + uint base_index; Object *ob; BMEditMesh *em; BMEdge *eed; @@ -111,8 +111,8 @@ static void edgering_select(RingSelOpData *lcd) } if (!lcd->extend) { - for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) { - Object *ob_iter = lcd->objects[ob_index]; + for (uint base_index = 0; base_index < lcd->bases_len; base_index++) { + Object *ob_iter = lcd->bases[base_index]->object; BMEditMesh *em = BKE_editmesh_from_object(ob_iter); EDBM_flag_disable_all(em, BM_ELEM_SELECT); DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT); @@ -252,7 +252,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) EDBM_preselect_edgering_destroy(lcd->presel_edgering); - MEM_freeN(lcd->objects); + MEM_freeN(lcd->bases); ED_region_tag_redraw(lcd->ar); @@ -307,21 +307,21 @@ static void ringcut_cancel(bContext *C, wmOperator *op) } static void loopcut_update_edge(RingSelOpData *lcd, - uint ob_index, + uint base_index, BMEdge *e, const int previewlines) { if (e != lcd->eed) { lcd->eed = e; lcd->ob = lcd->vc.obedit; - lcd->ob_index = ob_index; + lcd->base_index = base_index; lcd->em = lcd->vc.em; ringsel_find_edge(lcd, previewlines); } else if (e == NULL) { lcd->ob = NULL; lcd->em = NULL; - lcd->ob_index = UINT_MAX; + lcd->base_index = UINT_MAX; } } @@ -331,27 +331,26 @@ static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines) Object *ob; BMEdge *eed; float dist; - int ob_index; + int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; - for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) { - Object *ob_iter = lcd->objects[ob_index]; - ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter); - BMEdge *eed_test = EDBM_edge_find_nearest_ex(&lcd->vc, &best.dist, NULL, false, false, NULL); - if (eed_test) { - best.ob = ob_iter; - best.eed = eed_test; - best.ob_index = ob_index; - } + uint base_index; + BMEdge *eed_test = EDBM_edge_find_nearest_ex( + &lcd->vc, &best.dist, NULL, false, false, NULL, lcd->bases, lcd->bases_len, &base_index); + + if (eed_test) { + best.ob = lcd->bases[base_index]->object; + best.eed = eed_test; + best.base_index = base_index; } if (best.eed) { ED_view3d_viewcontext_init_object(&lcd->vc, best.ob); } - loopcut_update_edge(lcd, best.ob_index, best.eed, previewlines); + loopcut_update_edge(lcd, best.base_index, best.eed, previewlines); } /* called by both init() and exec() */ @@ -361,22 +360,22 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) /* Use for redo - intentionally wrap int to uint. */ const struct { - uint ob_index; + uint base_index; uint e_index; } exec_data = { - .ob_index = (uint)RNA_int_get(op->ptr, "object_index"), + .base_index = (uint)RNA_int_get(op->ptr, "object_index"), .e_index = (uint)RNA_int_get(op->ptr, "edge_index"), }; ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( - view_layer, CTX_wm_view3d(C), &objects_len); + uint bases_len; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + view_layer, CTX_wm_view3d(C), &bases_len); if (is_interactive) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob_iter = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *ob_iter = bases[base_index]->object; if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) { BKE_report( op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display"); @@ -390,12 +389,12 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) /* for re-execution, check edge index is in range before we setup ringsel */ bool ok = true; if (is_interactive == false) { - if (exec_data.ob_index >= objects_len) { + if (exec_data.base_index >= bases_len) { return OPERATOR_CANCELLED; ok = false; } else { - Object *ob_iter = objects[exec_data.ob_index]; + Object *ob_iter = bases[exec_data.base_index]->object; BMEditMesh *em = BKE_editmesh_from_object(ob_iter); if (exec_data.e_index >= em->bm->totedge) { ok = false; @@ -404,7 +403,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) } if (!ok || !ringsel_init(C, op, true)) { - MEM_freeN(objects); + MEM_freeN(bases); return OPERATOR_CANCELLED; } @@ -416,8 +415,8 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) RingSelOpData *lcd = op->customdata; - lcd->objects = objects; - lcd->objects_len = objects_len; + lcd->bases = bases; + lcd->bases_len = bases_len; if (is_interactive) { copy_v2_v2_int(lcd->vc.mval, event->mval); @@ -425,13 +424,13 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) } else { - Object *ob_iter = objects[exec_data.ob_index]; + Object *ob_iter = bases[exec_data.base_index]->object; ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter); BMEdge *e; BM_mesh_elem_table_ensure(lcd->vc.em->bm, BM_EDGE); e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index); - loopcut_update_edge(lcd, exec_data.ob_index, e, 0); + loopcut_update_edge(lcd, exec_data.base_index, e, 0); } #ifdef USE_LOOPSLIDE_HACK @@ -503,7 +502,7 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op) if (lcd->eed) { /* set for redo */ BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE); - RNA_int_set(op->ptr, "object_index", lcd->ob_index); + RNA_int_set(op->ptr, "object_index", lcd->base_index); RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed)); /* execute */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 9df03a81762..28551280ff4 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -67,6 +67,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "DRW_engine.h" + #include "mesh_intern.h" /* own include */ /* use bmesh operator flags for a few operators */ @@ -196,7 +198,87 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) /** \name Back-Buffer OpenGL Selection * \{ */ -/* set in drawobject.c ... for colorindices */ +struct EDBMBaseOffset { + uint face; + uint edge; + uint vert; +}; + +static struct EDBMBaseOffset *base_array_index_offsets = NULL; + +static void edbm_select_pick_cache_alloc(uint bases_len) +{ + BLI_assert(base_array_index_offsets == NULL); + base_array_index_offsets = MEM_mallocN(sizeof(struct EDBMBaseOffset) * bases_len, __func__); +} + +static void edbm_select_pick_cache_free(void) +{ + MEM_SAFE_FREE(base_array_index_offsets); +} + +static bool check_ob_drawface_dot(short select_mode, View3D *vd, char dt) +{ + if ((select_mode & SCE_SELECT_FACE) == 0) { + return false; + } + + /* if its drawing textures with zbuf sel, then don't draw dots */ + if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) { + return false; + } + + return true; +} + +static void edbm_select_pick_draw_bases(ViewContext *vc, + Base **bases, + uint bases_len, + short select_mode) +{ + Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); + DRW_framebuffer_select_id_setup(vc->ar, true); + + uint offset = 0; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, bases[base_index]->object); + struct EDBMBaseOffset *base_ofs = &base_array_index_offsets[base_index]; + + bool draw_facedot = check_ob_drawface_dot(select_mode, vc->v3d, ob_eval->dt); + + DRW_draw_select_id_object(scene_eval, + vc->rv3d, + ob_eval, + select_mode, + draw_facedot, + offset, + &base_ofs->vert, + &base_ofs->edge, + &base_ofs->face); + + offset = base_ofs->vert; + } + + DRW_framebuffer_select_id_release(vc->ar); +} + +static uint edbm_select_pick_base_index_find(uint bases_len, uint elem_index, uint *r_offset) +{ + *r_offset = 0; + uint base_index = 0; + for (; base_index < bases_len; base_index++) { + struct EDBMBaseOffset *base_ofs = &base_array_index_offsets[base_index]; + if (base_ofs->vert > elem_index) { + break; + } + *r_offset = base_ofs->vert; + } + + *r_offset += 1; + return base_index; +} + +/* set in view3d_draw_legacy.c ... for colorindices */ unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* facilities for box select and circle select */ @@ -217,6 +299,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma return false; } + ED_view3d_select_id_validate(vc); buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; @@ -303,6 +386,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, return false; } + ED_view3d_select_id_validate(vc); buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; @@ -354,6 +438,8 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; + + ED_view3d_select_id_validate(vc); buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; @@ -470,29 +556,47 @@ static void findnearestvert__doClosest(void *userData, BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, float *r_dist, const bool use_select_bias, - bool use_cycle) + bool use_cycle, + Base **bases, + uint bases_len, + uint *r_base_index) { - BMesh *bm = vc->em->bm; + uint base_index = 0; if (!XRAY_FLAG_ENABLED(vc->v3d)) { uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - unsigned int index; + uint index, offset; BMVert *eve; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX) ; - ED_view3d_select_id_validate_with_select_mode(vc, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px); - eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; + edbm_select_pick_cache_alloc(bases_len); + edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); + + index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + + if (index) { + base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); + ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); + eve = BM_vert_at_index_find_or_table(vc->em->bm, index - offset); + } + else { + eve = NULL; + } + + edbm_select_pick_cache_free(); FAKE_SELECT_MODE_END(vc, fake_select_mode); } if (eve) { if (dist_px < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } *r_dist = dist_px; return eve; } @@ -509,7 +613,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, if ((use_cycle == false) || (prev_select_elem && - (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) { + (prev_select_elem != BM_vert_at_index_find_or_table(vc->em->bm, prev_select_index)))) { prev_select_index = 0; prev_select_elem = NULL; } @@ -518,14 +622,26 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; 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); + for (; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + ED_view3d_viewcontext_init_object(vc, base_iter->object); + data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = + *r_dist; - hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; - *r_dist = hit->dist; + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); + + hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; + + if (hit->dist < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } + *r_dist = hit->dist; + } + } prev_select_elem = hit->vert; prev_select_index = hit->index; @@ -536,7 +652,8 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + return EDBM_vert_find_nearest_ex(vc, r_dist, false, false, &base, 1, NULL); } /* find the distance to the edge we already have */ @@ -659,23 +776,38 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - BMEdge **r_eed_zbuf) + BMEdge **r_eed_zbuf, + Base **bases, + uint bases_len, + uint *r_base_index) { - BMesh *bm = vc->em->bm; + uint base_index = 0; if (!XRAY_FLAG_ENABLED(vc->v3d)) { uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - unsigned int index; + uint index, offset; BMEdge *eed; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_EDGE) ; - ED_view3d_select_id_validate_with_select_mode(vc, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px); - eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; + edbm_select_pick_cache_alloc(bases_len); + edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); + + index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + + if (index) { + base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); + ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); + eed = BM_edge_at_index_find_or_table(vc->em->bm, index - offset); + } + else { + eed = NULL; + } + + edbm_select_pick_cache_free(); FAKE_SELECT_MODE_END(vc, fake_select_mode); } @@ -704,6 +836,9 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, if (eed) { if (dist_px < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } *r_dist = dist_px; return eed; } @@ -721,7 +856,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, if ((use_cycle == false) || (prev_select_elem && - (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) { + (prev_select_elem != BM_edge_at_index_find_or_table(vc->em->bm, prev_select_index)))) { prev_select_index = 0; prev_select_elem = NULL; } @@ -731,14 +866,27 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; 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_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + for (; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + ED_view3d_viewcontext_init_object(vc, base_iter->object); + data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = + *r_dist; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + + hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; + + if (hit->dist < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } + *r_dist = hit->dist; + } + } - hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; - *r_dist = hit->dist; if (r_dist_center) { *r_dist_center = hit->dist_center; } @@ -752,7 +900,8 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL); } /* find the distance to the face we already have */ @@ -832,22 +981,37 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - BMFace **r_efa_zbuf) + BMFace **r_efa_zbuf, + Base **bases, + uint bases_len, + uint *r_base_index) { - BMesh *bm = vc->em->bm; + uint base_index = 0; if (!XRAY_FLAG_ENABLED(vc->v3d)) { float dist_test = 0.0f; - unsigned int index; + uint index, offset; BMFace *efa; { FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_FACE) ; - ED_view3d_select_id_validate_with_select_mode(vc, select_mode); + + edbm_select_pick_cache_alloc(bases_len); + edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); - efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; + + if (index) { + base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); + ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); + efa = BM_face_at_index_find_or_table(vc->em->bm, index - offset); + } + else { + efa = NULL; + } + + edbm_select_pick_cache_free(); FAKE_SELECT_MODE_END(vc, fake_select_mode); } @@ -876,6 +1040,9 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, if (efa) { if (dist_test < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } *r_dist = dist_test; return efa; } @@ -892,7 +1059,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, if ((use_cycle == false) || (prev_select_elem && - (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) { + (prev_select_elem != BM_face_at_index_find_or_table(vc->em->bm, prev_select_index)))) { prev_select_index = 0; prev_select_elem = NULL; } @@ -901,14 +1068,28 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; 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_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); + for (; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + ED_view3d_viewcontext_init_object(vc, base_iter->object); + + data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = + *r_dist; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); + + hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; + + if (hit->dist < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } + *r_dist = hit->dist; + } + } - hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; - *r_dist = hit->dist; if (r_dist_center) { *r_dist_center = hit->dist; } @@ -922,7 +1103,8 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL); } #undef FIND_NEAR_SELECT_BIAS @@ -965,75 +1147,64 @@ static bool unified_findnearest(ViewContext *vc, } f, f_zbuf; } hit = {{NULL}}; - /* TODO(campbell): perform selection as one pass - * instead of many smaller passes (which doesn't work for zbuf occlusion). */ - /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ + short selectmode = vc->scene->toolsettings->selectmode; - if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { + if ((dist > 0.0f) && (selectmode & SCE_SELECT_FACE)) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base_iter = bases[base_index]; - Object *obedit = base_iter->object; - ED_view3d_viewcontext_init_object(vc, obedit); - BLI_assert(vc->em->selectmode == em->selectmode); - BMFace *efa_zbuf = NULL; - BMFace *efa_test = EDBM_face_find_nearest_ex( - vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); - if (efa_test && dist_center_p) { - dist = min_ff(dist_margin, dist_center); - } - if (efa_test) { - hit.f.base_index = base_index; - hit.f.ele = efa_test; - } - if (efa_zbuf) { - hit.f_zbuf.base_index = base_index; - hit.f_zbuf.ele = efa_zbuf; - } - } /* bases */ + uint base_index = 0; + BMFace *efa_zbuf = NULL; + BMFace *efa_test = EDBM_face_find_nearest_ex( + vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index); + + if (efa_test && dist_center_p) { + dist = min_ff(dist_margin, dist_center); + } + if (efa_test) { + hit.f.base_index = base_index; + hit.f.ele = efa_test; + } + if (efa_zbuf) { + hit.f_zbuf.base_index = base_index; + hit.f_zbuf.ele = efa_zbuf; + } } - if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { + if ((dist > 0.0f) && (selectmode & SCE_SELECT_EDGE)) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base_iter = bases[base_index]; - Object *obedit = base_iter->object; - ED_view3d_viewcontext_init_object(vc, obedit); - BMEdge *eed_zbuf = NULL; - BMEdge *eed_test = EDBM_edge_find_nearest_ex( - vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); - if (eed_test && dist_center_p) { - dist = min_ff(dist_margin, dist_center); - } - if (eed_test) { - hit.e.base_index = base_index; - hit.e.ele = eed_test; - } - if (eed_zbuf) { - hit.e_zbuf.base_index = base_index; - hit.e_zbuf.ele = eed_zbuf; - } - } /* bases */ + uint base_index = 0; + BMEdge *eed_zbuf = NULL; + BMEdge *eed_test = EDBM_edge_find_nearest_ex( + vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf, bases, bases_len, &base_index); + + if (eed_test && dist_center_p) { + dist = min_ff(dist_margin, dist_center); + } + if (eed_test) { + hit.e.base_index = base_index; + hit.e.ele = eed_test; + } + if (eed_zbuf) { + hit.e_zbuf.base_index = base_index; + hit.e_zbuf.ele = eed_zbuf; + } } - if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base_iter = bases[base_index]; - Object *obedit = base_iter->object; - ED_view3d_viewcontext_init_object(vc, obedit); - BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); - if (eve_test) { - hit.v.base_index = base_index; - hit.v.ele = eve_test; - } - } /* bases */ + if ((dist > 0.0f) && (selectmode & SCE_SELECT_VERTEX)) { + uint base_index = 0; + BMVert *eve_test = EDBM_vert_find_nearest_ex( + vc, &dist, true, use_cycle, bases, bases_len, &base_index); + + if (eve_test) { + hit.v.base_index = base_index; + hit.v.ele = eve_test; + } } /* return only one of 3 pointers, for frontbuffer redraws */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index c32fef42d27..e29cfa6b6e0 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1109,13 +1109,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, } ED_view3d_viewcontext_init(C, &vc); + ED_view3d_select_id_validate(&vc); 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 */ - - ED_view3d_select_id_validate(&vc); - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px); } else { @@ -1291,14 +1289,12 @@ bool ED_mesh_pick_vert( } ED_view3d_viewcontext_init(C, &vc); + ED_view3d_select_id_validate(&vc); if (use_zbuf) { 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 */ - - ED_view3d_select_id_validate(&vc); - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px); } else { diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 6d003820723..84b4a130183 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -389,6 +389,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]); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index fbec99c5f28..cc76c151a29 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -41,7 +41,6 @@ #include "GPU_batch.h" #include "GPU_matrix.h" #include "GPU_state.h" -#include "GPU_framebuffer.h" #include "ED_mesh.h" @@ -51,8 +50,6 @@ #include "view3d_intern.h" /* bad level include */ -#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ - int view3d_effective_drawtype(const struct View3D *v3d) { if (v3d->shading.type == OB_RENDER) { @@ -61,24 +58,6 @@ int view3d_effective_drawtype(const struct View3D *v3d) return v3d->shading.type; } -static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) -{ - if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) { - return false; - } - - if (G.f & G_FLAG_BACKBUFSEL) { - return false; - } - - /* if its drawing textures with zbuf sel, then don't draw dots */ - if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) { - return false; - } - - return true; -} - /* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */ /* 32 values of sin function (still same result!) */ #define CIRCLE_RESOL 32 @@ -138,222 +117,6 @@ bool view3d_camera_border_hack_test = false; /* ***************** BACKBUF SEL (BBS) ********* */ -/** See #DRW_shgroup_world_clip_planes_from_rv3d, same function for draw manager. */ -static void bbs_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) -{ - GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); -} - -static void bbs_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) -{ - GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -static void bbs_mesh_wire(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) -{ - GPU_line_width(1.0f); - glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - - glProvokingVertex(GL_LAST_VERTEX_CONVENTION); -} - -/* two options, facecolors or black */ -static void bbs_mesh_face(GPUBatch *batch, - const bool use_select, - const float world_clip_planes[6][4]) -{ - if (use_select) { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", 1); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } - else { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "id", 0); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } -} - -static void bbs_mesh_face_dot(GPUBatch *batch, const float world_clip_planes[6][4]) -{ - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", 1); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph), - Scene *UNUSED(scene), - Object *ob, - const float world_clip_planes[6][4]) -{ - Mesh *me = ob->data; - - DRW_mesh_batch_cache_validate(me); - - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - /* Only draw faces to mask out verts, we don't want their selection ID's. */ - bbs_mesh_face(geom_faces, false, world_clip_planes); - bbs_mesh_verts(geom_verts, 1, world_clip_planes); - - bm_vertoffs = me->totvert + 1; -} - -static void bbs_mesh_solid_faces(Scene *UNUSED(scene), - Object *ob, - const float world_clip_planes[6][4]) -{ - Mesh *me = ob->data; - Mesh *me_orig = DEG_get_original_object(ob)->data; - - DRW_mesh_batch_cache_validate(me); - - const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide); - - bbs_mesh_face(geom_faces, true, world_clip_planes); -} - -void draw_object_select_id(Depsgraph *depsgraph, - Scene *scene, - View3D *v3d, - RegionView3D *rv3d, - Object *ob, - short select_mode) -{ - ToolSettings *ts = scene->toolsettings; - if (select_mode == -1) { - select_mode = ts->selectmode; - } - - GPU_matrix_mul(ob->obmat); - GPU_depth_test(true); - - const float(*world_clip_planes)[4] = NULL; - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_local(rv3d, ob->obmat); - world_clip_planes = rv3d->clip_local; - } - - switch (ob->type) { - case OB_MESH: - if (ob->mode & OB_MODE_EDIT) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt); - const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; - - DRW_mesh_batch_cache_validate(me); - - BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); - - GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; - geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - if (select_mode & SCE_SELECT_EDGE) { - geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); - } - if (select_mode & SCE_SELECT_VERTEX) { - geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - } - if (draw_facedot) { - geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); - } - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes); - - if (use_faceselect && draw_facedot) { - bbs_mesh_face_dot(geom_facedots, world_clip_planes); - } - - if (select_mode & SCE_SELECT_FACE) { - bm_solidoffs = 1 + em->bm->totface; - } - else { - bm_solidoffs = 1; - } - - ED_view3d_polygon_offset(rv3d, 1.0); - - /* we draw edges if edge select mode */ - if (select_mode & SCE_SELECT_EDGE) { - bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes); - bm_wireoffs = bm_solidoffs + em->bm->totedge; - } - else { - /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */ - bm_wireoffs = bm_solidoffs; - } - - ED_view3d_polygon_offset(rv3d, 1.1); - - /* we draw verts if vert select mode. */ - if (select_mode & SCE_SELECT_VERTEX) { - bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes); - bm_vertoffs = bm_wireoffs + em->bm->totvert; - } - else { - bm_vertoffs = bm_wireoffs; - } - - ED_view3d_polygon_offset(rv3d, 0.0); - } - else { - Mesh *me = DEG_get_original_object(ob)->data; - if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && - /* currently vertex select supports weight paint and vertex paint*/ - ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { - bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes); - } - else { - bbs_mesh_solid_faces(scene, ob, world_clip_planes); - } - } - break; - case OB_CURVE: - case OB_SURF: - break; - } - - GPU_matrix_set(rv3d->viewmat); -} - void ED_draw_object_facemap(Depsgraph *depsgraph, Object *ob, const float col[4], diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index b0cee18f8e3..e0dbe1f6543 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -77,6 +77,7 @@ #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_gpencil.h" +#include "ED_mesh.h" #include "ED_screen.h" #include "ED_space_api.h" #include "ED_screen_types.h" @@ -208,7 +209,16 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { DRW_framebuffer_select_id_setup(ar, true); - draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); + DRW_draw_select_id_object(scene_eval, + rv3d, + obact_eval, + select_mode, + false, + 0, + &bm_vertoffs, + &bm_wireoffs, + &bm_solidoffs); + DRW_framebuffer_select_id_release(ar); } @@ -271,10 +281,8 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc) } } -uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len) +uint *ED_view3d_select_id_read_rect(ViewContext *UNUSED(vc), const rcti *clip, uint *r_buf_len) { - ED_view3d_select_id_validate(vc); - uint width = BLI_rcti_size_x(clip); uint height = BLI_rcti_size_y(clip); uint buf_len = width * height; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index 6f35c0aa748..9cbf179ab49 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -304,15 +304,14 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); - for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) { - Object *ob_iter = gz_ring->bases[base_index]->object; - ED_view3d_viewcontext_init_object(&vc, ob_iter); - BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL); - if (eed_test) { - best.ob = ob_iter; - best.eed = eed_test; - best.base_index = base_index; - } + uint base_index; + BMEdge *eed_test = EDBM_edge_find_nearest_ex( + &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index); + + if (eed_test) { + best.ob = gz_ring->bases[base_index]->object; + best.eed = eed_test; + best.base_index = base_index; } BMesh *bm = NULL; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 9075909a6fe..e499672acc1 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -127,13 +127,6 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot); void VIEW3D_OT_walk(struct wmOperatorType *ot); /* drawobject.c */ -void draw_object_select_id(struct Depsgraph *depsgraph, - Scene *scene, - View3D *v3d, - RegionView3D *rv3d, - struct Object *ob, - short select_mode); - int view3d_effective_drawtype(const struct View3D *v3d); /* view3d_draw.c */ diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index c916e470322..419ec87eec8 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -135,9 +135,6 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact) if (vc->obedit) { BLI_assert(BKE_object_is_in_editmode(obact)); vc->obedit = obact; - /* previous selections are now invalid. */ - vc->v3d->flag |= V3D_INVALID_BACKBUF; - if (vc->em) { vc->em = BKE_editmesh_from_object(vc->obedit); } @@ -2359,14 +2356,14 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe } else if (use_zbuf) { MVert *mvert; - unsigned int *rt; + uint *rt, *buf, buf_len; int a, index; char *selar; selar = MEM_callocN(me->totvert + 1, "selar"); - uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); + ED_view3d_select_id_validate(vc); + buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); rt = buf; |