Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / mesh / editmesh_path.c
index eccc15bf83fa796bb1512d7cdf3cbcab1b229f5c..68157dab4e00a530ca3540e268ae3bd34c877bf2 100644 (file)
@@ -29,6 +29,8 @@
  *  \ingroup edmesh
  */
 
+#include "MEM_guardedalloc.h"
+
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
 #include "DNA_mesh_types.h"
@@ -41,6 +43,7 @@
 #include "BLI_math.h"
 #include "BLI_linklist.h"
 
+#include "BKE_layer.h"
 #include "BKE_context.h"
 #include "BKE_editmesh.h"
 #include "BKE_report.h"
@@ -59,6 +62,8 @@
 #include "bmesh.h"
 #include "bmesh_tools.h"
 
+#include "DEG_depsgraph.h"
+
 #include "mesh_intern.h"  /* own include */
 
 /* -------------------------------------------------------------------- */
@@ -126,10 +131,9 @@ static void verttag_set_cb(BMVert *v, bool val, void *user_data_v)
 }
 
 static void mouse_mesh_shortest_path_vert(
-        Scene *scene, const struct PathSelectParams *op_params,
+        Scene *UNUSED(scene), Object *obedit, const struct PathSelectParams *op_params,
         BMVert *v_act, BMVert *v_dst)
 {
-       Object *obedit = scene->obedit;
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
        BMesh *bm = em->bm;
 
@@ -287,11 +291,11 @@ static void edgetag_set_cb(BMEdge *e, bool val, void *user_data_v)
        }
 }
 
