Mesh Select: use select context instead of static structs

This patch does not bring any functional change, but it does expose
some utilities that can be very useful to correct occlusion and
performance problems of Circle Select and similar.
Creating a selection context still makes it easier to track issues.
This commit is contained in:
Germano Cavalcante 2019-05-17 14:59:30 +10:00 committed by Campbell Barton
parent 1f22a20d5f
commit d7628d4b7f
3 changed files with 99 additions and 48 deletions

View File

@ -142,6 +142,16 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
void ED_mesh_undosys_type(struct UndoType *ut);
/* editmesh_select.c */
struct EDBMSelectID_Context;
struct EDBMSelectID_Context *EDBM_select_id_context_create(struct ViewContext *vc,
struct Base **bases,
const uint bases_len,
short select_mode);
void EDBM_select_id_context_destroy(struct EDBMSelectID_Context *sel_id_ctx);
struct BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx,
const uint sel_id,
uint *r_base_index);
void EDBM_select_mirrored(
struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail);
void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag);

View File

@ -204,18 +204,12 @@ struct EDBMBaseOffset {
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);
}
struct EDBMSelectID_Context {
struct EDBMBaseOffset *base_array_index_offsets;
/** Borrow from caller (not freed). */
struct Base **bases;
uint bases_len;
};
static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt)
{
@ -233,19 +227,19 @@ static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt)
return false;
}
static void edbm_select_pick_draw_bases(ViewContext *vc,
Base **bases,
uint bases_len,
static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx,
ViewContext *vc,
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];
for (uint base_index = 0; base_index < sel_id_ctx->bases_len; base_index++) {
Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph,
sel_id_ctx->bases[base_index]->object);
struct EDBMBaseOffset *base_ofs = &sel_id_ctx->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,
@ -264,20 +258,74 @@ static void edbm_select_pick_draw_bases(ViewContext *vc,
DRW_framebuffer_select_id_release(vc->ar);
}
static uint edbm_select_pick_base_index_find(uint bases_len, uint elem_index, uint *r_offset)
BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx,
const uint sel_id,
uint *r_base_index)
{
*r_offset = 0;
char elem_type;
uint elem_id;
uint prev_offs = 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) {
for (; base_index < sel_id_ctx->bases_len; base_index++) {
struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
if (base_ofs->face > sel_id) {
elem_id = sel_id - prev_offs;
elem_type = BM_FACE;
break;
}
*r_offset = base_ofs->vert;
if (base_ofs->edge > sel_id) {
elem_id = sel_id - base_ofs->face;
elem_type = BM_EDGE;
break;
}
if (base_ofs->vert > sel_id) {
elem_id = sel_id - base_ofs->edge;
elem_type = BM_VERT;
break;
}
prev_offs = base_ofs->vert;
}
*r_offset += 1;
return base_index;
if (r_base_index) {
*r_base_index = base_index;
}
Object *obedit = sel_id_ctx->bases[base_index]->object;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
switch (elem_type) {
case BM_FACE:
return (BMElem *)BM_face_at_index_find_or_table(em->bm, elem_id);
case BM_EDGE:
return (BMElem *)BM_edge_at_index_find_or_table(em->bm, elem_id);
case BM_VERT:
return (BMElem *)BM_vert_at_index_find_or_table(em->bm, elem_id);
default:
BLI_assert(0);
return NULL;
}
}
struct EDBMSelectID_Context *EDBM_select_id_context_create(ViewContext *vc,
Base **bases,
uint bases_len,
short select_mode)
{
struct EDBMSelectID_Context *sel_id_ctx = MEM_mallocN(sizeof(*sel_id_ctx), __func__);
sel_id_ctx->base_array_index_offsets = MEM_mallocN(sizeof(struct EDBMBaseOffset) * bases_len,
__func__);
sel_id_ctx->bases = bases;
sel_id_ctx->bases_len = bases_len;
edbm_select_pick_draw_bases(sel_id_ctx, vc, select_mode);
return sel_id_ctx;
}
void EDBM_select_id_context_destroy(struct EDBMSelectID_Context *sel_id_ctx)
{
MEM_freeN(sel_id_ctx->base_array_index_offsets);
MEM_freeN(sel_id_ctx);
}
/* set in view3d_draw_legacy.c ... for colorindices */
@ -567,28 +615,26 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
uint index, offset;
uint index;
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);
edbm_select_pick_cache_alloc(bases_len);
edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode);
struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
vc, bases, bases_len, select_mode);
index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px);
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);
eve = (BMVert *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index);
}
else {
eve = NULL;
}
edbm_select_pick_cache_free();
EDBM_select_id_context_destroy(sel_id_ctx);
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
@ -794,28 +840,26 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
uint index, offset;
uint index;
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);
edbm_select_pick_cache_alloc(bases_len);
edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode);
struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
vc, bases, bases_len, select_mode);
index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px);
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);
eed = (BMEdge *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index);
}
else {
eed = NULL;
}
edbm_select_pick_cache_free();
EDBM_select_id_context_destroy(sel_id_ctx);
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
@ -1006,27 +1050,25 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
float dist_test = 0.0f;
uint index, offset;
uint index;
BMFace *efa;
{
FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
edbm_select_pick_cache_alloc(bases_len);
edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode);
struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
vc, bases, bases_len, select_mode);
index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
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);
efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index);
}
else {
efa = NULL;
}
edbm_select_pick_cache_free();
EDBM_select_id_context_destroy(sel_id_ctx);
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}

View File

@ -548,7 +548,6 @@ PointerRNA rna_pointer_inherit_refine(struct PointerRNA *ptr, struct StructRNA *
int rna_parameter_size(struct PropertyRNA *parm);
/* XXX, these should not need to be defined here~! */
struct MTex *rna_mtex_texture_slots_add(struct ID *self,
struct bContext *C,