Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormano-wii <germano.costa@ig.com.br>2019-05-16 02:26:33 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-05-16 02:36:15 +0300
commit8a6414ed46f669ede106b3ffbe48f74b47718e11 (patch)
tree2aec66bbcc3d42acd2f09ea4ef215c3993300f7d /source/blender/editors/mesh
parent989d8543853c422fb555411bfd8fffc46d9a070b (diff)
Fix T54686: objects don't occlude each other for edit-mesh select
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editface.c6
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c69
-rw-r--r--source/blender/editors/mesh/editmesh_select.c359
-rw-r--r--source/blender/editors/mesh/meshtools.c8
5 files changed, 305 insertions, 138 deletions
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 {