-static void edgetag_ensure_cd_flag(Scene *scene, Mesh *me)
+static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode)
 {
        BMesh *bm = me->edit_btmesh->bm;
 
-       switch (scene->toolsettings->edge_mode) {
+       switch (edge_mode) {
                case EDGE_MODE_TAG_CREASE:
                        BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
                        break;
@@ -314,10 +318,9 @@ static void edgetag_ensure_cd_flag(Scene *scene, Mesh *me)
 
 /* since you want to create paths with multiple selects, it doesn't have extend option */
 static void mouse_mesh_shortest_path_edge(
-        Scene *scene, const struct PathSelectParams *op_params,
+        Scene *scene, Object *obedit, const struct PathSelectParams *op_params,
         BMEdge *e_act, BMEdge *e_dst)
 {
-       Object *obedit = scene->obedit;
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
        BMesh *bm = em->bm;
 
@@ -326,7 +329,7 @@ static void mouse_mesh_shortest_path_edge(
        Mesh *me = obedit->data;
        bool is_path_ordered = false;
 
-       edgetag_ensure_cd_flag(scene, obedit->data);
+       edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
 
        if (e_act && (e_act != e_dst)) {
                if (op_params->use_fill) {
@@ -385,7 +388,7 @@ static void mouse_mesh_shortest_path_edge(
        }
        else {
                const bool is_act = !edgetag_test_cb(e_dst, &user_data);
-               edgetag_ensure_cd_flag(scene, obedit->data);
+               edgetag_ensure_cd_flag(obedit->data, op_params->edge_mode);
                edgetag_set_cb(e_dst, is_act, &user_data); /* switch the edge option */
        }
 
@@ -461,10 +464,9 @@ static void facetag_set_cb(BMFace *f, bool val, void *user_data_v)
 }
 
 static void mouse_mesh_shortest_path_face(
-        Scene *scene, const struct PathSelectParams *op_params,
+        Scene *UNUSED(scene), Object *obedit, const struct PathSelectParams *op_params,
         BMFace *f_act, BMFace *f_dst)
 {
-       Object *obedit = scene->obedit;
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
        BMesh *bm = em->bm;
 
@@ -557,7 +559,7 @@ static void mouse_mesh_shortest_path_face(
  * \{ */
 
 static bool edbm_shortest_path_pick_ex(
-        Scene *scene, const struct PathSelectParams *op_params,
+        Scene *scene, Object *obedit, const struct PathSelectParams *op_params,
         BMElem *ele_src, BMElem *ele_dst)
 {
 
@@ -565,15 +567,15 @@ static bool edbm_shortest_path_pick_ex(
                /* pass */
        }
        else if (ele_src->head.htype == BM_VERT) {
-               mouse_mesh_shortest_path_vert(scene, op_params, (BMVert *)ele_src, (BMVert *)ele_dst);
+               mouse_mesh_shortest_path_vert(scene, obedit, op_params, (BMVert *)ele_src, (BMVert *)ele_dst);
                return true;
        }
        else if (ele_src->head.htype == BM_EDGE) {
-               mouse_mesh_shortest_path_edge(scene, op_params, (BMEdge *)ele_src, (BMEdge *)ele_dst);
+               mouse_mesh_shortest_path_edge(scene, obedit, op_params, (BMEdge *)ele_src, (BMEdge *)ele_dst);
                return true;
        }
        else if (ele_src->head.htype == BM_FACE) {
-               mouse_mesh_shortest_path_face(scene, op_params, (BMFace *)ele_src, (BMFace *)ele_dst);
+               mouse_mesh_shortest_path_face(scene, obedit, op_params, (BMFace *)ele_src, (BMFace *)ele_dst);
                return true;
        }
 
@@ -652,7 +654,7 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
        op_params.track_active = track_active;
        op_params.edge_mode = vc.scene->toolsettings->edge_mode;
 
-       if (!edbm_shortest_path_pick_ex(vc.scene, &op_params, ele_src, ele_dst)) {
+       if (!edbm_shortest_path_pick_ex(vc.scene, vc.obedit, &op_params, ele_src, ele_dst)) {
                return OPERATOR_PASS_THROUGH;
        }
 
@@ -689,7 +691,7 @@ static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op)
        op_params.track_active = true;
        op_params.edge_mode = scene->toolsettings->edge_mode;
 
-       if (!edbm_shortest_path_pick_ex(scene, &op_params, ele_src, ele_dst)) {
+       if (!edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst)) {
                return OPERATOR_CANCELLED;
        }
 
@@ -730,67 +732,87 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot)
 static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
 {
        Scene *scene = CTX_data_scene(C);
-       Object *ob = CTX_data_edit_object(C);
-       BMEditMesh *em = BKE_editmesh_from_object(ob);
-       BMesh *bm = em->bm;
-       BMIter iter;
-       BMEditSelection *ese_src, *ese_dst;
-       BMElem *ele_src = NULL, *ele_dst = NULL, *ele;
+       bool found_valid_elements = false;
+
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       uint objects_len = 0;
+       Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+       for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+               Object *obedit = objects[ob_index];
+               BMEditMesh *em = BKE_editmesh_from_object(obedit);
+               BMesh *bm = em->bm;
+               BMIter iter;
+               BMEditSelection *ese_src, *ese_dst;
+               BMElem *ele_src = NULL, *ele_dst = NULL, *ele;
+
+               if ((em->bm->totvertsel == 0) &&
+                   (em->bm->totedgesel == 0) &&
+                   (em->bm->totfacesel == 0))
+               {
+                       continue;
+               }
 
-       /* first try to find vertices in edit selection */
-       ese_src = bm->selected.last;
-       if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype  == ese_dst->htype)) {
-               ele_src = ese_src->ele;
-               ele_dst = ese_dst->ele;
-       }
-       else {
-               /* if selection history isn't available, find two selected elements */
-               ele_src = ele_dst = NULL;
-               if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) {
-                       BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
-                               if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
-                                       if      (ele_src == NULL) ele_src = ele;
-                                       else if (ele_dst == NULL) ele_dst = ele;
-                                       else                      break;
+               /* first try to find vertices in edit selection */
+               ese_src = bm->selected.last;
+               if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype  == ese_dst->htype)) {
+                       ele_src = ese_src->ele;
+                       ele_dst = ese_dst->ele;
+               }
+               else {
+                       /* if selection history isn't available, find two selected elements */
+                       ele_src = ele_dst = NULL;
+                       if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) {
+                               BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+                                       if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+                                               if      (ele_src == NULL) ele_src = ele;
+                                               else if (ele_dst == NULL) ele_dst = ele;
+                                               else                      break;
+                                       }
                                }
                        }
-               }
 
-               if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) {
-                       ele_src = NULL;
-                       BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
-                               if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
-                                       if      (ele_src == NULL) ele_src = ele;
-                                       else if (ele_dst == NULL) ele_dst = ele;
-                                       else                      break;
+                       if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) {
+                               ele_src = NULL;
+                               BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+                                       if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+                                               if      (ele_src == NULL) ele_src = ele;
+                                               else if (ele_dst == NULL) ele_dst = ele;
+                                               else                      break;
+                                       }
                                }
                        }
-               }
 
-               if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) {
-                       ele_src = NULL;
-                       BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
-                               if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
-                                       if      (ele_src == NULL) ele_src = ele;
-                                       else if (ele_dst == NULL) ele_dst = ele;
-                                       else                      break;
+                       if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) {
+                               ele_src = NULL;
+                               BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+                                       if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+                                               if      (ele_src == NULL) ele_src = ele;
+                                               else if (ele_dst == NULL) ele_dst = ele;
+                                               else                      break;
+                                       }
                                }
                        }
                }
-       }
 
-       if (ele_src && ele_dst) {
-               struct PathSelectParams op_params;
-               path_select_params_from_op(op, &op_params);
+               if (ele_src && ele_dst) {
+                       struct PathSelectParams op_params;
+                       path_select_params_from_op(op, &op_params);
 
-               edbm_shortest_path_pick_ex(scene, &op_params, ele_src, ele_dst);
+                       edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst);
 
-               return OPERATOR_FINISHED;
+                       found_valid_elements = true;
+               }
        }
-       else {
-               BKE_report(op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected");
+       MEM_freeN(objects);
+
+       if (!found_valid_elements) {
+               BKE_report(op->reports,
+                          RPT_WARNING,
+                          "Path selection requires two matching elements to be selected");
                return OPERATOR_CANCELLED;
        }
+
+       return OPERATOR_FINISHED;
 }
 
 void MESH_OT_shortest_path_select(wmOperatorType *ot)