[Bf-blender-cvs] [d7628d4b7fc] master: Mesh Select: use select context instead of static structs

mano-wii noreply at git.blender.org
Fri May 17 07:04:12 CEST 2019


Commit: d7628d4b7fcd72af48e7b28891e63c9abd88e0a1
Author: mano-wii
Date:   Fri May 17 14:59:30 2019 +1000
Branches: master
https://developer.blender.org/rBd7628d4b7fcd72af48e7b28891e63c9abd88e0a1

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.

===================================================================

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

===================================================================

diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 29bf8115a39..4e6bf7d4df5 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -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);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 63fff243cd8..f74614cca71 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -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);
     }
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_i

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list