[Bf-blender-cvs] [411c9b9eb22] soc-2021-knife-tools: Fix: Knife Project crash in multi-object edit mode

Cian Jinks noreply at git.blender.org
Mon Jul 26 12:10:47 CEST 2021


Commit: 411c9b9eb22b40d09c614783070a51fc6301b99c
Author: Cian Jinks
Date:   Mon Jul 26 11:09:07 2021 +0100
Branches: soc-2021-knife-tools
https://developer.blender.org/rB411c9b9eb22b40d09c614783070a51fc6301b99c

Fix: Knife Project crash in multi-object edit mode

The commit which added multi-object edit mode support for the knife tool (bd6587cb524b24f3f43c4dde2a5eab845f54d82c) broke knife project in multi-object edit mode.

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

M	source/blender/editors/mesh/editmesh_knife.c

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

diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 86cc779ec3e..26d627cf0b6 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -3832,6 +3832,24 @@ static void knifetool_finish_ex(KnifeTool_OpData *kcd)
   knifetool_free_bmbvh(kcd);
 }
 
+static void knifetool_finish_single_ex(KnifeTool_OpData *kcd, Object *ob)
+{
+  knife_switch_object(kcd, ob);
+
+  knife_make_cuts(kcd);
+
+  EDBM_selectmode_flush(kcd->em);
+  EDBM_update(kcd->ob->data,
+              &(const struct EDBMUpdate_Params){
+                  .calc_looptri = true,
+                  .calc_normals = true,
+                  .is_destructive = true,
+              });
+
+  /* Re-tessellating makes this invalid, don't use again by accident. */
+  knifetool_free_bmbvh(kcd);
+}
+
 static void knifetool_finish(wmOperator *op)
 {
   KnifeTool_OpData *kcd = op->customdata;
@@ -4410,102 +4428,106 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
 
   /* Finish. */
   {
-    knifetool_finish_ex(kcd);
+    Object *ob;
+    for (int b = 0; b < kcd->bases_len; b++) {
+      ob = kcd->bases[b]->object;
+      knifetool_finish_single_ex(kcd, ob);
 
-    /* Tag faces inside! */
-    if (use_tag) {
-      BMesh *bm = kcd->em->bm;
-      float projmat[4][4];
+      /* Tag faces inside! */
+      if (use_tag) {
+        BMesh *bm = kcd->em->bm;
+        float projmat[4][4];
 
-      BMEdge *e;
-      BMIter iter;
+        BMEdge *e;
+        BMIter iter;
 
-      bool keep_search;
+        bool keep_search;
 
-      /* Freed on knifetool_finish_ex, but we need again to check if points are visible. */
-      if (kcd->cut_through == false) {
-        knifetool_init_bmbvh(kcd);
-      }
+        /* Freed on knifetool_finish_ex, but we need again to check if points are visible. */
+        if (kcd->cut_through == false) {
+          knifetool_init_bmbvh(kcd);
+        }
 
-      ED_view3d_ob_project_mat_get(kcd->region->regiondata, kcd->ob, projmat);
+        ED_view3d_ob_project_mat_get(kcd->region->regiondata, kcd->ob, projmat);
 
-      /* Use face-loop tag to store if we have intersected. */
+        /* Use face-loop tag to store if we have intersected. */
 #define F_ISECT_IS_UNKNOWN(f) BM_elem_flag_test(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
 #define F_ISECT_SET_UNKNOWN(f) BM_elem_flag_enable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
 #define F_ISECT_SET_OUTSIDE(f) BM_elem_flag_disable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
-      {
-        BMFace *f;
-        BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
-          F_ISECT_SET_UNKNOWN(f);
-          BM_elem_flag_disable(f, BM_ELEM_TAG);
-        }
-      }
-
-      /* Tag all faces linked to cut edges. */
-      BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
-        /* Check are we tagged?, then we are an original face. */
-        if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
+        {
           BMFace *f;
-          BMIter fiter;
-          BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
-            float cent[3], cent_ss[2];
-            BM_face_calc_point_in_face(f, cent);
-            knife_project_v2(kcd, cent, cent_ss);
-            if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
-              BM_elem_flag_enable(f, BM_ELEM_TAG);
-            }
+          BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+            F_ISECT_SET_UNKNOWN(f);
+            BM_elem_flag_disable(f, BM_ELEM_TAG);
           }
         }
-      }
-
-      /* Expand tags for faces which are not cut, but are inside the polys. */
-      do {
-        BMFace *f;
-        keep_search = false;
-        BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
-          if (BM_elem_flag_test(f, BM_ELEM_TAG) == false && (F_ISECT_IS_UNKNOWN(f))) {
-            /* Am I connected to a tagged face via an un-tagged edge
-             * (ie, not across a cut)? */
-            BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
-            BMLoop *l_iter = l_first;
-            bool found = false;
-
-            do {
-              if (BM_elem_flag_test(l_iter->e, BM_ELEM_TAG) != false) {
-                /* Now check if the adjacent faces is tagged. */
-                BMLoop *l_radial_iter = l_iter->radial_next;
-                if (l_radial_iter != l_iter) {
-                  do {
-                    if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
-                      found = true;
-                    }
-                  } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter &&
-                           (found == false));
-                }
-              }
-            } while ((l_iter = l_iter->next) != l_first && (found == false));
 
-            if (found) {
+        /* Tag all faces linked to cut edges. */
+        BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+          /* Check are we tagged?, then we are an original face. */
+          if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
+            BMFace *f;
+            BMIter fiter;
+            BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
               float cent[3], cent_ss[2];
               BM_face_calc_point_in_face(f, cent);
               knife_project_v2(kcd, cent, cent_ss);
-              if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) &&
-                  edbm_mesh_knife_point_isect(polys, cent_ss)) {
+              if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
                 BM_elem_flag_enable(f, BM_ELEM_TAG);
-                keep_search = true;
-              }
-              else {
-                /* Don't lose time on this face again, set it as outside. */
-                F_ISECT_SET_OUTSIDE(f);
               }
             }
           }
         }
