Mesh Select: use select context instead of static structs
authormano-wii <germano.costa@ig.com.br>
Fri, 17 May 2019 04:59:30 +0000 (14:59 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 17 May 2019 05:02:19 +0000 (15:02 +1000)
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.

source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/editmesh_select.c
source/blender/makesrna/intern/rna_internal.h

index 29bf811..4e6bf7d 100644 (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);
index 63fff24..f74614c 100644 (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;
+    }
+    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;
     }
-    *r_offset = base_ofs->vert;
+    prev_offs = base_ofs->vert;
+  }
+
+  if (r_base_index) {
+    *r_base_index = base_index;
   }
 
-  *r_offset += 1;
-  return 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);
     }
index 6402416..938db92 100644 (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,