-      } while (keep_search);
+
+        /* Expand tags for faces which are not cut, but are inside the polys. */
+        do {
+          BMFace *f;
+          keep_search = false;
+          BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+            if (BM_elem_flag_test(f, BM_ELEM_TAG) == false && (F_ISECT_IS_UNKNOWN(f))) {
+              /* Am I connected to a tagged face via an un-tagged edge
+               * (ie, not across a cut)? */
+              BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+              BMLoop *l_iter = l_first;
+              bool found = false;
+
+              do {
+                if (BM_elem_flag_test(l_iter->e, BM_ELEM_TAG) != false) {
+                  /* Now check if the adjacent faces is tagged. */
+                  BMLoop *l_radial_iter = l_iter->radial_next;
+                  if (l_radial_iter != l_iter) {
+                    do {
+                      if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
+                        found = true;
+                      }
+                    } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter &&
+                             (found == false));
+                  }
+                }
+              } while ((l_iter = l_iter->next) != l_first && (found == false));
+
+              if (found) {
+                float cent[3], cent_ss[2];
+                BM_face_calc_point_in_face(f, cent);
+                knife_project_v2(kcd, cent, cent_ss);
+                if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) &&
+                    edbm_mesh_knife_point_isect(polys, cent_ss)) {
+                  BM_elem_flag_enable(f, BM_ELEM_TAG);
+                  keep_search = true;
+                }
+                else {
+                  /* Don't lose time on this face again, set it as outside. */
+                  F_ISECT_SET_OUTSIDE(f);
+                }
+              }
+            }
+          }
+        } while (keep_search);
 
 #undef F_ISECT_IS_UNKNOWN
 #undef F_ISECT_SET_UNKNOWN
 #undef F_ISECT_SET_OUTSIDE
+      }
     }
 
     knifetool_exit_ex(C, kcd);



More information about the Bf-blender-cvs mailing list